- Remplacement intégral index.css par palette Charcoal (DESIGN_SYSTEM.md v2.0)
- Dark = thème par défaut, .light = override via @custom-variant light
- Sidebar navy #0C1528 permanent (identique dark+light)
- Script anti-FOUC inline dans index.html
- Layout : radial-gradient sur <main>, sidebar 230px, max-w-[1100px]
- Renommage tokens Boréal→Charcoal sur ~45 composants
- Inversion dark: → baseline + light: sur primitives shadcn
- Fix logo blanc forcé dans sidebar
- ADR 006 mis à jour
Typecheck: OK · Tests: 122/122 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
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_modulesqui 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)
- Casse un
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 <html> active le mode clair en override. Configuré via :
@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)
@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 <html class="light"> */
.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 :
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.mdliste 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
- Mettre à jour
ARCHITECTURE.md §2avec les versions ci-dessus (réalisé en session actuelle) - Mettre à jour
ONBOARDING.mdpour référencer React 19 et Tailwind 4 dans les ressources (à faire) - Aucune action sur
TESTS_AUTOMATISES.md— Vitest fonctionne identiquement - 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 — support officiel confirmé
- React 19 Upgrade Guide
- Tailwind CSS v4.0
ARCHITECTURE.md§2 (mis à jour en parallèle)