# ADR 006 — Stack frontend : versions 2026 (React 19, Vite 8, TypeScript 6, Tailwind 4, RR7) **Statut :** Accepté — mis à jour Sprint 0.5 **Date :** 2026-04-17 **Décideur :** Hermann **Contexte :** Révélé par l'état des lieux Claude Code au démarrage du Sprint 0 frontend --- ## Contexte La première version d'`ARCHITECTURE.md` §2 listait une stack basée sur les versions "connues stables" : - React 18 - Vite 5 - TypeScript 5 - Tailwind 3 - React Router v6 L'état des lieux effectué par Claude Code au démarrage du Sprint 0 (2026-04-17) a révélé que le scaffold installé plusieurs semaines auparavant utilisait des versions plus récentes : - React 19.2.4 - Vite 8.0.4 - TypeScript 6.0.2 - Tailwind 4.2.2 - React Router v7.14.1 Cette divergence doit être résolue : soit downgrader le scaffold, soit mettre à jour la documentation. ## Options envisagées ### Option A — Downgrader vers les versions de la doc originale Aligner le scaffold sur React 18, Vite 5, TypeScript 5, Tailwind 3, React Router v6. - **Avantages :** documentation historique respectée, versions "éprouvées" en production. - **Inconvénients :** - Casse un `node_modules` qui fonctionne - Perd l'optimisation du compilateur React 19 (Actions, useOptimistic) - Perd le moteur Oxide de Tailwind 4 (builds 3,5x plus rapides) - Perd le typage strict amélioré de TypeScript 6 - Downgrade effectué pour des raisons qui n'existent plus (les versions récentes sont matures en avril 2026) ### Option B — Mettre à jour la documentation Accepter les versions installées et mettre à jour `ARCHITECTURE.md §2` pour refléter la réalité. - **Avantages :** - Préserve le travail de scaffold déjà fait - Bénéficie des améliorations de performance des versions récentes - Écosystème mature : shadcn/ui supporte complètement Tailwind 4 et React 19 depuis début 2025 - Alignement avec l'écosystème 2026 (les nouveaux tutoriels, docs, et ressources communautaires supposent ces versions) - **Inconvénients :** - Versions légèrement plus récentes = moins de StackOverflow disponible pour les cas exotiques - Mitigation : Claude Opus 4.7 connaît bien ces versions (cf. knowledge cutoff janvier 2026) ### Option C — Hybride Garder React 19, Vite 8, TypeScript 6 mais downgrader Tailwind 4 → 3 pour "compatibilité shadcn/ui classique". - **Avantages :** apparemment plus prudent. - **Inconvénients :** injustifié depuis que shadcn/ui supporte complètement Tailwind 4 avec configuration CSS-first via `@theme`. Ajoute de la complexité sans bénéfice. ## Décision **Option B** — accepter les versions installées et mettre à jour la documentation. ### Stack frontend officielle au 2026-04-17 | Couche | Version | Notes | |---|---|---| | React | 19.2.x | Server Components N/A (SPA pur), Actions et useOptimistic disponibles | | React DOM | 19.2.x | | | Vite | 8.0.x | Moteur Rolldown stable, config simplifiée | | TypeScript | 6.0.x | Typage strict activé (voir tsconfig.app.json) | | Tailwind CSS | 4.2.x | Configuration CSS-first via `@theme`, pas de `tailwind.config.ts` | | `@tailwindcss/vite` | 4.2.x | Plugin Vite officiel (préféré au plugin PostCSS) | | React Router | v7.14.x | Compatible API v6, data loaders disponibles | | Supabase JS | 2.103.x | | ### Dépendances à ajouter lors du scaffold | Package | Rôle | Cf. ADR | |---|---|---| | `@tanstack/react-query` | Cache serveur, refetch, mutations | ARCHITECTURE.md §2 | | `zod` | Validation des inputs formulaires | SECURITY.md SEC-04 | | `react-markdown` | Rendu sécurisé des rapports IA | SECURITY.md SEC-05 | | `class-variance-authority`, `clsx`, `tailwind-merge` | Utilitaires shadcn/ui | — | | `lucide-react` | Icônes (standard shadcn/ui) | — | | Packages `@radix-ui/react-*` | Primitives shadcn/ui (installés à la demande) | — | | `@sentry/react` | Monitoring | TECH_DEBT.md FTD-07 (après MVP) | ### Dépendances de développement | Package | Rôle | |---|---| | `vitest` | Tests unitaires | | `@vitest/coverage-v8` | Couverture | | `@testing-library/react` | Tests React | | `@testing-library/jest-dom` | Matchers DOM | | `@testing-library/user-event` | Simulation user | | `jsdom` | Environnement DOM pour Vitest | | `prettier` | Formatage | | `eslint-config-prettier` | Intégration ESLint ↔ Prettier | ### Configuration Tailwind 4 Pas de `tailwind.config.ts`. La configuration se fait exclusivement dans `src/index.css`. #### Mode thème (mis à jour Sprint DA Charcoal — 2026-04-24) **Dark est le thème par défaut.** Les tokens de contenu (`--color-canvas`, `--color-ink-*`, etc.) sont déclarés en mode dark dans `@theme`. Une classe `.light` sur `` active le mode clair en override. Configuré via : ```css @custom-variant light (&:where(.light, .light *)); ``` Ce variant permet d'écrire `light:bg-surface` dans les composants quand un comportement spécifique au mode clair est requis (ex. primitives shadcn où l'opacité doit être adaptée). #### Tokens @theme (DA Charcoal — validée Sprint DA Charcoal 2026-04-24) ```css @import 'tailwindcss'; @import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap'); @custom-variant light (&:where(.light, .light *)); @theme { /* ── Invariants (identiques dark + light) ── */ /* Sidebar navy permanent */ --color-sidebar-bg: #0C1528; --color-sidebar-border: rgba(255, 255, 255, 0.07); --color-sidebar-text: rgba(255, 255, 255, 0.6); --color-sidebar-text-hover: rgba(255, 255, 255, 0.9); --color-sidebar-text-active: #FFFFFF; --color-sidebar-nav-hover: rgba(255, 255, 255, 0.07); --color-sidebar-nav-active: rgba(255, 255, 255, 0.1); --color-sidebar-section-label: rgba(255, 255, 255, 0.3); /* Brand */ --color-brand: #1B4FD8; --color-brand-hover: #1744B8; --color-brand-active: #13379C; --color-brand-dark: #1740B0; --color-brand-ink: #FFFFFF; /* Semantic (invariants) */ --color-warning: #F59E0B; --color-warning-soft: rgba(245, 158, 11, 0.12); --color-danger: #EF4444; --color-danger-soft: rgba(239, 68, 68, 0.12); /* Typographie */ --font-sans: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif; --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace; /* Rayons (override Tailwind) */ --radius-xs: 6px; --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px; --radius-xl: 20px; --radius-pill: 999px; /* Focus */ --shadow-focus: 0 0 0 3px rgba(27, 79, 216, 0.18); /* ── Dark mode (défaut) ── */ --color-canvas: #111111; --color-surface: rgba(255, 255, 255, 0.035); --color-surface-hover: rgba(255, 255, 255, 0.055); --color-surface-solid: #1E1E1E; --color-surface-raised: #222222; --color-border: rgba(255, 255, 255, 0.06); --color-border-strong: rgba(255, 255, 255, 0.12); --color-ink-primary: #E5E5E5; --color-ink-secondary: rgba(255, 255, 255, 0.55); --color-ink-tertiary: rgba(255, 255, 255, 0.3); --color-ink-inverse: #111111; --color-brand-soft: rgba(27, 79, 216, 0.1); --color-brand-text: #7DA4F0; --color-success: #4ADE80; --color-success-soft: rgba(74, 222, 128, 0.12); --color-topbar-bg: rgba(17, 17, 17, 0.88); --color-gradient-a: rgba(27, 79, 216, 0.05); --color-gradient-b: rgba(27, 79, 216, 0.03); --shadow-card: none; --shadow-raised: none; } /* Light mode — override sur */ .light { --color-canvas: #F3F4F6; --color-surface: #FFFFFF; --color-surface-hover: #F8F9FB; --color-surface-solid: #FFFFFF; --color-surface-raised: #FFFFFF; --color-border: rgba(0, 0, 0, 0.07); --color-border-strong: rgba(0, 0, 0, 0.14); --color-ink-primary: #0F0F1A; --color-ink-secondary: rgba(0, 0, 0, 0.55); --color-ink-tertiary: rgba(0, 0, 0, 0.3); --color-ink-inverse: #FFFFFF; --color-brand-soft: rgba(27, 79, 216, 0.06); --color-brand-text: #1B4FD8; --color-success: #16A34A; --color-success-soft: rgba(22, 163, 74, 0.1); --color-topbar-bg: rgba(243, 244, 246, 0.88); --color-gradient-a: rgba(27, 79, 216, 0.025); --color-gradient-b: rgba(27, 79, 216, 0.01); --shadow-card: 0 1px 2px rgba(15, 18, 32, 0.04), 0 1px 8px rgba(15, 18, 32, 0.03); --shadow-raised: 0 4px 16px rgba(15, 18, 32, 0.06), 0 1px 2px rgba(15, 18, 32, 0.04); } ``` #### Classes Tailwind générées Les tokens `@theme` créent des classes utilitaires directement utilisables : | Token | Classes Tailwind | |---|---| | `--color-canvas` | `bg-canvas`, `text-canvas`, `border-canvas` | | `--color-surface` | `bg-surface`, `border-surface` | | `--color-surface-hover` | `bg-surface-hover` | | `--color-sidebar-bg` | `bg-sidebar-bg` (navy permanent, identique dark+light) | | `--color-ink-primary` | `text-ink-primary` | | `--color-ink-secondary` | `text-ink-secondary` | | `--color-ink-tertiary` | `text-ink-tertiary` | | `--color-brand` | `bg-brand`, `border-brand`, `ring-brand` | | `--color-brand-text` | `text-brand-text` (bleu adapté au fond — `#7DA4F0` dark, `#1B4FD8` light) | | `--color-brand-soft` | `bg-brand-soft` (teinte chip / highlight discret) | | `--color-success-soft`, `-warning-soft`, `-danger-soft` | `bg-success-soft`, etc. | | `--shadow-card`, `--shadow-raised` | `shadow-card`, `shadow-raised` (auto dual-theme : `none` en dark, ombre en light) | | `--shadow-focus` | `shadow-focus` (halo bleu 3px sur `:focus-visible`) | **Conventions critiques :** - `bg-surface` = cards / modals / panels. `bg-canvas` = fond de page. Ne jamais inverser. - `bg-sidebar-bg` = navy permanent — ne change jamais entre dark et light (ancre visuelle de marque). - Utiliser le préfixe `light:` uniquement quand un override spécifique au mode clair est strictement nécessaire (ex. primitives shadcn où l'opacité d'une couleur sémantique diffère). #### Typographie Plus Jakarta Sans chargée via Google Fonts dans `index.html` (preconnect + stylesheet, weights 400/500/600/700). Migration vers auto-hébergement (`@fontsource/plus-jakarta-sans`) après MVP si les performances réseau deviennent un enjeu. ### shadcn/ui avec Tailwind 4 La CLI shadcn/ui supporte Tailwind 4 depuis début 2025 : ```bash npx shadcn@latest init npx shadcn@latest add button dialog form ``` Les composants générés utilisent les conventions Tailwind 4 (pas de `forwardRef`, attributs `data-slot`). Le fichier de configuration reste `components.json` à la racine. ## Conséquences **Positives :** - Pas de perte de travail sur le scaffold existant - Performances optimales (build Tailwind 4 : microsecondes sur builds incrémentaux) - Stack aligné sur l'écosystème 2026 — facile pour un dev externe qui arrivera - Compilateur React 19 apporte des optimisations gratuites **Négatives :** - Les versions récentes peuvent avoir quelques bugs non encore découverts. Mitigation : mise à jour ponctuelle vers la dernière version patch en cas de bug signalé (ex : 19.2.4 → 19.2.5). - Si un dev arrive avec une expertise sur React 17/18 uniquement, courbe d'apprentissage légère. Mitigation : `ONBOARDING.md` liste les ressources officielles pour React 19 et Tailwind 4. **À revisiter si :** - Une faille de sécurité critique apparaît dans une version spécifique - Une incompatibilité bloquante est découverte entre deux packages (peu probable en avril 2026) ## Actions de mise en cohérence 1. Mettre à jour `ARCHITECTURE.md §2` avec les versions ci-dessus (réalisé en session actuelle) 2. Mettre à jour `ONBOARDING.md` pour référencer React 19 et Tailwind 4 dans les ressources (à faire) 3. Aucune action sur `TESTS_AUTOMATISES.md` — Vitest fonctionne identiquement 4. Aucune action sur les ADRs 001-005 — ils ne référencent pas de versions précises ## Références - État des lieux Claude Code du 2026-04-17 - [shadcn/ui Tailwind v4](https://ui.shadcn.com/docs/tailwind-v4) — support officiel confirmé - [React 19 Upgrade Guide](https://react.dev/blog/2024/04/25/react-19) - [Tailwind CSS v4.0](https://tailwindcss.com/blog/tailwindcss-v4) - `ARCHITECTURE.md` §2 (mis à jour en parallèle)