Pourquoi les conseils au niveau du prompt sont insuffisants
Les conseils de prompt ne sont pas erronés, ils sont simplement éphémères. Si on lui demande d'utiliser une palette chaude, l'agent le fera. Six écrans plus tard, il ne lui reste que l'adjectif et non les valeurs, il improvise donc — et les approximations divergent. C'est le mécanisme qui explique pourquoi les sites créés par IA convergent, et c'est pourquoi les corrections ci-dessous sont toutes formulées comme des valeurs plutôt que comme des instructions.
Règle d'or lors de la lecture : si un changement peut être exprimé par un nombre ou un code hex, placez-le dans les tokens. S'il ne peut être exprimé que par un adjectif, c'est que la décision n'est pas encore finalisée.
1. Teinter les neutres vers votre couleur d'accentuation
C'est la modification au rendement le plus élevé et presque personne ne le fait. Les thèmes par défaut associent une rampe de gris purs à une couleur d'accentuation sans lien, et les deux ne semblent jamais appartenir au même produit. Les design systems professionnels orientent les neutres de quelques degrés vers la teinte d'accentuation, avec un chroma très faible.
/* Default: pure neutral, unrelated to the accent */
--background: oklch(0.145 0 0);
--muted: oklch(0.269 0 0);
--primary: oklch(0.55 0.19 45);
/* Tinted: same lightness, a trace of the accent hue */
--background: oklch(0.145 0.008 45);
--muted: oklch(0.269 0.012 45);
--primary: oklch(0.55 0.19 45);Gardez le chroma réellement bas. Au-delà de 0.02 environ, les gris commencent à être perçus comme colorés plutôt que neutres, et vous remplacez un aspect générique par un autre.
2. Ajouter une seconde famille typographique
Une seule famille pour les titres, le corps de texte, les labels et les chiffres est le moyen le plus rapide de repérer une UI générée. La solution est un appairage avec un vrai contraste — pas deux grotesques similaires, ce qui ressemblerait à un accident plutôt qu'à un choix.
- Serif pour les titres + grotesque pour le corps. Le contraste le plus fiable et le plus difficile à rater.
- Grotesque pour les titres + humaniste pour le corps. Plus discret ; idéal pour les UI de produits denses où un serif paraîtrait trop décoratif.
- Une seule superfamille, deux extrêmes. Un gras condensé face à un regular. Prudent quand la marque doit rester sobre.
- Une mono pour les données. Pas pour la décoration : les chiffres tabulaires empêchent les nombres de sauter entre les lignes.
Quel que soit votre choix, inscrivez les familles exactes, les graisses et l'espacement des lettres (letter-spacing) dans les tokens. « Associer un serif à un sans » est un adjectif, et les adjectifs s'estompent.
3. Adapter le radius à la taille de l'élément
Un seul --radius appliqué partout est le troisième indice. Le radius est perçu *relativement à l'élément sur lequel il se trouve* : ainsi, un 8px identique rendra un petit bouton trop arrondi et une grande carte à peine arrondie.
/* One value, applied to everything */
--radius: 0.5rem;
/* Scaled to element size */
--radius-sm: 0.25rem; /* inputs, chips, badges */
--radius-md: 0.5rem; /* buttons, small controls */
--radius-lg: 0.875rem; /* cards, panels */
--radius-xl: 1.25rem; /* modals, sheets, hero surfaces */4. Briser la grille uniforme
Trois cartes identiques suggèrent que chaque élément a le même poids. C'est presque toujours faux, et une mise en page qui prétend le contraire ne donne aucune information sur le produit.
Le changement est éditorial plutôt que technique : décidez quel élément est réellement le plus important et laissez la mise en page l'exprimer. Une carte large au-dessus de deux étroites. Un split deux-tiers/un-tiers. Une seule fonctionnalité avec un véritable visuel de soutien plutôt que trois icônes. La grille convient lorsque les éléments sont réellement pairs — l'erreur est de l'utiliser par défaut.
Consistency check · No type scale
The same plan card, built two ways in Mauve Broadcast.
Pricing
Everything a small team needs to ship a branded UI.
Pricing
Everything a small team needs to ship a branded UI.
5. Définir un modèle d'élévation
L'UI générée utilise généralement une seule ombre, appliquée à tout élément devant paraître surélevé. Les véritables systèmes d'élévation disposent de deux ou trois niveaux cohérents quant à la source de lumière, et utilisent des variations de bordures et de fonds en plus de l'ombre — et souvent à sa place.
/* One shadow doing every job */
--shadow: 0 1px 3px rgb(0 0 0 / 0.1);
/* Levels that agree about a light source */
--elevation-0: none; /* flush: use a border */
--elevation-1: 0 1px 2px rgb(0 0 0 / 0.06); /* cards */
--elevation-2: 0 4px 12px rgb(0 0 0 / 0.08); /* dropdowns */
--elevation-3: 0 16px 40px rgb(0 0 0 / 0.12); /* modals */6. Écrivez-le là où l'agent pourra le relire
Les cinq modifications ci-dessus n'ont que peu de valeur si elles restent dans une conversation. Intégrez-les dans un fichier DESIGN.md ainsi que dans des fichiers de tokens dans le repo ; l'agent appliquera alors les mêmes valeurs à chaque exécution — même lors d'une session ouverte le mois prochain.
- 1
Installer le contrat de design
Écrit le fichier DESIGN.md et les fichiers de tokens dans le projet.
npx --yes identityforge@latest install --client claude-code - 2
Appliquer un kit qui intègre déjà ces choix
Neutres teintés, appairage typographique réel, rayons d'arrondi gradués et modèle d'élévation : tout est déjà défini.
identityforge apply terrain-vivant - 3
Le référencer dans votre fichier d'agent
Une seule ligne dans AGENTS.md pour que le contrat soit explicitement trouvé plutôt que découvert par hasard.
Never hardcode theme colors. Use the semantic tokens in DESIGN.md. - 4
Vérifier la persistance
Ouvrez une nouvelle session, créez un écran sans rapport et comparez sa couleur primaire et son radius avec le premier. S'ils sont identiques, c'est que les valeurs sont lues et non mémorisées.
Ce qui semble encore généré après ces six étapes
Chaque guide sur cette SERP s'arrête à la liste des corrections. C'est une erreur, car deux indices persistent malgré ces six changements, et ce sont ceux que les gens remarquent sans savoir les nommer. Tous deux se situent en dehors du fichier de tokens tel qu'il est habituellement écrit, et c'est précisément pour cela qu'ils persistent.
Tout bouge de la même manière
Les interfaces générées n'ont qu'une seule animation : un court fondu avec une légère translation vers le haut, appliqué à chaque élément qui apparaît. On le retrouve sur le hero, les cartes, la modale et le toast. Rien dans le mouvement n'indique la nature de l'événement, donnant au produit l'impression d'un diaporama continu.
Le mouvement prend du sens lorsque la durée et l'easing varient selon *ce que fait l'élément*, et non selon sa position. La distinction à encoder se fait entre les éléments qui répondent à l'utilisateur et ceux qui apparaissent d'eux-mêmes :
| Élément | Durée | Easing | |
|---|---|---|---|
| Réponse à un clic ou survol | Un contrôle qui accuse réception | 100–150ms | ease-out — démarrage rapide, l'action doit sembler déjà terminée |
| Entrée d'un élément | Un menu, un popover ou un panneau | 200–250ms | ease-out, la transformation effectuant l'essentiel du travail |
| Sortie d'un élément | Fermeture du même élément | 120–180ms | ease-in — les sorties doivent être plus rapides que les entrées |
L'asymétrie de cette dernière ligne est l'aspect que presque aucune interface générée ne maîtrise : les sorties s'exécutent à la même vitesse que les entrées, ce qui rend la fermeture de tout élément « collante ». Définissez ces trois durées comme des tokens et l'agent cessera d'utiliser un chiffre unique pour tout.
/* One duration, one curve, applied to everything */
--transition: 200ms ease;
/* Motion that says what kind of event it was */
--motion-response: 120ms cubic-bezier(0, 0, 0.2, 1);
--motion-enter: 220ms cubic-bezier(0, 0, 0.2, 1);
--motion-exit: 160ms cubic-bezier(0.4, 0, 1, 1);
@media (prefers-reduced-motion: reduce) {
--motion-response: 1ms;
--motion-enter: 1ms;
--motion-exit: 1ms;
}Tous les produits utilisent les mêmes icônes
Le second indice est l'iconographie. Une installation par défaut vous donne un ensemble open-source avec une seule épaisseur de trait, et comme cet ensemble est livré avec la bibliothèque de composants, les mêmes vingt glyphes apparaissent sur des milliers de produits. Vous pouvez changer chaque couleur et chaque police, le produit restera reconnaissable rien qu'aux icônes.
Remplacer l'ensemble n'en vaut généralement pas la peine. Le contraindre, si :
- Alignez l'épaisseur du trait sur le poids de votre typographie. Un trait de 1.5px face à un corps de texte léger semble emprunté ; face à un poids medium, il semble assorti. Choisissez une valeur et intégrez-la dans vos tokens.
- Liez la taille au texte adjacent, afin qu'une icône dans un bouton et une icône dans une ligne de tableau n'aient pas la même taille en pixels par pur hasard.
- Bannissez les icônes décoratives. Interdisez les icônes qui servent à évoquer une ambiance plutôt qu'une action — les étincelles, les fusées et les éclairs sont les signaux les plus flagrants d'une UI générée, même après un changement complet de thème.
- Autorisez une seule exception et nommez-la. Un unique glyphe personnalisé, généralement la marque, utilisé à un endroit cohérent. Un seul écart délibéré est perçu comme une décision ; plusieurs sont perçus comme un accident.
Le test de l'étincelle
Si un écran contient une icône d'étincelle, un dégradé du violet au bleu et le mot « seamlessly », aucun des six changements de tokens ci-dessus ne pourra le sauver. Ces trois éléments relèvent de décisions de contenu et d'iconographie, et ils doivent être interdits par écrit car aucune palette ne peut les annuler.
Ce que les gens font mal dans leurs fichiers
Rédiger les six changements est la partie facile. Nous avons analysé 299 fichiers DESIGN.md publics sur GitHub pour voir ce que les utilisateurs commitent réellement, et le schéma d'échec est suffisamment constant pour mériter d'être anticipé.
| Part des fichiers | |
|---|---|
| Omettent totalement le mode sombre | 69% |
| N'utilisent aucun nom de rôle de couleur sémantique | 86% |
| N'énoncent aucune interdiction | 76% |
| N'énoncent aucun motif ni principe | 57% |
| Ne contiennent aucune valeur de taille concrète | 44% |
| Utilisent un adjectif vague là où une valeur est requise | 54% |
| Spécifient une échelle de rayons (radius) | 21% |
Comparez cela aux six changements ci-dessus et le chevauchement est exact. L'échelle des rayons est spécifiée dans un fichier sur cinq. Les interdictions — la chose la plus simple à écrire et la plus fiable à suivre — sont absentes dans trois quarts des cas. Et les mots les plus courants utilisés pour remplacer une décision étaient *clean* (39% des fichiers), *modern* (36%) et *professional* (22%).
L'écrire n'est pas la même chose que de le décider
Plus de la moitié des fichiers réels contiennent au moins un adjectif là où une valeur est requise. Un agent à qui l'on demande du « clean et modern » doit interpréter cela, et il le fait différemment à chaque fois. Si une ligne peut produire deux écrans différents pour deux lecteurs compétents, c'est que la décision n'a pas encore été prise.
La conséquence pratique pour les six changements : rédigez chacun d'eux sous forme de nombre ou de code hex, et vérifiez que votre propre fichier ne contient pas les trois adjectifs cités plus haut avant de le commiter.
Les six, déjà décidés
Chaque kit Identity Forge inclut des neutres teintés, un véritable duo de polices, un ensemble de rayons d'arrondi gradués et un modèle d'élévation — accompagnés du fichier DESIGN.md qui garantit leur cohérence d'une session à l'autre. Les kits gratuits ne nécessitent aucun compte.
Quel changement unique apporte la plus grande amélioration ?
Teinter les neutres. Cela ne nécessite aucun travail de mise en page, aucune nouvelle police ni aucun redesign — vous ajustez la chroma de valeurs existantes, et cela change la perception de l'ensemble de la page.
L'ajout d'une seconde police nuira-t-il aux performances ?
Marginalement, et c'est gérable. Deux familles avec deux graisses chacune représentent environ 60–120 KB en woff2 avec subsetting, chargées une seule fois. Les polices variables réduisent encore ce poids. C'est un compromis acceptable pour éliminer l'indice visuel le plus flagrant de la page.
Ai-je besoin d'OKLCH pour les neutres teintés ?
Non, mais cela facilite grandement la tâche. OKLCH sépare la luminosité de la chroma, vous permettant ainsi d'ajouter une nuance de teinte sans modifier la luminosité perçue. En HSL, la même modification déplace également la luminosité, ce qui oblige à réajuster toute la palette.
S'agit-il simplement de thémisation ?
En partie, et c'est justement le point — la majeure partie de ce qui semble « générique » réside dans des valeurs déjà gérées par une couche de thème. Les éléments qui ne relèvent pas de la thémisation sont le choix de la grille et le modèle d'élévation, qui sont structurels.
Comment empêcher l'agent de passer outre ces réglages ?
Énoncez la contrainte sous forme d'interdiction plutôt que de préférence. « Ne jamais coder les couleurs du thème en dur ; utilisez les tokens sémantiques » est suivi bien plus rigoureusement que « préférez les tokens sémantiques ».