Architecture

Stack technique

Ce que le projet utilise, et pourquoi. Les décisions détaillées sont dans decisions/ ; cette page sert à s'orienter.

Socle

BriqueVersionRôle
Node22Exécution
pnpm10Paquets. pnpm-workspace.yaml existe sans clé packages: : ce n'est pas un monorepo
Next.js16.4App Router, pages statiques, Turbopack
React19—
Mantine7.17Composants d'interface ; thème calculé depuis la charte d'instance
Pagefind1.4Recherche 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é
Storybook10Catalogue de composants (design-system.md)
Recharts3Graphiques du tableau de bord interne
Biome2.5Lint (règles React, Next, TypeScript) ; le formatage reste à Prettier
Lefthook2Contrô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

DossierContenu
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.

PaquetCe qu'il faitCe qu'il ne fait pas
packages/analyticsCollecte : catalogue typé, consentement, files par fournisseur, adaptateurs Umami/Matomo/RybbitAucun rendu
packages/observabilityOpenTelemetry vers OpenObserve, caviardageAucun rendu
packages/analytics-uiVisualisation : Mantine + RechartsAucune collecte

La chaîne de données

Code
11 sources ouvertes data/raw/<instance>/ data/public/<instance>/ RNSR, scanR, HAL, ROR, ──► NDJSON bruts, 2,1 Go ──► JSON publiés, 18 Mo ──► pages Wikidata, ORCID, OpenAIRE, pnpm data:extract pnpm data:build statiques OpenAlex, theses.fr, ≈ 20 min ≈ 45 s annuaire de l'établissement

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

CommandeDuréeRôle
pnpm data:extract~20 minMoisson des 11 sources → data/raw/
pnpm data:build~45 sFusion et publication → data/public/
pnpm data:freeze / data:verify< 5 sFige et vérifie la référence (tests/reference/)
pnpm data:export< 5 sTableurs pour les validations externes
pnpm build:<instance>~12 min23 696 pages (Saclay) puis index Pagefind
pnpm search:eval <inst> <url>~2 min20 requêtes de référence → score
pnpm a11y <url> [chemins…]~1 minaxe, WCAG 2.1 AA
pnpm telemetry:test[:app]~2 minFumée analytics, paquets puis application
make check~1 minFormatage, 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.