
Série « Vibe coding avec Claude Code » · Article 3/5. Avant de coder, j’ai posé un socle : les contraintes techniques, une architecture décidée en dialogue, une documentation qui sert de vérité unique, et un cadre de gouvernance pour piloter l’IA. C’est cet investissement initial qui rend la vélocité sûre.
Sommaire de la série :
- J’ai vibe-codé une application e-commerce complète avec Claude Code
- Avant le code : faire produire le fonctionnel par l’IA
- Préparer le terrain : doc, archi et gouvernance avant la première ligne (cet article)
- La méthode au quotidien : comment Claude code, et comment je garde le contrôle
- Bilan : ce que ça apporte, ce que ça coûte, et la recette à réutiliser
Dans le premier article, j’ai montré le résultat. Dans le deuxième, le fonctionnel produit par l’IA, avant la première ligne de code. On reste avant le code, mais on change de plan : on passe du quoi (le métier, l’article 2) au comment technique. C’est l’objet de cet article : comment l’architecture a été décidée, comment la documentation a été posée, et surtout comment j’ai outillé Claude pour qu’il travaille dans un cadre, pas en roue libre. Mon fil rouge ne bouge pas :
Je dirige, l’IA exécute.
À ce stade du projet, « diriger » veut dire quelque chose de précis : je décide l’architecture et les règles du jeu, l’IA propose des options, me challenge, puis exécute à l’intérieur du cadre que j’ai fixé. Cet article raconte la construction de ce cadre. C’est moins spectaculaire qu’une page qui s’affiche, mais c’est exactement ce qui sépare un POC robuste d’un tas de code plausible.
💬 Toujours la « Phase 0 ». Comme le fonctionnel (article 2), une partie du brainstorming technique s’est jouée en amont, dans Claude Chat sur le web : la même longue conversation de cadrage, à brasser les options d’architecture et de stack avant d’ouvrir le moindre fichier. Cette phase reste hors des outils du dépôt (pas de log, pas de commit), une limite que j’assume et sur laquelle je reviens en fin d’article.
1. Recueil technique : contraintes, cible et outillage existant
Symétrique du recueil fonctionnel, le recueil technique commence par poser les contraintes, pas les solutions. Trois comptaient vraiment.
La règle d’or, d’abord. Celle de l’article 2 est aussi une contrainte technique : le domaine est la seule chose simplifiée, tout le reste est production-grade. Concrètement, ça interdit d’avance une foule de raccourcis qu’une IA prendrait volontiers : pas de TODO, pas d’exception avalée, pas d’effet « on verra plus tard ». Cette ligne cadre toutes les décisions qui suivent.
Une cible d’hébergement. Je voulais que le projet soit, à terme, hébergeable sur Azure à coût minimal (du managé, du serverless, pas de serveur à administrer). Cette contrainte n’a pas dicté le code, mais elle a façonné le socle : tout ce qui touche au monde extérieur (cache, stockage d’images, bus de messages, envoi d’e-mails, export de télémétrie) passe par des ports abstraits, sélectionnés par configuration. Conséquence voulue : passer sur Azure devient un changement de configuration, pas une réécriture. L’hébergement réel a été différé (c’est un incrément optionnel), mais la portabilité, elle, a été pensée dès la première décision.
Un profil et une stack existants. Je suis architecte .NET / Azure, et Claude le sait : mon profil est renseigné dans sa configuration globale (on y revient en section 4). Il pose donc des questions de niveau pair et ne me fait pas de cours. C’est aussi à ce moment qu’est née l’anecdote de l’article 1 : connaissant ma stack, il proposait spontanément du React pour le front ; j’ai choisi Svelte exprès, pour m’observer le diriger sur une techno que je maîtrise moins.
Le rôle de l’IA dans ce recueil n’a pas été d’inventer les contraintes (elles sont à moi) mais de dérouler les options sous chacune, avec leurs compromis, et de vérifier le concret. Point important et souvent sous-estimé : pour chaque bibliothèque, Claude est allé vérifier la version courante et l’API réelle dans la documentation à jour, au lieu de se fier à sa mémoire d’entraînement, parfois périmée. Le résultat de ce travail est une stack épinglée et datée (.NET 10, Wolverine 6, Marten 9, EF Core 10, Elasticsearch 9, Keycloak, SvelteKit), figée dans un seul fichier de versions. La vérification des versions n’est pas un détail : c’est l’une des premières choses où une IA se trompe, et l’un des premiers garde-fous que j’ai mis en place.
2. Le brainstorming d’architecture, décidé ensemble
Voici le cœur de cet article. L’architecture de ecom n’a pas été « générée » par l’IA, ni dictée par moi seul. Elle a été tranchée en dialogue : j’apporte l’intention et le jugement, Claude expose des options argumentées et me challenge, je décide. Et chaque décision qui compte a été figée dans une ADR (Architecture Decision Record), une note courte qui capture le pourquoi.
Les grands choix, posés ensemble, tiennent en quelques lignes :
- Un modular monolith, pas des microservices : on veut la valeur d’apprentissage et la garantie d’extraction (pouvoir détacher un module plus tard) sans payer tout de suite la taxe du distribué.
- Une architecture hexagonale par module (domaine sans aucune dépendance technique), pour que « le domaine est pur » soit une vérité vérifiée à la compilation, pas un vœu de revue de code.
- DDD et CQRS : des contextes métier nets, l’écriture via EF Core, la lecture via Dapper, des projections dédiées pour les vues transversales.
- Un seul agrégat event-sourced (la Commande, via Marten), tout le reste en persistance classique par état : c’est délibéré, pour comparer les deux styles dans une même base de code.
- Un bus de messages (Wolverine) avec outbox / inbox durable, en transport mémoire pour les tests et RabbitMQ en vrai, le tout commutable par configuration.
Ce qui m’importe ici, ce n’est pas la liste (elle est probablement banale pour un architecte) : c’est la manière. L’ADR est l’artefact de la co-décision. Sa structure l’impose : un Contexte, une Décision, ses Conséquences, et surtout une rubrique « Alternatives considérées (et pourquoi rejetées) ». C’est là que la discussion laisse une trace. Un exemple réel, tiré de l’ADR sur le monolithe modulaire :
« Monolithe maintenant, on refactorera en services plus tard. » Rejeté comme un non-plan : sans coutures imposées, ce refactoring ultérieur est précisément la réécriture qu’on cherche à éviter. Les coutures doivent exister dès le premier commit, ou elles n’existeront jamais.
Une IA laissée seule aurait probablement choisi par défaut, sans tracer l’arbitrage. Là, chaque option écartée est argumentée. C’est ça, « diriger » au niveau architecture : pas refuser les propositions de l’IA, mais exiger qu’elles soient pesées et que la décision soit raisonnée, pas subie.
Reste un risque propre au travail avec une IA sur la durée : re-débattre les fondations à chaque session. La parade tient en un mécanisme simple : un chapitre du document-source liste les décisions actées, à ne pas reconsidérer. Le fondamental est verrouillé une fois ; ce qui reste ouvert est explicitement marqué comme ouvert. Le socle est stable, mais le design n’est pas figé pour autant : il s’étoffe incrément par incrément, et de nouvelles ADR apparaissent quand le besoin arrive (la saga de paiement, par exemple, est née quand le checkout est devenu réellement transverse). Ce mécanisme du « design qui mûrit au fil de l’eau » est le sujet de l’article 4.
📐 Les 15 règles du jeu (R1 à R15), vulgarisées
Le brainstorming a produit quinze règles d’architecture, le vrai cœur du POC. Ce sont elles qui, si on les casse, détruisent silencieusement la fiabilité ou la capacité d’extraction. Les voici en clair, regroupées par thème.
Transactions et résistance aux pannes
- R1 · La frontière d’une transaction = exactement ce que le message « c’est fait » promet à l’utilisateur, ni plus ni moins.
- R2 · Tout ce qui doit survivre à un crash est rendu durable avant de valider (via l’outbox). Un effet post-commit gardé seulement en mémoire est banni.
Événements et traçabilité
- R3 · Événement de domaine (interne, libre) ≠ événement d’intégration (contrat versionné, stable, publié aux autres).
- R4 · Le journal d’audit est séparé de l’event sourcing : il enregistre chaque fait métier, mais n’est jamais rejoué.
- R5 · L’identité de l’initiateur (l’utilisateur Keycloak) circule du périmètre de l’API jusqu’à chaque événement.
Lectures et cohérence
- R7 · Deux façons de lire en travers des modules : composer à la lecture (toujours à jour) ou lire une projection dénormalisée (à jour éventuellement).
- R8 · « Lire ce qu’on vient d’écrire » ou « tolérer un léger retard » est un choix délibéré, lecture par lecture (et le retard est affiché).
Projections et reconstructions
- R6 · Les projections doivent être reconstructibles à volonté, de façon déterministe (idempotentes, ordonnées).
- R10 · Un import en masse contourne le domaine, puis déclenche une reconstruction.
- R11 · Les reconstructions se font à chaud (blue-green), jamais sur la donnée vivante.
Règles métier et communication
- R9 · Un invariant tient dans un seul agrégat (atomique) ; une règle qui traverse les modules n’est pas un invariant : on l’applique en réaction (autoriser, détecter, compenser).
- R13 · Chorégraphie, pas chaînes d’appels synchrones : A, B et C réagissent indépendamment via le bus.
Extraction et exploitation
- R12 · Les consommateurs de messages sont bornés ; la contre-pression vit dans le broker.
- R14 · Un schéma par module, aucune clé étrangère entre schémas : on se référence par identifiant. C’est ce qui rend l’extraction mécanique.
- R15 · Un changement de schéma sans interruption se fait en deux temps (expand / contract).

Les 15 règles, regroupées par thème. Elles ont été décidées une fois, encodées (section 4), et rappelées à l’IA avant chaque décision. C’est ce qui garantit la cohérence sans re-débattre à chaque session.
3. La documentation socle, finalisée avant de coder
Une fois l’architecture tranchée, il fallait la poser noir sur blanc, avant le code. Pas pour faire joli : pour qu’elle serve de vérité unique, relisible par une nouvelle session de Claude comme par un humain.
Le pivot est un document-source unique (PROJECT-CONTEXT-AND-PLAN.md) : il capture pourquoi chaque décision a été prise, la stack vérifiée, les livrables à produire et la feuille de route. Une session fraîche le lit de haut en bas avant d’écrire une ligne. Autour de lui gravitent les ADR (une par décision) et un contrat d’API gelé (son rôle de synchro front/back est détaillé à l’article 4).
Viennent ensuite les diagrammes. J’ai modélisé l’architecture en C4 (description d’un système à plusieurs niveaux de zoom) et le domaine en UML (un diagramme par contexte métier). Le C4 se lit comme une carte qu’on agrandit : trois niveaux de zoom valent d’être montrés.
Le contexte système : qui parle à quoi, vu de très haut.

C4 niveau 1 (contexte système). Le backend est une seule boîte logique ; autour, les acteurs et les systèmes externes (l’identité Keycloak, le flux de faits vers la plateforme data, l’import de masse).
Le diagramme de conteneurs : ce qu’on déploie réellement, et les données de chacun.

C4 niveau 2 (conteneurs). Quatre processus .NET aux rôles distincts (l’API ne fait aucun travail de fond, le Worker consomme le bus, le Scheduler planifie, le Migration Runner applique le schéma), deux fronts, et les magasins de données. Tout passe par Postgres (un schéma par module) et le bus.
🔬 Pour les curieux : l’intérieur d’un module (C4 niveau 3). Un dernier cran de zoom, sur le module Commande (celui qui est event-sourced et porte la saga). C’est la matérialisation de l’hexagonal décidé en section 2 : le domaine est au centre, avec zéro dépendance technique ; autour, les ports (des interfaces) ; et tout autour, les adaptateurs qui parlent au monde réel (l’event store Marten, l’outbox, le bus). Les dépendances pointent toutes vers le centre, jamais l’inverse. Les décideurs peuvent sauter ; les pairs y verront la discipline qui garde le domaine pur.

C4 niveau 3 (composants), sur le module Commande. Au centre, le domaine pur (agrégat, événements, value objects), testable sans aucun conteneur. L’application définit des ports ; l’infrastructure fournit les adaptateurs (Marten, outbox durable dans la même transaction, publisher Wolverine). C’est l’hexagonal rendu visible. Version simplifiée du .puml du dépôt.
Le point que je veux vraiment faire passer ici dépasse le code : cette doc n’est pas un livrable de dev. Elle est transversale, et c’est tout l’intérêt.
- Pour l’infra : le diagramme de conteneurs est la topologie de déploiement (quatre processus, leurs magasins, le bus). Run, scaling, dépendances : tout est lisible là.
- Pour la sécurité : les décisions d’authentification et d’autorisation (Keycloak, PKCE pour l’acheteur, flux confidentiel pour l’admin, validation du jeton côté API) sont des ADR à part entière, discutables et tracées.
- Pour le métier : c’est la spécification fonctionnelle de l’article 2, vivante au même endroit.
Autrement dit, la documentation est le langage commun de toutes les équipes qui graviteront autour du projet, pas seulement des développeurs. C’est le prolongement direct des « trois amigos » de l’article 2, étendu à l’infra et à la sécurité.
🧭 Ça porte un nom (suite). Ce socle (document-source unique, ADR, contrat gelé, diagrammes) est exactement ce que l’industrie appelle le spec-driven development : une spécification versionnée et vivante qui sert de source de vérité, dont on dérive le plan puis le code. La doc n’est pas la trace du travail, elle en est le point de départ.
⚖️ Honnêteté : l’amorçage n’est pas gratuit. Poser ce socle (la Phase 0 sur Claude Chat, plusieurs heures, puis la mise en place du document-source, des ADR fondateurs, des C4 et de la gouvernance) a occupé le tout début du projet, avant le premier incrément métier. C’est l’investissement initial que l’article 1 promettait de situer : il est réel, et il est front-loaded. Je ne peux pas l’isoler au token près des chiffres globaux (ils sont au bilan, article 5), mais le principe est clair : on paie cher au début, et on amortit ensuite à chaque incrément qui réutilise le cadre.
4. Le différenciant : la gouvernance de Claude
Si je ne devais montrer qu’une chose de cette série à un autre architecte, ce serait celle-ci. Entre « demander gentiment à l’IA » et « industrialiser l’IA », il y a un dossier : .claude/. C’est là que vit le cadre qui transforme un assistant bavard en exécutant discipliné.
.claude/
├── agents/ # les rôles spécialisés
│ ├── architect-expert.md
│ ├── senior-back-lead.md
│ ├── senior-front-lead.md
│ ├── code-reviewer.md
│ ├── security-analyser.md
│ └── postgres-dba.md
├── commands/ # les workflows répétables
│ ├── new-adr.md
│ ├── new-increment.md
│ ├── uml-sync.md
│ ├── verify-contract.md
│ └── new-lesson.md
├── skills/
│ └── ecom-architecture-rules/ # les R1-R15 encodées
│ └── SKILL.md
├── hooks/
│ └── block-secrets.ps1 # garde-fou déterministe
└── settings.json # branchement des hooks
Le CLAUDE.md, contexte toujours présent. Deux fichiers : un global (qui porte mon profil d’architecte, d’où les questions de niveau pair) et un projet (build, run, tests, architecture). La règle, recommandée par Anthropic dans ses bonnes pratiques, est de le garder court et d’élaguer sans pitié, sinon l’IA en ignore la moitié.
Le skill qui encode les règles. Plutôt que de gonfler le CLAUDE.md avec les quinze règles, je les ai déportées dans un skill dédié, ecom-architecture-rules, chargé à la demande avant chaque décision. C’est la variante recommandée : les règles sont toujours disponibles, jamais noyées. Extrait réel :
R2 : Anything that must survive a crash is durable BEFORE commit (outbox).
R14 : Schema-per-module, NO cross-schema foreign keys, ever. Modules
reference each other by ID only. This is what keeps extraction mechanical.
Golden rule: the domain is the only thing simplified. Everything else is
production-grade. No TODO, no swallowed exceptions, no shortcuts.
Cinq agents (plus un) spécialisés. Chacun est un contexte séparé avec un rôle étroit : un architecte (gate avant chaque incrément), un lead back, un lead front, un relecteur de code, un analyste sécurité, un DBA Postgres. L’intérêt, documenté par Anthropic (Building Effective Agents), est double : un sous-agent explore ou relit sans polluer le fil principal, et un relecteur qui ne voit que le diff (pas le raisonnement qui l’a produit) juge mieux. Le relecteur de code, par exemple, est explicitement contradictoire :
You are the code reviewer for the ecom POC. You are read-only and
adversarial in the useful sense: you find the problem before production does.
No praise, no scope creep.
...
VERDICT: SHIP | FIX-FIRST (<n> blockers, <n> majors)
La façon dont cette équipe travaille au quotidien (qui tourne en parallèle, dans quel ordre) est le sujet de l’article 4. Ici, ce qui compte, c’est que les rôles existent et qu’ils ont chacun leur cadre.
Des commandes et des hooks. Les commandes (/new-adr, /new-increment, /uml-sync, /verify-contract, /new-lesson) encodent des workflows répétables. Les hooks, eux, sont la pièce que je trouve la plus sous-estimée : contrairement à une consigne du CLAUDE.md (qui est advisory, l’IA peut l’oublier), un hook est déterministe, il s’exécute à coup sûr. Trois sont en place : un blocage des fichiers de secrets (avant chaque lecture/écriture), une mise à jour automatique du graphe de connaissance du code (après chaque édition), et un statut au démarrage de session. Le blocage des secrets, par exemple, est un vrai garde-fou de sécurité, pas une simple recommandation.
Et des MCP (les connecteurs vers des outils et des données externes) : la documentation à jour des bibliothèques (pour vérifier les API plutôt que se fier à la mémoire du modèle), un graphe de connaissance du code (recherche structurelle, impact, couverture, sans rescanner tout le dépôt, donc moins de tokens et plus de rapidité), un accès Postgres en lecture seule, et un pilotage de navigateur pour les vérifications visuelles.
🔌 Pourquoi ce cadre, en une phrase chacun. Cohérence sans re-débat (le skill) · garde-fous qui ne s’oublient pas (les hooks) · relecture lucide en contexte frais (les agents) · documentation toujours à jour et exploration moins coûteuse (les MCP). Aucun de ces éléments n’écrit le code à ma place ; ils rendent l’exécution de l’IA fiable et dirigeable.
5. À retenir : on investit dans le cadre
Avant la première ligne de code, j’ai posé quatre choses : un recueil technique (contraintes, cible Azure, stack vérifiée), une architecture décidée ensemble et résumée en quinze règles, une documentation socle transversale (le document-source, les C4, l’UML), et une gouvernance qui outille l’IA (CLAUDE.md, skill, agents, commandes, hooks, MCP).
C’est un pari assumé : investir d’abord dans le cadre, et garder la main sur les décisions. Ce cadre n’a pas écrit le code à ma place ; il a fait en sorte que, quand le code est arrivé, il arrive dans les rails. La vélocité de l’article 1 n’est pas magique : elle est la contrepartie de ce socle. « Je dirige, l’IA exécute » prend ici tout son sens : je décide les règles, l’IA opère à l’intérieur.
✅ À retenir
- Le recueil technique pose des contraintes (règle d’or, cible Azure, stack vérifiée), pas des solutions. L’IA déroule les options ; l’architecte tranche.
- L’architecture est co-décidée et tracée en ADR, avec les alternatives rejetées. Quinze règles en forment le cœur, décidées une fois et encodées pour ne pas être re-débattues.
- La documentation socle (document-source unique, C4, UML) est une vérité transversale : dev, mais aussi infra, sécurité et métier. C’est du spec-driven development.
- Le vrai différenciant, c’est la gouvernance : un skill qui encode les règles, des agents en contexte séparé, des hooks déterministes, des MCP. Le cadre rend l’IA fiable et dirigeable.
- L’amorçage est un investissement initial réel, front-loaded, amorti ensuite à chaque incrément.
➡️ Article suivant : « La méthode au quotidien : comment Claude code, et comment je garde le contrôle ». On entre dans la boucle d’un incrément (du design au code et à la note pédagogique), le contrat d’API comme point de synchro, l’équipe d’agents en action, et l’anecdote d’une cascade de six bugs invisibles au build.
🛠️ À améliorer (transparence)
- Des worktrees plutôt que des répertoires disjoints. Pour faire travailler plusieurs agents en parallèle, je me suis appuyé sur une séparation des répertoires (back dans
src/, front dansapps/). Anthropic recommande plutôt les git worktrees pour les sessions parallèles : une vraie isolation des copies de travail, donc moins de collisions et moins de débordements. C’est ce que je ferais dès le départ la prochaine fois.- Plus de garde-fous déterministes. J’avais quelques hooks, mais beaucoup de règles restaient conseillées (la règle d’or « no TODO », le lint, le scan de sécurité). En équipe, elles devraient passer en hooks ou en gates de CI (où une violation casse la build), pas en simples consignes. C’est la différence entre « l’IA est censée le faire » et « ça arrive à coup sûr ».
- L’amorçage a un coût. Construire ce socle avant de coder demande du temps et de la discipline. Sur un petit projet, l’investissement peut ne pas se rentabiliser ; il se justifie d’autant plus que le projet est ambitieux et durable.