Communitygithub.com

MohamedRamadanSalah/figma-lens

Implémentez des interfaces utilisateur à partir de maquettes Figma avec une précision parfaite en utilisant les exports figma-lens (design/<frame>/spec.md, tokens.json, captures d'écran, icônes SVG) — sans avoir besoin de Figma MCP ou du mode Développement. Utilisez cette compétence chaque fois que l'utilisateur demande de construire, implémenter, faire correspondre ou corriger un écran/composant « depuis Figma », mentionne un dossier design/ ou un export figma-lens, ou souhaite du code Flutter ou web (HTML/CSS/React/Tailwind) correspondant à un frame Figma.

Qu'est-ce que figma-lens ?

figma-lens est une compétence conçue pour les agents IA comme Claude Code, Cursor ou Codex, permettant de traduire les maquettes Figma en code UI pixel-perfect. Elle élimine le besoin de Figma MCP ou du mode Développement en utilisant un plugin Figma et un pont local qui exporte chaque frame dans un dossier structuré contenant un cahier des charges (spec.md), des tokens de design, des captures d'écran, des icônes SVG et des ressources bitmaps. La compétence guide l'agent à travers un flux de travail complet : lire le spec.md, analyser les images, réutiliser les composants existants et appliquer les tokens de design. Elle intègre également une boucle de vérification et correction : après avoir généré le code, l'agent peut lancer une comparaison automatisée entre le rendu réel (web ou Flutter) et le design Figma, en utilisant `figma-lens check` pour produire un rapport de différences, une image côte-à-côte et un diff. Cette approche garantit un écart de rendu inférieur à 3 % avant de déclarer l'écran terminé. La compétence prend en charge Flutter (avec des mappings détaillés pour les layouts, les couleurs, les ombres, etc.) et le développement web (CSS, Tailwind, React) avec des équivalences précises entre les propriétés Figma et le code cible.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/MohamedRamadanSalah/figma-lens/tree/HEAD/skill/figma-lens

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

figma-lens : construire une UI qui correspond à Figma

figma-lens est un plugin Figma associé à un pont local. L'utilisateur sélectionne des frames dans Figma desktop et clique sur Exporter vers Claude. Le pont écrit un dossier par frame :

design/
  INDEX.md                  ← liste de tous les frames exportés (commencez ici)
  <frame>/
    spec.md                 ← À LIRE EN PREMIER : arbre des couches compact avec valeurs exactes
    spec.json               ← données complètes (+ CSS par couche issu de Figma) quand spec.md ne suffit pas
    tokens.json             ← variables (tous les modes), styles, comptes d'utilisation des valeurs brutes
    [email protected]           ← rendu complet (2x par défaut)
    sections/NN-name.png    ← vignettes des blocs de haut niveau en pleine résolution
    assets/*.svg            ← icônes/illustrations vectorielles, prêtes à l'emploi
    images/*                ← bitmaps originaux utilisés comme remplissages d'image
    compare/                ← écrit par `figma-lens check` (report.md, side-by-side.png, diff.png)
figma-lens.map.json         ← (racine du projet) composants/tokens Figma → code réel de ce projet

La commande figma-lens est l'interface en ligne de commande du dépôt figma-lens (npm link là-bas la rend globale ; sinon exécutez node <figma-lens>/bin/figma-lens.js …). Exécutez figma-lens help pour toutes les commandes.

S'il n'y a pas encore d'export

  1. Démarrez le pont pour le projet de l'utilisateur et laissez-le tourner (en arrière-plan) : figma-lens bridge --out <projet>/design.
  2. Demandez à l'utilisateur de sélectionner le(s) frame(s) dans Figma desktop → Plugins → Développement → Figma Lens → Exporter vers Claude.
  3. Lisez design/INDEX.md pour confirmer son arrivée.

Ne devinez jamais un design à partir d'une description quand un export est possible. Demandez l'export.

Flux de travail

  1. Lisez spec.md entièrement (il est petit). Notez la taille du frame, l'arbre de disposition, les variables et styles, et les ressources.
  2. Regardez les images. Lisez sections/*.png une par une pour les détails. Utilisez [email protected] uniquement pour la vue d'ensemble, car les grandes images sont réduites lorsque vous les visualisez. Les valeurs proviennent toujours du spec, jamais en mesurant les pixels.
  3. Utilisez la carte des composants (voir « Carte des composants » ci-dessous). Chaque ⇒ USE … dans spec.md est obligatoire : utilisez ce widget/composant et son mapping de props, et utilisez les tokens mappés ((color/primary ⇒ AppColors.primary)) au lieu des valeurs brutes. Pour les éléments marqués (not in map), recherchez dans le codebase le thème et les widgets existants (Flutter ThemeData, AppColors, TextTheme, constantes d'espacement, lib/widgets ; web variables CSS, configuration Tailwind, src/components). N'utilisez les valeurs brutes que lorsque aucun token n'existe, et indiquez à l'utilisateur celles que vous avez ajoutées.
  4. Réutilisez les composants. Une couche marquée component Button {Type=Primary} doit utiliser le widget ou composant Button existant du projet avec les props correspondantes. Créez-en un nouveau uniquement s'il n'en existe aucun, rendez-le réutilisable et ajoutez-le à la carte.
  5. Construisez de haut en bas, en suivant l'arbre. Les mises en page automatiques correspondent à Row/Column/flex (tableaux ci-dessous). Seules les couches @x,y (sans auto layout, ou absolute) nécessitent Stack/Positioned ou un positionnement absolu.
  6. Utilisez les fichiers exportés. Placez assets/*.svg et images/* dans le dossier de ressources du projet et référencez-les. Ne redessinez jamais les icônes et ne les remplacez jamais par un autre jeu d'icônes.
  7. Copiez le texte exactement à partir de "…" dans spec.md, y compris la casse, la ponctuation et les chaînes arabes/RTL. Un texte contenant plusieurs lignes run nécessite un texte enrichi (TextSpan / spans imbriqués).
  8. Vérifiez avec la boucle de comparaison et correction (ci-dessous). Ne déclarez pas un écran terminé en lisant le code ; prouvez-le avec un diff de capture d'écran.

Boucle de comparaison et correction

Après avoir construit un écran, comparez le résultat réel avec Figma et corrigez les différences :

  1. Exécutez la construction affichant cet écran :
    • Web : démarrez le serveur de développement et ouvrez la route.
    • Flutter web : flutter run -d web-server --web-port 8080, puis utilisez cette URL.
    • Flutter Android : exécutez l'application sur un émulateur/appareil et naviguez vers l'écran.
  2. Vérifiez-le :
    • Web / Flutter web : figma-lens check --design design/<frame> --url http://localhost:<port>/<route> (la zone d'affichage est automatiquement réglée à la taille du frame et à l'échelle).
    • Android : figma-lens check --design design/<frame> --adb --crop-top <barre d'état en px> [--crop-bottom <barre de navigation en px>] (la barre d'état fait environ 24–48 dp × la densité de l'appareil ; rognez-la pour ne comparer que le contenu de l'application).
  3. Lisez design/<frame>/compare/report.md (pourcentage de différence, les plus grandes zones de différence et les identifiants de couche Figma dans chacune) et regardez compare/side-by-side.png (Figma | build | diff, rouge = différent).
  4. Corrigez de haut en bas : d'abord les différences de hauteur ou d'espacement (elles décalent tout ce qui suit), puis les tailles, couleurs, typographie, rayons, ombres. Recherchez chaque identifiant de couche listé dans spec.md pour les valeurs exactes.
  5. Relancez la vérification. Le rapport affiche le score précédent, vous pouvez donc voir la progression.
  6. Arrêtez-vous lorsque la différence est ≤ 3 % (l'anticrénelage du texte n'atteint jamais 0) ou lorsque deux exécutions consécutives cessent de s'améliorer. Signalez alors le score final et tout ce que vous n'avez pas pu faire correspondre, en expliquant pourquoi (police manquante, rendu de la plateforme, données dynamiques).

Règles : corrigez le vrai code, ne trichez jamais sur le diff (pas de captures d'écran ni d'images du design à l'intérieur de l'application). Utilisez les mêmes données/texte que le design lors de la vérification (données factices si nécessaire), sinon les différences de texte dominent le score.

Carte des composants

figma-lens.map.json (racine du projet) fait correspondre les composants et tokens Figma au code de ce projet :

{
  "components": {
    "Button": { "flutter": "lib/widgets/app_button.dart#AppButton", "web": "src/components/Button.tsx#Button", "props": { "Label": "label", "Type": "variant" } },
    "Icon/*": "SvgPicture.asset('assets/icons/<name>.svg')"
  },
  "tokens": { "color/primary": { "flutter": "AppColors.primary", "web": "var(--color-primary)" } }
}
  • Pas encore de carte → exécutez figma-lens map --design design. Il ajoute chaque composant et token des exports avec des valeurs vides ("").
  • Remplissez-la vous-même : recherchez dans le codebase chaque composant (par nom, par apparence, par props) et chaque valeur de token ; écrivez path#Symbol (ou une expression). Ne laissez "" que lorsque rien n'existe encore. "Prefix/*" correspond à toute une famille (icônes).
  • Après avoir modifié la carte, exécutez figma-lens render design/<frame> pour que spec.md affiche les flèches ⇒ USE. Le pont applique également la carte à chaque nouvel export.
  • Lorsque vous créez un nouveau widget réutilisable pour un composant non mappé, ajoutez-le à la carte.

Lecture de spec.md

  • Les unités sont des px de design, qui sont équivalents aux px CSS et aux px logiques Flutter. Ne multipliez jamais par l'échelle de la capture d'écran.
  • row|column gap G pad t,r,b,l main:X cross:Y est une mise en page automatique. pad 16 signifie que les quatre côtés font 16. gap auto signifie espace entre.
  • w:FILL h:HUG donne le dimensionnement sur chaque axe : FIXED (taille exacte indiquée), HUG (s'adapte au contenu) ou FILL (prend l'espace disponible).
  • @x,y est la position à l'intérieur du parent. absolute signifie un enfant positionné en absolu dans une mise en page automatique. pin H/V donne les contraintes (MIN = gauche/haut, MAX = droite/bas, STRETCH = les deux, CENTER, SCALE).
  • bg A + B liste les couches de peinture de bas en haut. (name) est une variable Figma et [style name] est un style Figma.
  • Les couleurs sont #RRGGBB ou #RRGGBBAA (alpha en dernier).
  • Le texte utilise le format "chars" · Famille Style (poids) taille/hauteurDeLigne couleur. hauteurDeLigne est en px, % ou auto. ls est l'espacement des lettres en px, ou en % de la taille de police.
  • radius 12 définit tous les coins. radius tl,tr,br,bl définit chaque coin. smoothing est un lissage de coin de style iOS ; approximez-le, ou ignorez-le dans Flutter sauf si un package squircle est utilisé.
  • drop-shadow x,y blur B spread S couleur, inner-shadow, layer-blur R, background-blur R.
  • → assets/x.svg signifie que la couche est une icône. Utilisez le SVG à la taille indiquée.
  • vars{itemSpacing=space/md} signifie que la propriété de la couche est liée à cette variable. Utilisez le token.

Mapping Flutter

FigmaFlutter
column / rowColumn / Row (utilisez spacing: G sur Flutter ≥ 3.27, sinon SizedBox pour les espacements)
wrap, rowGap RWrap(spacing: G, runSpacing: R)
pad t,r,b,lPadding(padding: EdgeInsets.fromLTRB(l, t, r, b)). Attention à l'ordre.
main MIN / CENTER / MAX / SPACE_BETWEENMainAxisAlignment.start / center / end / spaceBetween
cross MIN / CENTER / MAX / BASELINECrossAxisAlignment.start / center / end / baseline (baseline nécessite textBaseline)
HUG sur l'axe principalmainAxisSize: MainAxisSize.min
FILL sur l'axe principal du parentExpanded (ou Flexible) ; grow N définit flex: N
FILL sur l'axe transversal du parentCrossAxisAlignment.stretch sur le parent, ou SizedBox(width: double.infinity)
FIXED w×hSizedBox(width: w, height: h)
@x,y / absoluteStack + Positioned(left: x, top: y) ; utilisez pin pour droite/bas
bg solidBoxDecoration(color: Color(0xAARRGGBB)). Déplacez l'alpha au début : #11223380 → 0x80112233.
gradient-linear from/toLinearGradient(begin: Alignment(fx*2-1, fy*2-1), end: Alignment(tx*2-1, ty*2-1), colors, stops) en utilisant from/to dans spec.json
radiusBorderRadius.circular(r) ou BorderRadius.only(...)
border W color insideBorder.all(width: W, color: …) (inside est la valeur par défaut de Flutter ; center/outside nécessitent strokeAlign)
drop-shadow x,y blur B spread SBoxShadow(offset: Offset(x, y), blurRadius: B, spreadRadius: S, color: …)
background-blur RClipRRect + BackdropFilter(filter: ImageFilter.blur(sigmaX: R/2, sigmaY: R/2))
opacityOpacity (ou alpha de couleur pour les peintures)
text size/lineHeightTextStyle(fontSize: size, height: lineHeight / size). Pour % : height: pct/100. Définissez leadingDistribution: TextLeadingDistribution.even pour correspondre au centrage vertical de Figma.
weight 600FontWeight.w600
ls px / ls %letterSpacing: px / letterSpacing: size * pct / 100
ellipsis maxLines NmaxLines: N, overflow: TextOverflow.ellipsis
align CENTERtextAlign: TextAlign.center. Pour les écrans RTL, utilisez TextAlign.start et EdgeInsetsDirectional.
assets/x.svgSvgPicture.asset('assets/…/x.svg', width:, height:) (flutter_svg)
image fill FILL / FITImage.asset(fit: BoxFit.cover / BoxFit.contain)

Mapping Web (CSS / Tailwind / React)

FigmaCSS
column / rowdisplay:flex; flex-direction: column / row; gap: Gpx
wrap, rowGap Rflex-wrap: wrap; column-gap: G; row-gap: R
pad t,r,b,lpadding: t r b l (même ordre que CSS)
main MIN / CENTER / MAX / SPACE_BETWEENjustify-content: flex-start / center / flex-end / space-between
cross MIN / CENTER / MAX / BASELINEalign-items: flex-start / center / flex-end / baseline
HUGwidth/height: fit-content (ou simplement auto)
FILL (axe principal)flex: 1 1 0; min-width: 0
FILL (axe transversal)align-self: stretch
FIXEDwidth: Wpx; height: Hpx; flex-shrink: 0
@x,y / absoluteparent position: relative ; enfant position:absolute; left:x; top:y (utilisez pin pour droite/bas)
couleurs #RRGGBBAAvalide en CSS tel quel
gradient-linear Ndeglinear-gradient(Ndeg, c1 p1%, c2 p2%)
drop-shadowbox-shadow: x y B S color (inner-shadow ajoute inset)
layer-blur / background-blur Rfilter: blur(R/2 px) / backdrop-filter: blur(R/2 px)
textefont: weight size/lineHeight family; letter-spacing (ls % → pct/100 em)
ellipsis maxLines Ndisplay:-webkit-box; -webkit-line-clamp:N; -webkit-box-orient:vertical; overflow:hidden
assets/x.svg<img src> ou SVG en ligne ; conservez la taille exportée

spec.json contient également le CSS généré par Figma lui-même (css) pour la plupart des couches. Utilisez-le pour recouper les valeurs CSS ; les tokens et la structure de disposition proviennent toujours de l'arbre ci-dessus.

Règles

  • Les valeurs du spec priment sur ce que vous voyez dans l'image. En cas de conflit, faites confiance au spec et mentionnez le conflit.
  • N'arrondissez pas et n'« améliorez » pas les valeurs (14 reste 14, pas 16) sauf si l'utilisateur demande une normalisation en tokens.
  • Les couches cachées ne sont pas exportées. N'inventez pas d'états (survol, erreur, vide) qui ne figurent pas dans l'export ; demandez ces frames.
  • Signalez les polices manquantes. Si la famille de polices n'est pas incluse dans le projet, dites-le et indiquez à l'utilisateur quoi ajouter (polices dans pubspec / @font-face).
  • Pour plusieurs points de rupture ou états, demandez à l'utilisateur d'exporter chaque frame. Chacun devient son propre dossier.

Skills associés