1. Le moment : quand l'app tourne à l'extérieur mais craque à l'intérieur
Au début, tout est magique. Tu dis à l'IA "ajoute un écran de profil" et il apparaît. "Maintenant un bouton pour exporter", et il apparaît. Tu avances vite, très vite. Mais il y a un moment — presque toujours entre la troisième et la dixième semaine — où quelque chose change. Demander une petite fonctionnalité n'est plus instantané. L'IA met plus de temps, se trompe, touche à des choses qu'elle ne devait pas. Des bugs apparaissent à des endroits que tu n'as même pas touchés. L'app fonctionne, mais la faire évoluer est devenu pénible, comme marcher avec de la boue aux chaussures.
C'est LE moment. Rien de dramatique ne s'est produit : rien de visible n'est cassé. Ce qui s'est passé est invisible et ça s'appelle la dette technique. L'IA a construit vite et, comme tous ceux qui construisent vite, elle a laissé des gravats : du code que plus personne n'utilise mais qui reste là, la même logique copiée dans cinq fichiers, des types any qui coupent toutes les alarmes, des animations montées n'importe comment. Rien de tout ça ne se voit à l'écran. Mais tout ça rend chaque changement futur plus difficile.
2. La douleur : d'où elle vient et pourquoi l'IA salit (même quand elle écrit "bien")
Voici l'essentiel, en toute honnêteté : l'IA n'écrit pas du mauvais code. Elle écrit du code qui fonctionne. Le problème, c'est qu'elle optimise pour "que ça marche maintenant", pas pour "que ce soit facile à maintenir dans trois mois". Et ces deux objectifs tirent dans des directions opposées. Voilà pourquoi, même si chaque morceau est correct, la somme finit par se salir. Voici les quatre types de gravats qu'elle laisse, et pourquoi elle les laisse :
- Code mort. Tu demandes un changement, l'IA réécrit une nouvelle fonction… mais oublie d'effacer l'ancienne. Elle reste là, orpheline, sans que personne ne l'appelle. Multiplie ça par des centaines de changements et tu te retrouves avec des fichiers entiers qui ne servent plus à rien.
- Duplication. L'IA ne se souvient pas toujours qu'elle a déjà écrit cette même logique auparavant, alors elle la réécrit. Maintenant la même règle vit à cinq endroits. Le jour où la règle change, il faut la corriger cinq fois — et on en oublie toujours une.
- `any` et types flous. Quand l'IA n'est pas sûre du type d'une donnée, elle prend le raccourci : elle le marque comme
any. Avec ça, elle coupe toutes les alarmes que TypeScript possède pour t'avertir des erreurs. Le code compile… et explose en production. - Animations et effets montés à l'arrache. L'IA place des dégradés animés, des flous, des ombres — ça a l'air bien, mais mal montés ils font transpirer le GPU et l'app devient lente sur mobiles et ordinateurs portables modestes.
3. Les 7 phases de la chirurgie (le cœur de tout)
Un chirurgien n'ouvre pas et ne fouille pas au hasard : il suit un protocole, dans l'ordre, étape par étape. La chirurgie de code, c'est pareil. Ce sont sept phases, et l'ordre compte : d'abord tu retires le mort (pour ne pas nettoyer du code que tu allais effacer), puis tu fusionnes les doublons, puis tu durcis les animations, puis les performances de React, puis les types, puis tu apaises le GPU, et à la fin tu émets un rapport de santé. Voici chacune d'elles.
Phase 1 · Éliminer le code mort
La première chose, c'est de retirer de la table tout ce qui ne respire plus. C'est la phase la plus rentable car elle dégage le terrain pour toutes les autres : ça n'a aucun sens d'optimiser une fonction que tu vas effacer.
- Fichiers orphelins — des fichiers que personne n'importe depuis nulle part. Ils sont là depuis une vieille version qui n'a jamais été effacée.
- Exports sans consommateurs — des fonctions ou composants exportés que personne n'utilise. Ils ont été exportés "au cas où" et le cas n'est jamais arrivé.
- Variables, fonctions et imports inutilisés — déclarés et oubliés. Le linter les signale souvent, mais l'IA les laisse parce que "ça ne gêne pas". Si, ça gêne : c'est du bruit.
- Branches de code inatteignables — des conditions qui ne peuvent jamais être vraies, du code après un
return, desifque plus personne ne déclenche.
Phase 2 · Auditer les doublons
Le terrain nettoyé, tu cherches maintenant ce qui est répété. La règle du métier est simple : si quelque chose apparaît trois fois ou plus, ce n'est plus un hasard mais un motif qui mérite un seul endroit où vivre.
- Logique répétée → sors-la dans une fonction auxiliaire (
helper) que les deux endroits appellent. Une règle, un seul endroit. - Nombres et textes magiques répétés (le même
48, la même URL, la même couleur) → centralise-les dans des constantes nommées. Tu changes une fois, ça change partout. - JSX répété trois fois ou plus (la même carte, le même bouton avec de légères variantes) → transforme-le en un sous-composant qui reçoit ses différences via des props.
- Le motif `useState` + son handler répété (le même état avec sa fonction de mise à jour copié dans plusieurs composants) → extrais-le dans un hook maison (un
custom hook) qui encapsule la logique une seule fois.
Phase 3 · Respecter les règles d'animation
Les animations, c'est là où l'IA improvise le plus et où elle laisse le plus de défauts subtils — des choses qui ne cassent pas mais qui font que l'app se sent "cheap" : clignotements, sauts, transitions qui ne démarrent pas. Voici les règles concrètes que la chirurgie vérifie (elles s'appliquent aux librairies d'animation de React comme Motion / Framer Motion, le standard de l'écosystème) :
- Animer vers/depuis `transparent` peut clignoter → utilise
rgba(0,0,0,0)à la place. Quand tu interpoles le mottransparentavec une couleur, la transition peut produire un clignotement laid à mi-chemin ;rgba(0,0,0,0)interpole proprement. - Pas de `transition` dupliqué — une animation avec deux définitions de transition qui se battent entre elles donne un résultat imprévisible. Une seule source de vérité pour le timing.
- Ne pas animer le raccourci `border` (le shorthand qui regroupe épaisseur, style et couleur) → anime des propriétés séparées comme
borderColor. Le shorthand n'interpole pas proprement. - `background` → `backgroundColor` dans les animations — animer le raccourci complet
backgroundest problématique ; anime seulement la propriété spécifique qui change. - Keys stables dans les listes qui entrent et sortent (
AnimatePresence) — si les éléments d'une liste animée n'ont pas dekeystable et unique, les animations de sortie se cassent et les éléments sautent. La key doit être un id réel, jamais l'index du tableau.
Phase 4 · Performances de React
Ici la chirurgie cherche le travail que React répète sans nécessité. Chaque re-render inutile, c'est un peu de lenteur ; additionnés, ils font que l'app se sent lourde. Quatre points concrets sont passés en revue :
- Handlers passés comme props sans `useCallback` → enveloppe-les. Sinon, chaque render crée une nouvelle fonction et oblige les composants enfants à se re-rendre même si rien n'a changé.
- Calculs coûteux sans `useMemo` (filtrer/trier une grande liste, calculs lourds) → mémoïse-les. Sinon, ils sont recalculés à chaque render même si les données sont identiques.
- `useEffect` avec des dépendances mal déclarées — trop de dépendances déclenchent l'effet sans raison ; trop peu font qu'il utilise des données périmées. Les deux sont des bugs. Le tableau de dépendances doit lister exactement ce que l'effet utilise.
- `.map` sans `key` stable — rendre des listes sans key unique (ou en utilisant l'index) fait que React se perd lors du réordonnancement et perd l'état. Chaque élément a besoin de son propre id.
useCallback et useMemo "au cas où". Non : mémoïser a aussi un coût (mémoire, complexité). La chirurgie ne mémoïse que là où il y a un bénéfice réel et mesurable — un handler qui descend vers beaucoup d'enfants, un calcul vraiment coûteux. Trop optimiser est sa propre forme de saleté.Phase 5 · Hygiène de TypeScript
TypeScript est le système d'alarmes de ton code : il t'avertit avant qu'une erreur n'atteigne l'utilisateur. Mais il ne fonctionne que si tu le laisses voir les types. Chaque any est une alarme que quelqu'un a coupée. Cette phase les rallume.
- `any` → un type réel, ou `unknown` — le
anydésactive toutes les vérifications. Si tu ne connais vraiment pas le type, utiliseunknown, qui t'oblige à le vérifier avant de l'utiliser (sûr), au lieu deany, qui n'oblige à rien (dangereux). - Passer en revue les casts `as Type` — dire à TypeScript "fais-moi confiance, c'est de ce type" est une promesse qui peut être un mensonge. Chaque
asest un point où le compilateur a cessé de vérifier. On les revoit un par un : est-ce vrai, ou est-ce un pansement ? - Internaliser les exports à usage unique — si un type ou une fonction est exporté mais n'est utilisé que dans son propre fichier, il ne devrait pas être public. Rends-le privé : moins de surface, moins de bruit.
- Typer les props des composants — chaque composant doit déclarer quelles props il reçoit et de quel type. Des props non typées sont des
anydéguisés.
Phase 6 · Auditer l'effondrement du GPU
Voici la phase que presque personne ne connaît et celle qui se remarque le plus sur les appareils modestes. Certains effets visuels sont magnifiques mais brutalement coûteux à dessiner : si tu en abuses, la carte graphique se sature et l'app saccade. La chirurgie cherche les trois coupables classiques :
- Dégradé conique (`conic-gradient`) animé → déplace-le vers une animation CSS avec
@keyframes. Animer un dégradé conique par JavaScript à chaque frame est très coûteux ; avec les keyframes le navigateur l'optimise. - Beaucoup de `repeat: Infinity` (plusieurs animations en boucle infinie en même temps) → consolide-les. Dix animations éternelles tournant en parallèle maintiennent le GPU éveillé et brûlent la batterie sans arrêt. Fusionne-les ou réduis celles qui sont vraiment nécessaires.
- `backdrop-blur` sur de nombreux petits éléments répétés → si le même flou d'arrière-plan se répète sur vingt petites cartes, le GPU le recalcule vingt fois. Pour des éléments petits et répétés, un fond solide (ou semi-transparent) a l'air presque pareil et coûte une fraction.
backdrop-blur, cet effet de verre dépoli si à la mode) oblige le GPU à regarder TOUT ce qui se trouve derrière l'élément et à le flouter en temps réel. Un seul, grand, ce n'est rien. Vingt petits qui se répètent, c'est comme demander à la carte de flouter l'écran vingt fois par frame. C'est là que le portable de ton utilisateur commence à faire souffler le ventilateur.Phase 7 · Le rapport de santé
Toute chirurgie se termine par un compte rendu. Sans rapport, tu ne sais pas ce qui a été touché ni ne peux avoir confiance qu'il n'y a pas eu de dégâts collatéraux. La dernière phase, c'est que l'agent te remette un résumé clair, dans ta langue, de tout ce qu'il a fait :
- Décompte par phase — combien de fichiers orphelins, combien de doublons fusionnés, combien de
anyéliminés, combien d'animations corrigées, etc. - Lignes purgées — le total de lignes de code mort qui sont sorties. C'est le chiffre le plus satisfaisant : du code que tu n'as plus à maintenir.
- Verdict "prêt pour la production" — la confirmation explicite que rien n'a changé, ni visuel ni comportemental, seulement la structure interne.
- Ce qu'il n'a PAS touché et pourquoi — les choses qui semblaient candidates mais qui ont été laissées volontairement (doublons qui changent pour des raisons différentes, mémoïsation qui n'en valait pas la peine). L'honnêteté de ce qu'on a décidé de ne pas faire.
4. L'habitude : la chirurgie est un entretien, pas une opération unique
L'erreur la plus courante, c'est de penser la chirurgie comme quelque chose qu'on fait une fois, quand tout est déjà un désastre. Non. Le code de l'IA se salit CONTINUELLEMENT, parce que chaque session de construction laisse de nouveaux gravats. La chirurgie n'est pas une opération d'urgence : c'est le détartrage que tu fais tous les six mois pour ne jamais en arriver au traitement de canal.
- Après un gros sprint de construction — quand l'IA vient de générer beaucoup de code d'un coup, ce sont les gravats frais. Nettoie-les avant qu'ils ne s'accumulent par-dessus.
- Avant de commencer une fonctionnalité importante — donne à l'IA une toile propre pour construire. Sur du code sale, elle construit sale.
- Quand tu remarques que l'IA commence à se perdre — si l'outil touche à des choses qu'il ne devait pas ou se perd, c'est le signe qu'il y a trop de bruit. La chirurgie lui rend de la clarté.
- Un fichier ou un module à la fois, pas tout le projet d'un coup — opérer un seul module est sûr et vérifiable. Opérer tout d'un coup, c'est une chirurgie à cœur ouvert sans anesthésie. Vas-y par morceaux.
5. Le prompt maître · passe-le à ton agent et opère phase par phase
Voici la pièce maîtresse : UN seul prompt qui transforme ton agent de code en chirurgien appliquant les 7 phases, dans l'ordre, à un fichier ou un module — sans toucher à rien de visuel. Remplis les [crochets], colle-le, et laisse-le opérer. Un conseil avant : fais d'abord un commit sur GitHub (ton filet de sécurité) et pointe-le vers UN module, pas vers tout le projet.
Agis comme un chirurgien de code expert en debug. Tu vas opérer ce fichier/module : [CHEMIN DU FICHIER OU DOSSIER, ex : src/components/Dashboard/]. Le stack est : [ex : React + TypeScript + Motion/Framer Motion + Tailwind]. RÈGLE SACRÉE ET INVIOLABLE : ZÉRO changement visuel et ZÉRO changement de comportement. L'app doit avoir l'air et se comporter EXACTEMENT pareil avant et après. Tu ne fais que nettoyer et durcir à l'intérieur. Devant tout doute entre nettoyer plus ou préserver le comportement, c'est TOUJOURS préserver le comportement qui gagne. N'efface rien si tu n'es pas sûr que ce n'est pas utilisé ; signale-le et demande-moi. Applique ces 7 phases DANS L'ORDRE. Ne passe pas à la suivante sans terminer la précédente. À la fin de chaque phase, dis-moi en une ligne ce que tu as trouvé et ce que tu as changé. PHASE 1 — CODE MORT : élimine les fichiers orphelins (que personne n'importe), les exports sans consommateurs, les variables/fonctions/imports inutilisés, et les branches de code inatteignables. Avant d'effacer quelque chose de douteux, liste-le-moi et attends ma confirmation. PHASE 2 — DOUBLONS : cherche la logique répétée (→ extrais dans un helper), les nombres/textes magiques répétés (→ constantes nommées), le JSX répété 3+ fois (→ sous-composant avec props), et le motif useState+handler répété (→ custom hook). NE fusionne PAS des choses qui se ressemblent seulement mais changent pour des raisons différentes. PHASE 3 — RÈGLES D'ANIMATION : corrige transparent→rgba(0,0,0,0), élimine le transition dupliqué, n'anime pas le shorthand border (utilise borderColor), change background→backgroundColor dans les animations, et assure des keys stables et uniques (jamais l'index) dans les listes avec AnimatePresence. PHASE 4 — PERFORMANCE REACT : enveloppe dans useCallback les handlers passés comme props, mémoïse avec useMemo les calculs coûteux, corrige les tableaux de dépendances de useEffect (ni trop ni trop peu), et ajoute une key stable à chaque .map. NE mémoïse PAS au cas où : seulement là où il y a un bénéfice réel. PHASE 5 — TYPESCRIPT : remplace chaque any par un type réel ou par unknown ; passe en revue chaque cast 'as Type' (est-ce vrai ou est-ce un pansement ?) ; internalise les exports qui ne sont utilisés que dans leur propre fichier ; et type les props de tous les composants. PHASE 6 — EFFONDREMENT DU GPU : déplace les dégradés coniques animés vers des @keyframes CSS ; consolide les repeat:Infinity s'il y en a beaucoup en même temps ; et remplace backdrop-blur par un fond solide/semi-transparent sur les petits éléments qui se répètent beaucoup. PHASE 7 — RAPPORT DE SANTÉ : à la fin, remets-moi un rapport avec : décompte par phase, total de lignes purgées, la confirmation explicite que tu n'as rien changé, ni visuel ni comportemental, et une liste de ce que tu as décidé de NE PAS toucher et pourquoi. Travaille phase par phase, montre-moi le diff de chacune, et si quelque chose met en péril la règle sacrée, ARRÊTE-toi et demande-moi avant de continuer.
6. Vérifie que la chirurgie n'a pas laissé de blessures
Une chirurgie ne se termine pas quand tu refermes : elle se termine quand tu confirmes que le patient va bien. La règle sacrée (zéro changement de comportement), il faut la vérifier, pas seulement lui faire confiance. Il y a deux filets de sécurité automatiques qui te le confirment en quelques secondes, et que ton agent peut lancer sans que tu programmes quoi que ce soit.
# 1) La vérification des types : zéro erreur = la chirurgie n'a pas cassé les contrats npx tsc --noEmit # 2) Les tests : s'ils passaient avant et passent pareil après, # le comportement a été préservé npm test
git diff. Règle de lecture : presque tout ce que tu vois doit être des lignes ROUGES (effacées) ou des déplacements, pas de la logique nouvelle. Si apparaissent des chaînes de texte que l'utilisateur voit modifiées, des valeurs par défaut différentes, ou des conditions nouvelles, il y a là une possible blessure — demande à l'IA pourquoi avant d'accepter.7. Les chemins les plus faciles · ce que fait l'IA par chat et ce que tu décides toi
Pour que ça ne se complique pas : la plus grande partie de la chirurgie, c'est ton agent de code qui la fait seul, par le chat. Ton rôle, c'est de diriger et d'approuver. Voici la répartition.
- Parcourir le module et détecter le code mort, les doublons, les
anyet les animations mal montées — tu ne fais que lui donner le prompt maître. - Appliquer les corrections phase par phase, en te montrant le diff de chacune.
- Lancer
tscet les tests pour confirmer qu'elle n'a rien cassé. - Rédiger le rapport de santé final avec les décomptes et ce qu'elle a décidé de ne pas toucher.
- Faire le commit de sécurité AVANT — ton bouton d'annulation. Ça, tu le fais toi depuis GitHub Desktop ou le chat, avant d'opérer.
- Approuver les effacements douteux — quand l'IA n'est pas sûre que quelque chose est utilisé, elle te demande ; la décision finale est la tienne.
- Vérifier le diff — lire les changements et confirmer qu'il n'y a pas de blessures de comportement avant d'accepter.
- Décider la portée — quel module est opéré et dans quel ordre. Ne délègue pas "opère tout" : vas-y par morceaux.