Stack technique
Ce que le projet utilise, et pourquoi. Les décisions détaillées sont dans decisions/ ; cette page sert à s'orienter.
Socle
| Brique | Version | Rôle |
|---|---|---|
| Node | 22 | Exécution |
| pnpm | 10 | Paquets. pnpm-workspace.yaml existe sans clé packages: : ce n'est pas un monorepo |
| Next.js | 16.4 | App Router, pages statiques, Turbopack |
| React | 19 | — |
| Mantine | 7.17 | Composants d'interface ; thème calculé depuis la charte d'instance |
| Pagefind | 1.4 | Recherche plein texte dans le navigateur, index construit après le build |
| Zod | — | Contrats de données, aux frontières (src/contracts/) |
| Vitest, Playwright, axe | — | Tests unitaires, bout en bout, accessibilité |
| Storybook | 10 | Catalogue de composants (design-system.md) |
| Recharts | 3 | Graphiques du tableau de bord interne |
| Biome | 2.5 | Lint (règles React, Next, TypeScript) ; le formatage reste à Prettier |
| Lefthook | 2 | Contrôles avant commit et avant push |
Pas de base de données, pas de serveur applicatif : tout est calculé au build. Les pages lisent des JSON sur le disque, la recherche s'exécute chez le visiteur.
Dossiers
| Dossier | Contenu |
|---|---|
instances/<id>/ | Configuration d'un établissement : charte, périmètre, groupes, thématiques |
scripts/data/ | Moisson (extract/), fusion (build.ts), sondes, gel (freeze.ts), exports |
src/config/ | Schéma Zod et registre des instances |
src/contracts/ | Modèle publié (public.ts) : ce que la chaîne écrit, ce que les pages lisent |
src/server/ | Lecture des données publiées, observabilité. Interdit d'import côté client |
src/app/[lang]/ | Pages publiques, français sans préfixe, anglais sous /en |
src/app/admin/ | Tableau de bord interne de couverture, construit seulement sur demande |
src/features/ | Recherche, analytics, observabilité |
src/theme/ | Thème Mantine calculé, tokens.css |
packages/ | Paquets autonomes, réutilisables hors du projet |
infra/analytics/ | Pile d'analytics auto-hébergée (Docker Compose) |
ops/observability/ | Prometheus, Grafana, alertes |
Les trois paquets
Autonomes, sans import du projet : copier le dossier suffit à les réutiliser. Résolus par alias
@workspace/* dans tsconfig.json, sans clé packages: dans pnpm — le cahier des charges
interdisait la conversion en monorepo.
| Paquet | Ce qu'il fait | Ce qu'il ne fait pas |
|---|---|---|
packages/analytics | Collecte : catalogue typé, consentement, files par fournisseur, adaptateurs Umami/Matomo/Rybbit | Aucun rendu |
packages/observability | OpenTelemetry vers OpenObserve, caviardage | Aucun rendu |
packages/analytics-ui | Visualisation : Mantine + Recharts | Aucune collecte |
La chaîne de données
Code
data/raw/ n'est pas versionné (2,1 Go, et il contient des noms de personnes). Les JSON
publiés le sont : 18 Mo, parce que Vercel construit le site à partir d'eux et ne moissonne pas
(exploitation/deploiement-vercel.md).
Commandes
| Commande | Durée | Rôle |
|---|---|---|
pnpm data:extract | ~20 min | Moisson des 11 sources → data/raw/ |
pnpm data:build | ~45 s | Fusion et publication → data/public/ |
pnpm data:freeze / data:verify | < 5 s | Fige et vérifie la référence (tests/reference/) |
pnpm data:export | < 5 s | Tableurs pour les validations externes |
pnpm build:<instance> | ~12 min | 23 696 pages (Saclay) puis index Pagefind |
pnpm search:eval <inst> <url> | ~2 min | 20 requêtes de référence → score |
pnpm a11y <url> [chemins…] | ~1 min | axe, WCAG 2.1 AA |
pnpm telemetry:test[:app] | ~2 min | Fumée analytics, paquets puis application |
make check | ~1 min | Formatage, lint, typage, 75 tests |
pnpm storybook | — | Catalogue de composants |
Marque blanche
Une instance = un fichier de configuration et deux logos. La charte tient en quatre couleurs et deux polices ; les échelles, les variantes accessibles et les jetons CSS en sont calculés. Le périmètre s'exprime avec les identifiants de l'établissement dans chaque source.
Procédure complète : architecture/marque-blanche.md. Deux instances sont livrées : Paris-Saclay, et Paris 1 en démonstration.