Retour au Blog
tech/

Le site web est la démo

Comment nous avons construit un site IA frugal et souverain : modèles bi-niveau, secrets Infisical, Docker Hub et Hugging Face pour Wagmi, garde-fous loi IA, et une stack sous 100 $/mois.

Ce site est la démo. Pas une vitrine à côté du produit : le site que vous lisez est la preuve — architecture, sécurité, économie de l’inférence, discipline réglementaire — livrés dans un seul artefact. Il a été codé à la main avec Cursor [1], sans low-code ni constructeur de pages.

Le récit que nous voulions tenir est volontaire : montrer comment construire une application économique, frugale et souveraine — code possédé, modèles possédés, moteurs d’inférence interchangeables — tout en faisant monter en puissance le modèle seulement quand cela en vaut la peine, en équilibrant en permanence coût et expérience utilisateur. Le visiteur anonyme reçoit un petit modèle CPU, rapide et peu coûteux ; l’utilisateur authentifié débloque un tier GPU plus lourd lorsque la capacité supplémentaire justifie la facture. La production reste prévisible ; le staging prouve le scale-to-zero sans parier le produit sur le runtime d’un seul fournisseur.

Ce qui suit est une vue CTO : principes, rôles de la stack, garde-fous, enveloppe mensuelle, feuille de route — formation continue, boucle d’évaluation AI Act, retour utilisateur lorsque le modèle dérape, puis pouvoirs élargis pour le grand modèle (e-mail, calendrier, documents, agents internes), toujours sous responsabilité croissante.


1. Principes de conception

Frugal par défaut. Marketing et blog en export statique sur Cloudflare Pages (edge, coût marginal proche de zéro). Le runtime Node sur Koyeb porte les APIs et le chat ; le petit Wagmi (Qwen 2.5 1,5B, Q4) tourne en CPU dans le même conteneur pour le trafic anonyme — pas de GPU facturé tant que personne ne s’authentifie. L’inférence GPU scale à zéro à l’idle.

Souverain et portable. Un codebase TypeScript, des images Docker que nous construisons et épinglons, des modèles que nous affinons et bakons — pas un widget chat SaaS opaque. Nous pointons LLM_API_URL vers llama.cpp co-localisé ou distant (API compatible OpenAI) sans réécrire l’application.

Agnostique à l’inférence. Le Vercel AI SDK et les variables validées par Zod (LLM_RUNTIME, LLM_RUNTIME_CPU, LLM_RUNTIME_GPU, alias de modèles) séparent la logique produit du runtime. Le staging valide l’image serveur complète ; la production sert les assets statiques au bord et proxifie les APIs vers Koyeb.

Les droits suivent la capacité. Le petit modèle répond à partir de faits publics (RAG sur wagmi-skills.md, ai.txt, contenu blog). Le grand modèle gagnera des outils plus larges — et une surveillance plus stricte — à mesure que nous ajouterons e-mail, calendrier, documents et agents internes.


2. La stack en un coup d’œil : qui fait quoi

CoucheOutilRôle
SecretsInfisical (UE)Source unique pour dev, staging, prod — URLs base, clés Supabase, endpoints LLM. Dev local via infisical run ; Koyeb et GitHub Actions alignés sur les mêmes espaces. Aucun secret dans git.
DonnéesPostgreSQL + Drizzle ORMSchéma typé, migrations drizzle/, écritures transactionnelles. Commodité sans chaînes magiques.
AuthSupabaseOTP e-mail (6 chiffres), cookies de session compatibles SSR. Supabase là où il excelle ; le reste dans notre app.
ContenuContent Collections + ZodBlog content/blog/ ; Markdown au build, bilingue EN/FR.
ImagesDocker Hub (jeanbapt/…)Registre de l’image web unifiée (Next.js + llama-server CPU + GGUF baké) et images GPU séparées (~10 Go). Pull Koyeb via secret de registre privé.
Usine à modèlesHugging FaceDépôts GGUF privés, datasets SFT (datasets/wagmi-sft/), entraînement et eval sur le Hub — là que nous cuisons Wagmi (wagmi-sft, wagmi-sft-14b).
Runtime stagingKoyebValidation full-stack : Standard xlarge, scale-to-zero, même image Docker qu’en secours production.
Front productionCloudflare PagesExport statique + Functions qui proxifient /api/* et l’auth vers Koyeb.
API / IA productionKoyebeco-xlarge always-on pour web + service GPU scale-to-zero pour le tier auth.
CI/CDGitHub ActionsLint, tests, build/push Docker, déploiements, release gate, porte AI Act (ci-dessous).
IDECursorImplémentation assistée ; l’architecture et la revue restent humaines.

3. Intelligence bi-niveau : coût, vitesse, et quand « passer au large »

Visiteur anonyme              Utilisateur authentifié
        │                              │
        ▼                              ▼
  Petit modèle (1,5B)            Grand modèle (14B)
  CPU, llama-server loopback     Service GPU, scale-to-zero
  Rapide, GPU marginal ~0      Wake + contexte plus profond
  RAG BM25                       Réponse CPU d’abord, puis GPU
  • Tier anonyme : wagmi-sft sur llama-server co-localisé (127.0.0.1:11434) — zéro saut réseau, latence maîtrisée après warm-up.
  • Tier auth : wagmi-sft-14b sur image GPU dédiée ; LLM_GPU_WAKE_URL réveille le scale-to-zero depuis l’edge public lorsque le maillage privé ne suffit pas.
  • Dégradé : LLM_MODEL_AUTH_FALLBACKS et chat CPU-first (CHAT_AUTH_CPU_FIRST) gardent le produit utilisable si le GPU est froid ou indisponible.

Nous plafonnons maxTokens (300 / 1024) car les petits LLM omettent souvent le token EOS et tournent en boucle. Un benchmark comportemental (scripts/benchmark-rag-qwen15b.ts) bloque le déploiement d’un petit modèle qui hallucine ou ignore l’incitation à l’auth.

Pourquoi nous n’avons pas découpé le LLM CPU en micro-service « par session » sur Koyeb : le scale-to-zero plateforme suit l’idle trafic (minutes), pas la fin de session chat ; un découpage ajouterait un second cold start sans granularité session. L’image web monolithique (~1,5 Go) est le compromis pragmatique pour l’UX anonyme en staging scale-to-zero.


4. Protéger l’environnement : Infisical

Avant les fonctionnalités, nous avons unifié la configuration :

  • Projet lié dans .infisical.json ; CLI sur l’UE (https://eu.infisical.com).
  • Environnements dev, staging, prod calqués sur le risque — pas des .env ad hoc par machine.
  • Scripts placeholders (scripts/infisical/placeholders-*.env) ; pnpm run infisical:push-placeholders pour amorcer les clés sans valeurs dans le dépôt.
  • pnpm run dev enchaîne infisical run puis Next.js pour la parité locale/staging.

GitHub Actions et Koyeb ne reçoivent que le nécessaire (tokens registry, API) ; les URLs LLM et base vivent sur le service Koyeb, synchronisées depuis Infisical prod — sans ré-injection complète à chaque deploy (ce qui effacerait la liste d’env).


5. Données et backend (condensé)

PostgreSQL via Drizzle : schéma src/lib/db/schema.ts, migrations drizzle/, URL de pool Infisical, withTransaction pour les écritures.

Supabase : auth OTP, cookies de session. Persistance chat uniquement après consentement explicite ; pas de stockage des conversations anonymes.

APIs (App Router) : POST /api/chat en flux, health, statut LLM, classification contact, callback auth. Contact uniquement via le chat.

RAG local (local-rag.ts) : chevauchement de tokens type BM25 — pas de base vectorielle pour le petit tier. Pipeline SFT : scripts/generate-wagmi-sft-dataset.tsdatasets/wagmi-sft/ pour l’entraînement Hub.


6. Construire, publier, exécuter

Docker Hub héberge des tags immuables (staging-<sha>, prod-<sha>). Dockerfile multi-stage : Node 24 bookworm-slim, utilisateur non-root nextjs, sortie standalone Next, llama-server + GGUF wagmi-sft baké (docs/ci-gguf-registry.md). Les images GPU suivent leur propre cadence quand docker/llamacpp-wagmi-gpu/** change — pas à chaque retouche de copie.

Production hybride :

  • Cloudflare Pages : assets out/, CDN mondial, edge DDoS — idéal pour le marketing et le blog.
  • Koyeb : APIs Node, chat SSE, Postgres, inférence CPU co-localisée ; la même image pourrait remplacer le routage Pages-only en quelques heures.

Staging : push dev ou workflow manuel → tests → push Docker → Koyeb deal-ex-machina-staging/web, min-scale 0, grâce santé 360 s pour VM froide + warm-up modèle.

Déploiement mixte : performance edge, runtime souverain

On pourrait objecter qu’un seul hébergeur suffirait. Pour autant, confondre simplicité opérationnelle et résilience architecturale serait une erreur. Cloudflare excelle là où l’edge excelle ; Koyeb porte le Node complet, les APIs et l’IA. Le staging valide le serveur en continu ; la production prouve l’export statique. Si l’un des deux devenait inadapté, le basculement relèverait de la reconfiguration, pas de la refonte.

Docker first : l’image comme contrat

Docker reste l’abstraction la plus portable : Dockerfile, registre, runtime interchangeable (Koyeb, ECS, Cloud Run, VPS). L’image qui tourne en staging est celle qui pourrait tourner en production serveur. Pour un cabinet qui vend des systèmes, démontrer cette rigueur sur son propre site relève du devoir, pas de l’élégance accessoire.


7. Usine à modèles, qualité, et loi européenne sur l’IA

Hugging Face est l’atelier : entraînement, versioning, GGUF privés. La CI précharge les poids dans un contexte BuildKit ou une image compagnon pour éviter de retélécharger des gigaoctets à chaque deploy.

Aujourd’hui en production :

  • Lint, tests unitaires/intégration/sécurité, type-check, E2E Playwright.
  • Release gate (scripts/release/release-gate.mjs) : santé, rounds chat SSE, Lighthouse optionnel.
  • Porte AI Act (scripts/release/ai-act-gate.mjs) : intégrée à deploy-production.yml — famille de modèle, runtime llamacpp, URLs de preuve red-team / tool-eval lors des changements de famille (ex. LFM2). Nous étendons cela en boucle d’évaluation intégrée (jeux d’eval automatisés, rétention d’artefacts, no-go plus strict).

Feuille de route — toujours protéger l’utilisateur :

  • Formation continue sur nouveau contenu blog, signaux de feedback, régressions d’eval — jamais « livrer des poids parce que c’est vendredi ».
  • Boucle de retour utilisateur : signalement in-chat lorsque Wagmi se trompe, dérape ou est inapproprié ; alimente l’hygiène des datasets et la revue d’incidents.
  • Agence graduée pour le grand modèle : brouillons e-mail, créneaux calendrier, recherche documentaire, orchestration d’agents internes — chaque capacité bornée par le rôle, les journaux d’audit, la documentation AI Act. Le petit modèle reste en lecture sur des faits publics ; les pouvoirs du grand modèle montent avec la responsabilité.

8. Garde-fous : sécurité, confidentialité, qualité

Sécurité (headers production) : CSP, HSTS, X-Frame-Options: DENY, nosniff, Referrer-Policy stricte, Permissions-Policy sans caméra/micro/géo. Allowlist CORS pour les mutations. Rate limits (ex. chat 20 req / 15 min). Zod sur toutes les entrées ; SQL uniquement via Drizzle ; filtre profanity sur le chat. Health : { "status": "ok" } seulement.

Confidentialité / RGPD : minimisation ; rétention chat consenti 7 jours ; cookies essentiels uniquement ; pages confidentialité EN/FR et case de consentement avant persistance.

Loi européenne sur l’IA : transparence (l’utilisateur sait qu’il parle à une IA) ; posture risque limité ; pas de pratiques interdites ; CGU et confidentialité limitent la reliance sur le contenu généré ; chemin d’incident via contact. La documentation technique et la supervision humaine s’étoffent avec l’usage d’outils.

Qualité : Biome, Vitest, Playwright, Lighthouse CI sur les PR ; lockfile gelé en CI ; Dependabot ; garde supply-chain pre-commit sur les workflows.


9. Économie : tenir sous ~100 $/mois

Nous visons moins de ~100 $/mois pour le site public + bursts staging + GPU occasionnel — pas une tarification « scale infini », mais une souveraineté maîtrisée :

PosteCoût typiqueNotes
Koyeb web (prod)~43 $/moiseco-xlarge (8 Go), min=1 — CPU + petit modèle résident
Koyeb GPU (prod)0–30 $/mois variableScale-to-zero ; GPU facturé à la seconde quand les auth le réveillent
Koyeb staging0–15 $/moisStandard xlarge, min=0 ; paiement à l’usage
Cloudflare Pages0 $Tier gratuit statique + proxy Functions
Supabase + Postgres0–25 $/moisTiers free/faible pour OTP + DB modeste
Infisical0 $Tier équipe/dev pour les secrets
Docker Hub + GitHub0 $Quotas gratuits
Hugging Face0 $Stockage Hub + fetch CI ; jobs d’entraînement épisodiques

Socle always-on : environ 45–55 $/mois (web prod + DB). Mois chargé avec réveils GPU et deploys staging reste souvent sous 100 $ car GPU et staging sont tarifés à la seconde, pas 24 h/24. Le choix de conception — petit modèle pour tous, grand modèle après auth — rend cette enveloppe tenable.


10. Runtimes et front (synthèse)

Node 24, TypeScript 5.9 strict, Next.js 16 App Router (standalone + export statique), React 19, Tailwind, Radix, next-intl EN/FR, Assistant UI + Vercel AI SDK. Critical CSS, bundle chat lazy, AVIF/WebP, JSON-LD, sitemaps, llms.txt / ai.txt. Cibles perf : Lighthouse performance ~96 %, CLS 0 — détail dans docs/PERFORMANCE_OPTIMIZATIONS_FINAL_STATUS.md.


11. Ce que nous évitons volontairement

Pas de WordPress/Wix/low-code pour le cœur du site. Pas de secrets dans git ou les bundles client. Pas d’any arbitraire. Pas de livraison sans lint, tests et type-check en CI. Pas de health endpoint bavard en production. Pas de cookies analytics tiers.


12. Pourquoi le web reste la démo

Cette stack montre qu’une surface IA niveau cabinet peut être :

  • frugale (tiers de modèles, GPU scale-to-zero, statique au bord),
  • souveraine (notre code, nos poids, runtimes interchangeables),
  • gouvernée (Infisical, RGPD, porte AI Act, boucle de feedback à venir),
  • et abordable (enveloppe opérationnelle ~ sous 100 $/mois).

Le dépôt et le site en ligne sont le livrable. La feuille de route ne remplace pas cette discipline — elle l’étend, pas à pas, en ne donnant au grand modèle plus de pouvoir que de responsabilité en face.


Références

  1. Cursor
  2. Node.js
  3. TypeScript
  4. Next.js
  5. PostgreSQL
  6. Drizzle ORM
  7. Supabase
  8. Content Collections
  9. Zod
  10. Vercel AI SDK
  11. Assistant UI
  12. Infisical
  13. Docker Hub
  14. Hugging Face
  15. Koyeb
  16. Cloudflare Pages
  17. GitHub Actions
  18. Biome · Vitest · Playwright · Lighthouse CI

Synthèse : Infisical (secrets) · Supabase + Drizzle + Postgres (auth/données) · Docker Hub (images) · Hugging Face (modèles Wagmi) · Koyeb (API + inférence CPU/GPU) · Cloudflare Pages (statique production) · GitHub Actions (CI, release gate, porte AI Act) · LLM bi-niveau · cible ops < ~100 $/mois.