# Stack Technique & Dépendances

Versions : plage déclarée dans les `package.json`, et entre parenthèses la version résolue dans `pnpm-lock.yaml` lorsqu'elle diffère utilement.

## 🧱 Commun

- **Runtime** : Node.js 24 (`.nvmrc` ; au moins 24.11 selon les `engines` du `package.json` racine). La CI lit `.nvmrc`, les images Docker partent de `node:24-alpine`, et le site comme la documentation déclarent `24.x` à Vercel.
- **Langage** : TypeScript 5 (5.9.3).
- **Gestionnaire de paquets** : pnpm 8 (`packageManager: pnpm@8.15.0`) ; la CI utilise pnpm 9.
- **Monorepo** : pnpm workspaces + Turborepo 2.
- **Tests** : Vitest 1 (API et ingestion ; côté frontend, seul le proxy `/api/v1` est testé).
- **Logs** : pino 8.

## ⚡ API (`apps/api`)

- **Framework** : Fastify 4 (4.29.1), avec `@fastify/compress`, `@fastify/cors`, `@fastify/helmet`, `@fastify/rate-limit`, `@fastify/swagger` et `@fastify/swagger-ui`.
- **ORM** : Prisma 5 (5.22.0).
- **Validation** : Zod 3.
- **Cache et limitation de débit** : Redis, via ioredis.
- **Recherche** : requêtes PostgreSQL par Prisma (`contains`, insensible à la casse), puis classement applicatif par similarité Jaro-Winkler (`apps/api/src/utils/fuzzy-search.ts`). Aucun moteur de recherche dédié.

## 💻 Frontend (`apps/web`)

- **Framework** : Next.js 14.0.4 (App Router), React 18.
- **Styles** : Tailwind CSS 3, `class-variance-authority`, `tailwind-merge`, `tailwindcss-animate`, thème clair et sombre avec `next-themes`.
- **Données** : TanStack Query 5 ; les appels du navigateur passent par un proxy Next (`app/api/v1/[...path]/route.ts`) qui relaie vers l'API.
- **Graphiques** : Recharts 2.
- **Icônes et animations** : lucide-react, framer-motion.
- **Mesure d'audience** : Plausible (sans cookie).

## 📥 Ingestion (`services/ingestion`)

- **CLI** : commander 11.
- **Téléchargement et lecture** : axios, cheerio (HTML), xml2js (XML), csv-parse (CSV), tar-stream (archives de la base LEGI), lecteur XLSX maison (`src/utils/xlsx.ts`), `pdftotext` de poppler-utils pour les comptes rendus de commission publiés en PDF.
- **Concurrence** : p-limit, limiter.
- **Références juridiques** : [@tricoteuses/tisseuse](https://www.npmjs.com/package/@tricoteuses/tisseuse) (AGPL-3.0, comme CLAIR) repère les textes et articles de loi cités dans le dispositif des amendements ; la résolution vers Légifrance passe par notre index de la base LEGI.
- **Build** : tsup (CJS + ESM) ; exécution en développement avec tsx.
- **IA** : API Mistral (`mistral-small-latest` pour la génération, `mistral-embed` pour le classement des liens de contexte), Tavily (recherche ciblée sur vie-publique.fr).

## 📚 Documentation (`docs`)

- **Portail** : Zudoku 0.86 ; recherche plein texte par Pagefind.
- **Référence de l'API** : la spécification OpenAPI générée par l'API de production (`https://api.clair.vote/docs/json`), téléchargée à chaque build dans `docs/public/openapi.json` (fichier ignoré par git).

## 🌐 Infrastructure

| Élément | Développement local | Production |
| :--- | :--- | :--- |
| PostgreSQL | 16 (`postgres:16-alpine`, `docker-compose.yml`) | 17 (image Railway `postgres-ssl:17`) |
| Redis | 7 (`redis:7-alpine`) | 8.2.1 |
| Frontend | `next dev` sur le port 3000 | Vercel, région `cdg1` (Paris) |
| API | `tsx watch` sur le port 3001 | Railway, image construite depuis le `Dockerfile` racine |
| Documentation | `zudoku dev` sur le port 3002 | Vercel (`docs.clair.vote`) |
| Ingestion | CLI lancée à la main | Railway, deux services planifiés (voir [Déploiement](/guide/guide-developpeur/deploiement-production)) |
| CI | | GitHub Actions : lint, tests, build (le `type-check` est désactivé en CI) |
