figma-generate-design

Utilisez cette compétence en tandem avec figma-use lorsque la tâche implique de traduire une page d'application, une vue ou une mise en page multi-sections dans Figma. Déclencheurs : « write to Figma », « create in Figma from code », « push page to Figma », « take this app/page and build it in Figma », « create a screen », « build a landing page in Figma », « update the Figma screen to match code ». Ceci est la compétence de flux de travail préférée chaque fois que l'utilisateur souhaite construire ou mettre à jour une page entière, un écran ou une vue dans Figma à partir du code ou d'une description. Découvre les composants du système de conception, les variables et les styles via search_design_system, les importe et assemble les écrans de manière progressive section par section en utilisant les jetons du système de conception au lieu de valeurs codées en dur.

npx skills add https://github.com/openai/skills --skill figma-generate-design

Créer / Mettre à jour les écrans à partir du système de design

Utilisez cette compétence pour créer ou mettre à jour des écrans complets dans Figma en réutilisant le système de design publié — composants, variables et styles — plutôt que de dessiner des primitives avec des valeurs codées en dur. L'idée clé : le fichier Figma contient probablement un système de design publié avec des composants, des variables de couleur/espacement et des styles de texte/effet qui correspondent aux composants UI et aux tokens du codebase. Trouvez et utilisez-les au lieu de dessiner des boîtes avec des couleurs hex.

OBLIGATOIRE : Vous DEVEZ également charger figma-use avant tout appel use_figma. Cette compétence contient des règles critiques (plages de couleurs, chargement de polices, etc.) qui s'appliquent à chaque script que vous écrivez.

Passez toujours skillNames: "figma-generate-design" lors de l'appel de use_figma dans le cadre de cette compétence. Ceci est un paramètre de journalisation — cela n'affecte pas l'exécution.

Limites de la compétence

  • Utilisez cette compétence quand le livrable est un écran Figma (nouveau ou mis à jour) composé d'instances de composants du système de design.
  • Si l'utilisateur souhaite générer du code à partir d'une conception Figma, basculez vers figma-implement-design.
  • Si l'utilisateur souhaite créer des composants ou variantes réutilisables, utilisez figma-use directement.
  • Si l'utilisateur souhaite écrire des mappages Code Connect, basculez vers figma-code-connect-components.

Prérequis

  • Le serveur MCP Figma doit être connecté
  • Le fichier Figma cible doit avoir un système de design publié avec des composants (ou un accès à une bibliothèque d'équipe)
  • L'utilisateur doit fournir soit :
    • Une URL de fichier Figma / clé de fichier pour travailler dedans
    • Ou du contexte sur le fichier à cibler (l'agent peut découvrir les pages)
  • Le code source ou la description de l'écran à créer/mettre à jour

Workflow parallèle avec generate_figma_design (applications Web uniquement)

Lors de la création d'un écran à partir d'une application web qui peut être rendue dans un navigateur, les meilleurs résultats proviennent de l'exécution des deux approches en parallèle :

  1. En parallèle :
    • Commencez à créer l'écran en utilisant le workflow de cette compétence (use_figma + composants du système de design)
    • Exécutez generate_figma_design pour capturer une capture d'écran pixel-parfaite de l'application web en cours d'exécution
  2. Une fois les deux terminés : Mettez à jour la sortie use_figma pour correspondre à la mise en page pixel-parfaite de la capture generate_figma_design. La capture fournit l'espacement exact, le dimensionnement et le traitement visuel à viser, tandis que votre sortie use_figma dispose d'instances de composants appropriées liées au système de design.
  3. Une fois confirmé que c'est bon : Supprimez la sortie generate_figma_design — elle n'a été utilisée que comme référence visuelle.

Cela combine le meilleur des deux : generate_figma_design donne une précision de mise en page pixel-parfaite, tandis que use_figma donne des instances de composants du système de design appropriées qui restent liées et mises à jour.

Ce workflow s'applique uniquement aux applications webgenerate_figma_design peut capturer la page en cours d'exécution. Pour les applications non-web (iOS, Android, etc.) ou lors de la mise à jour d'écrans existants, utilisez le workflow standard ci-dessous.

Workflow obligatoire

Suivez ces étapes dans l'ordre. Ne sautez pas d'étapes.

Étape 1 : Comprendre l'écran

Avant de toucher à Figma, comprenez ce que vous créez :

  1. Si vous créez à partir du code, lisez les fichiers source pertinents pour comprendre la structure de la page, les sections et les composants utilisés.
  2. Identifiez les sections principales de l'écran (par ex. En-tête, Héros, Panneaux de contenu, Grille de tarification, Accordéon FAQ, Pied de page).
  3. Pour chaque section, listez les composants UI impliqués (boutons, entrées, cartes, pilules de navigation, accordéons, etc.).

Étape 2 : Découvrir le système de design — Composants, variables et styles

Vous avez besoin de trois choses du système de design : composants (boutons, cartes, etc.), variables (couleurs, espacement, rayons), et styles (styles de texte, styles d'effet comme les ombres). Ne codez pas en dur les couleurs hex ou les valeurs en pixels quand les tokens du système de design existent.

2a : Découvrir les composants

Préféré : inspectez d'abord les écrans existants. Si le fichier cible contient déjà des écrans utilisant le même système de design, ignorez search_design_system et inspectez directement les instances existantes. Un seul appel use_figma qui parcourt les instances d'un cadre existant vous donne une carte de composants exacte et faisant autorité :

const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const uniqueSets = new Map();
frame.findAll(n => n.type === "INSTANCE").forEach(inst => {
  const mc = inst.mainComponent;
  const cs = mc?.parent?.type === "COMPONENT_SET" ? mc.parent : null;
  const key = cs ? cs.key : mc?.key;
  const name = cs ? cs.name : mc?.name;
  if (key && !uniqueSets.has(key)) {
    uniqueSets.set(key, { name, key, isSet: !!cs, sampleVariant: mc.name });
  }
});
return [...uniqueSets.values()];

Retournez à search_design_system uniquement quand le fichier n'a pas d'écrans existants à référencer. Lorsque vous l'utilisez, recherchez largement — essayez plusieurs termes et synonymes (par ex. "button", "input", "nav", "card", "accordion", "header", "footer", "tag", "avatar", "toggle", "icon", etc.). Utilisez includeComponents: true pour vous concentrer sur les composants.

Incluez les propriétés des composants dans votre carte — vous devez savoir quelles propriétés TEXT chaque composant expose pour les remplacements de texte. Créez une instance temporaire, lisez son componentProperties (et celles des instances imbriquées), puis supprimez l'instance temporaire.

Exemple de carte de composants avec informations sur les propriétés :

Component Map:
- Button → key: "abc123", type: COMPONENT_SET
  Properties: { "Label#2:0": TEXT, "Has Icon#4:64": BOOLEAN }
- PricingCard → key: "ghi789", type: COMPONENT_SET
  Properties: { "Device": VARIANT, "Variant": VARIANT }
  Nested "Text Heading" has: { "Text#2104:5": TEXT }
  Nested "Button" has: { "Label#2:0": TEXT }

2b : Découvrir les variables (couleurs, espacement, rayons)

Inspectez d'abord les écrans existants (identique aux composants). Ou utilisez search_design_system avec includeVariables: true.

AVERTISSEMENT : Deux méthodes de découverte de variables différentes — ne les confondez pas.

  • use_figma avec figma.variables.getLocalVariableCollectionsAsync() — retourne uniquement les variables locales définies dans le fichier courant. Si cela retourne vide, cela ne signifie pas qu'aucune variable n'existe. Les variables de bibliothèque distantes/publiées sont invisibles pour cette API.
  • search_design_system avec includeVariables: true — recherche dans toutes les bibliothèques liées, y compris les variables distantes et publiées. C'est l'outil correct pour découvrir les variables du système de design.

Ne concluez jamais "aucune variable n'existe" basé uniquement sur getLocalVariableCollectionsAsync() retournant vide. Exécutez toujours aussi search_design_system avec includeVariables: true pour vérifier les variables de bibliothèque avant de décider d'en créer.

Stratégie de requête : search_design_system correspond aux noms de variables (par ex. "Gray/gray-9", "core/gray/100", "space/400"), pas aux catégories. Exécutez plusieurs requêtes courtes et simples en parallèle plutôt qu'une requête composée :

  • Couleurs primitives : "gray", "red", "blue", "green", "white", "brand"
  • Couleurs sémantiques : "background", "foreground", "border", "surface", "text"
  • Espacement/dimensionnement : "space", "radius", "gap", "padding"

Si les recherches initiales retournent vide, essayez des fragments plus courts ou des conventions de nommage différentes — les bibliothèques varient largement ("grey" vs "gray", "spacing" vs "space", "color/bg" vs "background").

Inspectez les variables liées d'un écran existant pour les résultats les plus faisant autorité :

const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const varMap = new Map();
frame.findAll(() => true).forEach(node => {
  const bv = node.boundVariables;
  if (!bv) return;
  for (const [prop, binding] of Object.entries(bv)) {
    const bindings = Array.isArray(binding) ? binding : [binding];
    for (const b of bindings) {
      if (b?.id && !varMap.has(b.id)) {
        const v = await figma.variables.getVariableByIdAsync(b.id);
        if (v) varMap.set(b.id, { name: v.name, id: v.id, key: v.key, type: v.resolvedType, remote: v.remote });
      }
    }
  }
});
return [...varMap.values()];

Pour les variables de bibliothèque (remote = true), importez-les par clé avec figma.variables.importVariableByKeyAsync(key). Pour les variables locales, utilisez figma.variables.getVariableByIdAsync(id) directement.

Voir variable-patterns.md pour les modèles de liaison.

2c : Découvrir les styles (styles de texte, styles d'effet)

Recherchez des styles en utilisant search_design_system avec includeStyles: true et des termes comme "heading", "body", "shadow", "elevation". Ou inspectez ce qu'un écran existant utilise :

const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const styles = { text: new Map(), effect: new Map() };
frame.findAll(() => true).forEach(node => {
  if ('textStyleId' in node && node.textStyleId) {
    const s = figma.getStyleById(node.textStyleId);
    if (s) styles.text.set(s.id, { name: s.name, id: s.id, key: s.key });
  }
  if ('effectStyleId' in node && node.effectStyleId) {
    const s = figma.getStyleById(node.effectStyleId);
    if (s) styles.effect.set(s.id, { name: s.name, id: s.id, key: s.key });
  }
});
return {
  textStyles: [...styles.text.values()],
  effectStyles: [...styles.effect.values()]
};

Importez les styles de bibliothèque avec figma.importStyleByKeyAsync(key), puis appliquez avec node.textStyleId = style.id ou node.effectStyleId = style.id.

Voir text-style-patterns.md et effect-style-patterns.md pour les détails.

Étape 3 : Créer d'abord le cadre du wrapper de page

Ne construisez PAS les sections en tant qu'enfants de niveau page et ne les réorganisez pas plus tard — le déplacement de nœuds entre les appels use_figma avec appendChild() échoue silencieusement et produit des cadres orphelins. Au lieu de cela, créez d'abord le wrapper, puis construisez chaque section directement à l'intérieur.

Créez le wrapper de page dans son propre appel use_figma. Positionnez-le loin du contenu existant et retournez son ID :

// Trouvez un espace libre
let maxX = 0;
for (const child of figma.currentPage.children) {
  maxX = Math.max(maxX, child.x + child.width);
}

const wrapper = figma.createFrame();
wrapper.name = "Homepage";
wrapper.layoutMode = "VERTICAL";
wrapper.primaryAxisAlignItems = "CENTER";
wrapper.counterAxisAlignItems = "CENTER";
wrapper.resize(1440, 100);
wrapper.layoutSizingHorizontal = "FIXED";
wrapper.layoutSizingVertical = "HUG";
wrapper.x = maxX + 200;
wrapper.y = 0;

return { success: true, wrapperId: wrapper.id };

Étape 4 : Construire chaque section à l'intérieur du wrapper

C'est l'étape la plus importante. Construisez une section à la fois, chacune dans son propre appel use_figma. Au début de chaque script, récupérez le wrapper par ID et ajoutez directement le nouveau contenu à celui-ci.

const createdNodeIds = [];
const wrapper = await figma.getNodeByIdAsync("WRAPPER_ID_FROM_STEP_3");

// Importez les composants du système de design par clé
const buttonSet = await figma.importComponentSetByKeyAsync("BUTTON_SET_KEY");
const primaryButton = buttonSet.children.find(c =>
  c.type === "COMPONENT" && c.name.includes("variant=primary")
) || buttonSet.defaultVariant;

// Importez les variables du système de design pour les couleurs et l'espacement
const bgColorVar = await figma.variables.importVariableByKeyAsync("BG_COLOR_VAR_KEY");
const spacingVar = await figma.variables.importVariableByKeyAsync("SPACING_VAR_KEY");

// Construisez le cadre de section avec les liaisons de variables (pas les valeurs codées en dur)
const section = figma.createFrame();
section.name = "Header";
section.layoutMode = "HORIZONTAL";
section.setBoundVariable("paddingLeft", spacingVar);
section.setBoundVariable("paddingRight", spacingVar);
const bgPaint = figma.variables.setBoundVariableForPaint(
  { type: 'SOLID', color: { r: 0, g: 0, b: 0 } }, 'color', bgColorVar
);
section.fills = [bgPaint];

// Importez et appliquez les styles de texte/effet
const shadowStyle = await figma.importStyleByKeyAsync("SHADOW_STYLE_KEY");
section.effectStyleId = shadowStyle.id;

// Créez des instances de composants à l'intérieur de la section
const btnInstance = primaryButton.createInstance();
section.appendChild(btnInstance);
createdNodeIds.push(btnInstance.id);

// Ajoutez la section au wrapper
wrapper.appendChild(section);
section.layoutSizingHorizontal = "FILL"; // APRÈS l'ajout

createdNodeIds.push(section.id);
return { success: true, createdNodeIds };

Après chaque section, validez avec get_screenshot avant de passer à la suivante. Regardez attentivement le texte coupé/clippé (les hauteurs de ligne qui coupent le contenu) et les éléments qui se chevauchent — ce sont les problèmes les plus courants et faciles à manquer à première vue.

Remplacer le texte de l'instance avec setProperties()

Les instances de composants sont livrées avec du texte d'espace réservé ("Title", "Heading", "Button"). Utilisez les clés de propriété de composant que vous avez découvertes à l'étape 2 pour les remplacer avec setProperties() — c'est plus fiable que la manipulation directe de node.characters. Voir component-patterns.md pour le modèle complet.

Pour les instances imbriquées qui exposent leurs propres propriétés TEXT, appelez setProperties() sur l'instance imbriquée :

const nestedHeading = cardInstance.findOne(n => n.type === "INSTANCE" && n.name === "Text Heading");
if (nestedHeading) {
  nestedHeading.setProperties({ "Text#2104:5": "Actual heading from source code" });
}

Retournez uniquement à node.characters direct pour le texte qui n'est PAS géré par une propriété de composant.

Lire attentivement les valeurs par défaut du code source

Lors de la traduction de composants de code en instances Figma, vérifiez les valeurs de propriété par défaut du composant dans le code source, pas seulement ce qui est explicitement passé. Par exemple, <Button size="small">Register</Button> sans propriété variant — vérifiez la définition du composant pour trouver variant = "primary" comme valeur par défaut. Sélectionner la mauvaise variante (par ex. Neutral au lieu de Primary) produit un résultat visuellement incorrect qui est facile à manquer.

Quoi construire manuellement vs. importer du système de design

Construire manuellement Importer du système de design
Cadre wrapper de page Composants : boutons, cartes, entrées, nav, etc.
Cadres de conteneur de section Variables : couleurs (remplissages, contours), espacement (padding, gap), rayons
Grilles de mise en page (lignes, colonnes) Styles de texte : heading, body, caption, etc.
Styles d'effet : ombres, flous, etc.

Ne codez jamais en dur les couleurs hex ou l'espacement en pixels quand une variable du système de design existe. Utilisez setBoundVariable pour l'espacement/les rayons et setBoundVariableForPaint pour les couleurs. Appliquez les styles de texte avec node.textStyleId et les styles d'effet avec node.effectStyleId.

Étape 5 : Valider l'écran complet

Après la composition de toutes les sections, appelez get_screenshot sur le cadre de page complet et comparez avec la source. Corrigez les problèmes avec des appels use_figma ciblés — ne reconstruisez pas l'écran entier.

Prenez des captures d'écran des sections individuelles, pas seulement la page complète. Une capture d'écran de page complète à résolution réduite masque la troncature de texte, les mauvaises couleurs et le texte d'espace réservé qui n'a pas été remplacé. Prenez une capture d'écran de chaque section par ID de nœud pour détecter :

  • Texte coupé/clippé — les hauteurs de ligne ou le dimensionnement du cadre qui coupent les traits descendants, ascendants ou des lignes entières
  • Contenu qui se chevauche — les éléments qui s'empilent les uns sur les autres en raison d'un dimensionnement incorrect ou d'une auto-mise en page manquante
  • Texte d'espace réservé toujours affiché ("Title", "Heading", "Button")
  • Contenu tronqué par des bugs de dimensionnement de mise en page
  • Mauvaises variantes de composants (par ex. Bouton Neutral vs Primary)

Étape 6 : Mettre à jour un écran existant

Lors de la mise à jour plutôt que de la création à partir de zéro :

  1. Utilisez get_metadata pour inspecter la structure d'écran existante.
  2. Identifiez les sections qui ont besoin de mise à jour et celles qui peuvent rester.
  3. Pour chaque section qui a besoin de modifications :
    • Localisez les nœuds existants par ID ou nom
    • Échangez les instances de composants si le composant du système de design a changé
    • Mettez à jour le contenu du texte, les propriétés de variante ou la mise en page selon les besoins
    • Supprimez les sections obsolètes
    • Ajoutez de nouvelles sections
  4. Validez avec get_screenshot après chaque modification.
// Exemple : Échangez une variante de bouton dans un écran existant
const existingButton = await figma.getNodeByIdAsync("EXISTING_BUTTON_INSTANCE_ID");
if (existingButton && existingButton.type === "INSTANCE") {
  // Importez le composant mis à jour
  const buttonSet = await figma.importComponentSetByKeyAsync("BUTTON_SET_KEY");
  const newVariant = buttonSet.children.find(c =>
    c.name.includes("variant=primary") && c.name.includes("size=lg")
  ) || buttonSet.defaultVariant;
  existingButton.swapComponent(newVariant);
}
return { success: true, mutatedNodeIds: [existingButton.id] };

Documents de référence

Pour les modèles API détaillés et les pièges, chargez-les à partir des références figma-use selon les besoins :

  • component-patterns.md — importation par clé, recherche de variantes, setProperties, remplacements de texte, travail avec les instances
  • variable-patterns.md — création/liaison de variables, importation de variables de bibliothèque, portées, alias, découverte de variables existantes
  • text-style-patterns.md — création/application de styles de texte, importation de styles de texte de bibliothèque, rampes de type
  • effect-style-patterns.md — création/application de styles d'effet (ombres), importation de styles d'effet de bibliothèque
  • gotchas.md — pièges de mise en page (interactions HUG/FILL, counterAxisAlignItems, ordre de dimensionnement), problèmes de peinture/couleur, réinitialisations de contexte de page

Récupération d'erreur

Suivez le processus de récupération d'erreur à partir de figma-use :

  1. ARRÊTEZ en cas d'erreur — ne réessayez pas immédiatement.
  2. Lisez attentivement le message d'erreur pour comprendre ce qui s'est mal passé.
  3. Si l'erreur n'est pas claire, appelez get_metadata ou get_screenshot pour inspecter l'état actuel du fichier.
  4. Corrigez le script en fonction du message d'erreur.
  5. Réessayez le script corrigé — c'est sûr car les scripts échoués sont atomiques (rien n'est créé si un script génère une erreur).

Comme cette compétence fonctionne de manière incrémentielle (une section par appel), les erreurs sont naturellement limitées à une seule section. Les sections précédentes des appels réussis restent intactes.

Meilleures pratiques

  • Cherchez toujours avant de construire. Le système de design a probablement le composant, la variable ou le style dont vous avez besoin. La construction manuelle et les valeurs codées en dur doivent être l'exception, pas la règle.
  • Cherchez largement. Essayez les synonymes et les termes partiels. Une "NavigationPill" pourrait être trouvée sous "pill", "nav", "tab" ou "chip". Pour les variables, cherchez "color", "spacing", "radius", etc.
  • Préférez les tokens du système de design aux valeurs codées en dur. Utilisez les liaisons de variables pour les couleurs, l'espacement et les rayons. Utilisez les styles de texte pour la typographie. Utilisez les styles d'effet pour les ombres. Cela garde l'écran lié au système de design.
  • Préférez les instances de composants aux constructions manuelles. Les instances restent liées au composant source et se mettent à jour automatiquement quand le système de design évolue.
  • Travaillez section par section. Ne construisez jamais plus d'une section majeure par appel use_figma.
  • Retournez les ID de nœud de chaque appel. Vous en aurez besoin pour composer les sections et pour la récupération d'erreur.
  • Validez visuellement après chaque section. Utilisez get_screenshot pour détecter les problèmes tôt.
  • Correspondez aux conventions existantes. Si le fichier a déjà des écrans, correspondez à leurs conventions de nommage, de dimensionnement et de mise en page.