---
name: debug-frontend
description: Diagnose and auto-fix SmartStack React+Vite frontend failures
group: DEBUG
allowed-tools: [Read, Edit, Write, Glob, Grep, Bash]  # Bash: diagnostic commands
---

# Skill: Debug Frontend — React + Vite + SmartStack

## Contexte

Tu opères dans le worktree d'un projet SmartStack client. Le frontend est un projet
React 19 + Vite 7 dans `web/{appcode}-web/`, avec `@atlashub/smartstack` comme lib.
Le dev-runner du Studio spawn `npm run dev -- --port {port} --host localhost` avec
`env.VITE_API_URL=http://localhost:{apiPort}`.

## Plan d'exécution

### Étape 1 — Scaffold intégrité

Vérifier la présence des 5 fichiers critiques :

```bash
cd web/{appcode}-web
ls index.html src/main.tsx src/App.tsx package.json vite.config.ts 2>&1
```

| Fichier manquant | Action |
|------------------|--------|
| `index.html` | **CRITIQUE**. Créer avec `<div id="root"></div>` + `<script type="module" src="/src/main.tsx">` |
| `src/main.tsx` | Générer depuis template avec `BrowserRouter > SmartStackProvider config={{apiUrl: import.meta.env.VITE_API_URL}}` |
| `src/App.tsx` | Créer avec `<DynamicRouter />` de `@atlashub/smartstack` |
| `package.json` | Projet cassé — user doit relancer `ss init` |
| `vite.config.ts` | Créer avec plugin React + proxy `/api` → backend |

### Étape 2 — Dépendances

```bash
ls node_modules/@atlashub/smartstack/package.json 2>&1
```

Si manquant :
```bash
npm install
```

### Étape 3 — Config main.tsx

Ouvrir `src/main.tsx` et vérifier cette structure exacte :

```tsx
import { BrowserRouter } from 'react-router-dom';
import { SmartStackProvider } from '@atlashub/smartstack';

const config = {
  apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:5142',
  appName: '{AppCode}',
};

createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <SmartStackProvider config={config}>
      <App />
    </SmartStackProvider>
  </BrowserRouter>
);
```

**Erreurs courantes** :

| Symptôme runtime | Cause | Fix |
|------------------|-------|-----|
| `useLocation() may be used only in the context of a <Router> component` | `<BrowserRouter>` manquant | Wrap `<SmartStackProvider>` dans `<BrowserRouter>` |
| `Cannot read properties of undefined (reading 'extensions')` | `config` prop absente sur `<SmartStackProvider>` | Passer `config={{apiUrl: ...}}` |
| `Cannot read properties of undefined (reading 'apiUrl')` | Config passée mais `apiUrl` manquant | Ajouter `apiUrl: import.meta.env.VITE_API_URL` |
| `You cannot render a <Router> inside another <Router>` | Double BrowserRouter (main.tsx + App.tsx) | Retirer le second |

### Étape 4 — Lancement Vite

```bash
npm run dev -- --port 3000 --host localhost
```

**Analyser la sortie** :

| Ligne Vite | Interprétation |
|------------|----------------|
| `Port 3000 is in use, trying another one...` | Port occupé, Vite bump. L'URL Studio sera désynchronisée. |
| `Local:   http://localhost:3000/` | ✓ Vite écoute sur ce port |
| `error when starting dev server: [vite]...` | Bug config Vite — chercher `vite.config.ts` |
| `Failed to resolve import "..."` | Package manquant — `npm install` |

### Étape 5 — Vérifier le rendu

```bash
curl -fsS http://localhost:3000/
```

Attendu : HTML qui contient `<div id="root"></div>` et le script main.tsx.

| Réponse | Diagnostic |
|---------|-----------|
| HTTP 200 + HTML avec `#root` | ✓ OK |
| HTTP 404 | `index.html` absent à la racine du projet web (PAS dans public/) |
| ECONNREFUSED | Vite ne tourne pas — reboucler sur étape 4 |
| HTML sans `#root` | `index.html` corrompu — régénérer |

### Étape 6 — Check erreurs React en runtime

Si la page charge mais l'app ne s'affiche pas :
1. Ouvrir les DevTools du navigateur (ou parser les logs frontend)
2. Chercher les messages rouges d'erreur
3. Appliquer les fixes du tableau "Erreurs courantes" ci-dessus

### Étape 7 — Page blanche (silent spinner / empty render)

Bug le plus fréquent en SmartStack : la page charge (HTTP 200, HTML avec `#root`),
aucun message d'erreur console, mais l'écran reste vide OU affiche un spinner infini.
Cause quasi systématique : `DynamicRouter` ne résout pas le `componentKey` retourné
par l'API de navigation vers un composant enregistré.

#### Diagnostic en 4 contrôles

```bash
# 1. L'API de navigation répond correctement ?
curl -fsS http://localhost:{apiPort}/api/navigation/menu | head -80
```

Attendu : JSON avec `applications[].modules[].sections[].componentKey` renseignés.
Si le champ `componentKey` est vide/null ou le JSON est `{}` → problème backend
(seed pas lancé, user pas connecté, tenant incorrect). Aller à `debug/backend`.

```bash
# 2. Le registry est bien importé dans main.tsx ?
grep -n "componentRegistry\|Registry" web/{appcode}-web/src/main.tsx
```

Attendu : au moins une ligne `import './extensions/{module}Registry';` (ou équivalent)
AVANT `createRoot(...).render(...)`. Si absent → le PageRegistry est vide au boot,
DynamicRouter ne trouve aucune page.

```bash
# 3. Les fichiers Registry existent et appellent PageRegistry.register() ?
ls web/{appcode}-web/src/extensions/*Registry*.ts* 2>&1
grep -l "PageRegistry.register" web/{appcode}-web/src/extensions/ 2>&1
```

Attendu : un fichier par module, chacun contenant plusieurs lignes
`PageRegistry.register('{app}.{module}.{section}[.{view}]', {PageName});`.
Si le fichier existe mais n'a aucun `register()` → CLI de scaffold-routes
n'a pas tourné ou a échoué silencieusement.

```bash
# 4. Les clés registrées correspondent-elles aux componentKey de l'API ?
curl -fsS http://localhost:{apiPort}/api/navigation/menu \
  | grep -oE '"componentKey":\s*"[^"]+"' | sort -u
grep -hE "PageRegistry.register\('[^']+'" web/{appcode}-web/src/extensions/*.ts \
  | sed -E "s/.*register\('([^']+)'.*/\1/" | sort -u
```

Comparer les deux listes. Toute clé présente dans l'API mais absente du registry
= page blanche garantie pour ce chemin. L'inverse (clé registrée mais pas en API)
= page déclarée mais jamais accessible via la navigation (pas critique mais
gaspillage).

#### Tableau de diagnostic

| Symptôme | Cause probable | Fix |
|----------|----------------|-----|
| Écran blanc sur toute l'app, aucune erreur console | `import './extensions/*Registry'` absent de `main.tsx` | Ajouter l'import AVANT `render()` |
| Écran blanc sur une route précise, les autres OK | La clé `{app}.{module}.{section}` n'est pas dans un `PageRegistry.register(...)` | Relancer `scaffold-routes` pour ce module |
| Spinner infini sur une route, console muet | Mismatch de casse/tiret entre `componentKey` API et clé registrée | Regénérer les 2 côtés (seed + routes) depuis la même spec |
| `/api/navigation/menu` renvoie `{}` ou 401 | Seed pas lancé ou auth non établie | `debug/backend` |
| Route avec `/:id` affiche vide mais route liste OK | Page `.detail` pas enregistrée ou composant utilise `:userId` au lieu de `:id` | Vérifier la clé `{...}.detail` + `useParams<{ id: string }>()` |
| `TypeError: Cannot read properties of undefined (reading 'default')` | `lazy(() => import(...))` résout vers module sans default ni named export | Utiliser la forme `lazy(() => import().then(m => ({ default: m.Named ?? m.default })))` |

#### Vérification finale

Après correction, recharger la page et vérifier en console navigateur :
```
PageRegistry.list() // doit retourner un Array non-vide
```

Si le registry expose cette méthode de debug, confirmer que la clé attendue
y figure. Sinon, ajouter un `console.log('registry size', ...)` dans le
fichier Registry incriminé, recompiler, revalider.

## Fichiers clés

```
web/{appcode}-web/
├── index.html              # ⚠ OBLIGATOIRE à la racine — pas dans public/
├── vite.config.ts          # plugin React + server.port + proxy /api
├── package.json            # deps: react, react-dom, react-router-dom, @atlashub/smartstack
├── src/
│   ├── main.tsx            # BrowserRouter > SmartStackProvider config={...} > App
│   ├── App.tsx             # <DynamicRouter />
│   └── index.css           # Styles globaux (Tailwind)
└── .env.development        # VITE_API_URL (écrasé au runtime par le dev-runner)
```

## Validation finale

Avant de dire "fixé" :
1. `curl http://localhost:3000/` → HTTP 200 + HTML avec `#root` et script module
2. Aucune erreur rouge dans le stdout Vite
3. Si possible, tester un appel API : `curl http://localhost:3000/api/health` (via proxy Vite)

## Règles invariantes

- **Ne jamais** supprimer `index.html` sans avoir un remplaçant
- **Ne jamais** installer de packages sans validation explicite
- **Ne pas toucher** aux fichiers `.bak` (backups d'auto-repair)
- **VITE_API_URL** est injecté par le dev-runner — ne pas le hardcoder en prod
- Après fix : relancer `npm run dev` et re-vérifier
