Figma → landing page en HTML/CSS/JS
Ce skill convertit une maquette de landing page depuis Figma en HTML, CSS et JS statiques. Le travail se fait bloc par bloc : après chaque bloc, l'agent marque une pause et attend la confirmation de l'utilisateur.
Les règles de mise en page (structure, BEM, unités, images, hover, etc.) se trouvent dans templates/AGENTS.md de ce skill. À l'étape 3, ce fichier est copié à la racine du projet et s'applique désormais en permanence.
Prérequis
- Figma MCP connecté (
get_metadata,get_design_context,get_screenshot, et si disponible —get_variable_defs). S'il n'est pas présent, le signaler à l'utilisateur et s'arrêter. - L'utilisateur a fourni un lien de la forme
https://www.figma.com/design/:fileKey/:fileName?node-id=1-2. - Node.js est nécessaire pour le serveur, les captures d'écran et le WebP. Les commandes
npxtéléchargent des paquets depuis le réseau lors du premier lancement — Codex peut demander une autorisation, c'est normal.
Déroulement
Exécuter les étapes dans l'ordre, sans en sauter.
Étape 1. Analyser le lien
fileKey— la partie après/design/. Si le lien contient/branch/:branchKey/, utiliserbranchKey.nodeId— la valeur denode-id, remplacer le tiret par deux-points (1-2→1:2).- Le lien peut pointer vers le document entier, une page, une frame desktop ou une frame mobile. Déterminer le type à l'étape 2.
Étape 2. Carte de la maquette
- Appeler
get_metadatapour le nœud du lien (pour le document entier — sansnode-idou avec la page racine). - Trouver les frames versions de la landing page : desktop, mobile, parfois tablette. Les largeurs sont déterminées à partir de la maquette, ne pas utiliser de valeurs par défaut. Trouver également les frames séparés des fenêtres modales (popups) et du menu mobile ouvert, s'ils existent sur la page.
- À l'intérieur de chaque frame, identifier les sections de premier niveau (en-tête, hero, avantages, témoignages, pied de page, etc.).
- Faire correspondre les sections entre les versions : « section desktop ↔ section mobile » (par nom de calque, ordre et contenu).
- Présenter la carte à l'utilisateur et attendre sa confirmation :
Largeurs : desktop 1440, mobile 375
1. header — 12:30 ↔ 40:2
2. hero — 12:45 ↔ 40:18
3. advantages — 13:10 ↔ 41:5
...
Fenêtres modales / menu :
- mobile-menu — 45:12
- popup-order — 46:01
Si la version mobile n'existe pas — le signaler et demander comment procéder.
Étape 3. Structure du projet et UI de base
- Si le fichier
AGENTS.mdn'existe pas à la racine du projet — copiertemplates/AGENTS.mddepuis le dossier du skill. Remplir dans ce fichier la section « Ce landing page » (largeurs, conteneur, polices) avec les données de l'étape 2. Conserver les points de rupture par défaut ; ne les modifier que si la mise en page de cette maquette casse à d'autres largeurs — et dans ce cas, noter les nouvelles valeurs. - Créer la structure :
index.html,style.css,script.js,assets/icons/. index.html:<!doctype html>,lang="fr",charset,viewport,<title>et<meta name="description">en fonction du sens de la landing page. Ne pas ajouter de favicon. Inclurescript.jsavecdefer.- Polices : les extraire de
get_design_context/get_variable_defs, les connecter via Google Fonts en ne chargeant que les graisses nécessaires, avecdisplay=swap. Si une police n'est pas disponible sur Google Fonts — demander les fichiers à l'utilisateur, les inclure via@font-facedepuisassets/fonts/. style.css: réinitialisation des styles (voirAGENTS.md), puis:rootavec les variables de couleurs, polices, espacements, largeur du conteneur. Prendre les valeurs depuisget_variable_defssi des variables existent dans la maquette ; sinon, les extraire de la maquette et les arrondir.- Composants de base : identifier les éléments transversaux de la maquette (boutons, titres de sections, champs de saisie) et les transformer en classes réutilisables (
.btn,.section-title,.input,.container). Si la maquette ne contient pas de kit UI avec les états (hover,focus,active), demander une seule fois à l'utilisateur les règles de survol pour les boutons et liens typiques de tout le projet. Noter la réponse dans la ligne « UI-états » de la section « Ce landing page » dansAGENTS.md. - Outils (une seule fois) :
- lancer en arrière-plan un serveur local depuis la racine du projet :
npx -y serve -l 3000(solution de repli —python3 -m http.server 3000). Toutes les captures d'écran doivent être prises depuishttp://localhost:3000, pas depuisfile://; - vérifier l'outil de capture d'écran : Playwright MCP s'il est connecté ; sinon, le script
scripts/shot.cjs(voir « Auto-vérification ») ; - vérifier le convertisseur d'images (voir « Images ») et mémoriser le résultat.
- lancer en arrière-plan un serveur local depuis la racine du projet :
- Informer l'utilisateur que la structure est prête, puis passer au premier bloc.
Étape 4. Blocs un par un
Pour chaque section de la carte, dans l'ordre strict du haut vers le bas (y compris les sections avec formulaires) :
- Données.
get_design_contextetget_screenshotpour la section desktop et pour sa paire mobile.- Si la réponse est tronquée ou trop volumineuse — appeler
get_metadatasur la section et récupérer les nœuds enfants un par un. - Le code présent dans la réponse (généralement React + Tailwind) sert uniquement d'information sur les dimensions, couleurs et structure. Ne pas copier son style.
- Si la réponse est tronquée ou trop volumineuse — appeler
- Images. Télécharger et traiter les assets du bloc (voir « Images »).
- Mise en page. HTML du bloc dans
index.html, styles dansstyle.cssdans une section séparée avec le commentaire/* ===== hero ===== */, JS (si nécessaire) dansscript.js. Utiliser les classes de base de l'étape 3.6, sans dupliquer le code des boutons et titres. D'abord desktop, puis adaptation jusqu'au mobile viaclamp()et media queries.- Pour
headeren largeur mobile, réaliser immédiatement le menu hamburger (en utilisant la frame de la carte ou en précisant l'aspect à l'utilisateur). - Si le bloc contient un formulaire — le structurer avec les attributs de validation HTML de base (
required,type="email",type="tel",pattern), mais sans logique JavaScript d'envoi.
- Pour
- Auto-vérification. Prendre une capture uniquement de la section courante aux largeurs desktop, mobile et intermédiaires (1024, 768). Comparer avec les captures d'écran Figma : espacements, dimensions, polices, couleurs, retours à la ligne. Corriger les écarts et recapturer.
- Avec Playwright MCP — capture d'écran de l'élément de la section à chaque largeur.
- Sans MCP — script depuis le dossier du skill :
Le script enregistre# une fois mkdir -p .screens && cp <dossier-du-skill>/scripts/shot.cjs .screens/ npm i playwright --prefix .screens && npx -y playwright install chromium # après chaque bloc node .screens/shot.cjs http://localhost:3000 .hero 1440,1024,768,375.screens/<section>-<largeur>.pnget affiche⚠ défilement horizontalsi la page dépasse la largeur de l'écran. Tout avertissement de ce type doit être corrigé (ne pas masquer avecoverflow: hiddensurbody). - Supprimer les captures des sections après confirmation du bloc ; conserver le script et
node_modulesdans.screens/pour l'étape 6.
- Rapport et arrêt. Faire un court rapport à l'utilisateur : ce qui a été fait, où des écarts par rapport à la maquette se sont produits et pourquoi, ce qui doit être précisé concernant les éléments interactifs uniques du bloc (hover non standard des cartes, paramètres du slider). Attendre la confirmation. Appliquer les corrections demandées par l'utilisateur dans ce même bloc, puis attendre à nouveau.
- Ce n'est qu'après un « ok » que l'on passe au bloc suivant.
Étape 5. Fenêtres modales et logique des formulaires
Après la mise en page de toutes les sections principales :
- Structurer les fenêtres modales (popups) cachées, si elles ont été trouvées à l'étape 2, et connecter les déclencheurs d'ouverture/fermeture (boutons,
Esc, clic sur l'overlay). Comportement selon la section « JavaScript » dansAGENTS.md. - Chaque fenêtre est traitée comme un bloc séparé : auto-vérification par captures d'écran en état ouvert, rapport et attente de confirmation.
- Vérifier le fonctionnement de tous les formulaires de la page. Ne pas implémenter d'envoi de données (
fetch/AJAX) tant que l'utilisateur ne le demande pas explicitement et ne fournit pas une adresse (endpoint) ou un cahier des charges.
Étape 6. Finalisation
Après confirmation de la dernière étape : vérifier l'ensemble de la page à toutes les largeurs, supprimer les fichiers et dossiers temporaires (assets/_raw/, .screens/ entièrement), arrêter le serveur local en arrière-plan, supprimer les styles et images inutilisés. Rédiger un court résumé.
Images
- Récupérer les assets du bloc depuis la réponse Figma MCP (liens vers les images dans
get_design_context). Si l'adresse est unlocalhost— télécharger directement. Ne pas utiliser de placeholders ni de jeux d'icônes externes. - Télécharger dans un dossier temporaire
assets/_raw/<bloc>/, les images bitmap en 2× la taille affichée dans la maquette (2x). - Graphiques responsives : si la version mobile du bloc utilise une image recadrée (proportions différentes) ou une image différente par son contenu — télécharger les deux versions (
hero-bg-desktop.webpethero-bg-mobile.webp) et les intégrer via<picture>. - Tri :
- petites icônes dans les éléments interactifs (boutons, liens) qui doivent changer de couleur (
fill/stroke) au survol →<svg>inline dans le HTML avecfill="currentColor"(ou via CSSmask-image) ; - icônes statiques, logos, graphiques simples → SVG dans
assets/icons/via<img>(ou dans le dossier du bloc s'il s'agit de graphiques volumineux). Si l'icône est fournie en bitmap — le signaler à l'utilisateur ; - photos et images complexes → WebP dans
assets/<bloc>/.
- petites icônes dans les éléments interactifs (boutons, liens) qui doivent changer de couleur (
- Conversion en WebP, qualité 80. Ordre des tentatives :
npx -y sharp-cli -i in.png -o out.webp -f webp -q 80(nécessite Node.js) ;cwebp -q 80 in.png -o out.webp;- rien de disponible — conserver le format d'origine et une seule fois informer l'utilisateur qu'il doit installer (Node.js ou
cwebp), sans interrompre le travail.
- Si le WebP obtenu est plus lourd que l'original — conserver l'original.
- Noms de fichiers : latin, minuscules, avec des tirets, descriptifs (
hero-photo.webp,arrow-right.svg). - Après confirmation du bloc, supprimer
assets/_raw/<bloc>/.
Hover, animations, sliders
- Hover : pour les boutons et liens de base — règles issues de la ligne « UI-états » dans
AGENTS.md. Si le bloc contient des cartes/éléments interactifs uniques sans états dans la maquette — ne pas inventer, mais demander à l'utilisateur dans le rapport du bloc. - Animations au défilement et animations personnalisées — uniquement si l'utilisateur le demande explicitement. D'abord préciser ce qui doit se passer. Simple (apparition au défilement) —
IntersectionObserver; complexe (liaison à la molette, sections « collantes », parallaxe) — GSAP via CDN, seulement après accord de l'utilisateur. Toujours respecterprefers-reduced-motion. - Slider : simple (flèches, points, swipe) — CSS
scroll-snap+ un peu de JS. Complexe (infini, lecture automatique, effets, sliders liés) — Swiper via CDN.
Problèmes fréquents
- Réponse Figma tronquée → appeler
get_metadatasur la section, puisget_design_contextsur les nœuds enfants. - La paire mobile de la section ou la frame du menu mobile n'est pas visible → demander à l'utilisateur, ne pas inventer.
- La police ne correspond pas en largeur à la maquette → vérifier la graisse et
letter-spacing, ne pas modifier la taille de la police. - Les images ne se téléchargent pas → vérifier que Figma MCP est en cours d'exécution ; utiliser les liens sans modification.
- Sur la capture d'écran, les polices ou les icônes sont décalées → vérifier que le serveur est lancé sur
localhost:3000et que la capture provient de cette URL, pas defile://. - Le script indique « défilement horizontal » → trouver l'élément plus large que l'écran (largeur fixe, grand
gap, décor débordant) et le corriger ; pour les éléments décoratifs en dehors des limites — utiliseroverflow-x: clipsur leur section. - Écart par rapport à la maquette pour des raisons d'accessibilité ou de limitations techniques → acceptable, mais le mentionner dans le rapport du bloc.