Communitygithub.com

MohamedRamadanSalah/figma-lens

Implementa interfaces de usuario a partir de diseños de Figma con precisión de píxeles usando las exportaciones de figma-lens (design/<frame>/spec.md, tokens.json, capturas de pantalla, iconos SVG): no necesita Figma MCP ni Modo Desarrollador. Úsalo siempre que el usuario solicite construir, implementar, igualar o corregir una pantalla/componente «desde Figma», mencione una carpeta design/ o una exportación de figma-lens, o quiera código Flutter o web (HTML/CSS/React/Tailwind) que coincida con un frame de Figma.

¿Qué es figma-lens?

figma-lens es una habilidad para agentes de IA (como Claude Code, Cursor o Codex) que permite implementar interfaces de usuario a partir de diseños de Figma con precisión milimétrica, sin necesidad de conectar Figma MCP ni usar el Modo Desarrollador. El usuario exporta frames desde el plugin Figma Lens en el escritorio de Figma, y el agente recibe una carpeta estructurada con especificaciones (`spec.md`), tokens de diseño, capturas de pantalla e iconos SVG. El agente debe leer primero el archivo `spec.md`, que contiene un árbol de capas compacto con valores exactos (tamaños, colores, tipografía, espaciados, auto layout y posiciones absolutas). Luego debe inspeccionar las imágenes de sección y la captura de pantalla general, pero siempre priorizando los valores de la especificación sobre la medición visual. El flujo de trabajo incluye un bucle de comparación y corrección: tras construir la pantalla, se ejecuta `figma-lens check` que genera un informe de diferencias y una imagen comparativa (Figma vs. implementación), permitiendo al agente corregir errores de forma iterativa hasta alcanzar un desajuste ≤ 3%. La habilidad también incluye un mapeo de componentes (`figma-lens.map.json`) que asocia los componentes y tokens de Figma con el código real del proyecto (Flutter, React, Tailwind, etc.). Si el mapeo no existe, el agente puede generarlo con `figma-lens map` y luego completarlo manualmente. El objetivo es que el agente reutilice componentes existentes, use los tokens mapeados, copie el texto exactamente igual, inserte los SVG e imágenes exportados sin redibujar nada, y siga las reglas de mapeo específicas para Flutter y web (CSS/Tailwind/React) que están documentadas en la habilidad. La habilidad es especialmente útil para desarrolladores que usan agentes de IA para generar código de interfaz a partir de diseños, ya que elimina la ambigüedad de las descripciones textuales y proporciona datos precisos y verificables.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

figma-lens: crea UI que coincida con Figma

figma-lens es un plugin de Figma más un puente local. El usuario selecciona frames en Figma desktop y hace clic en Exportar a Claude. El puente escribe una carpeta por frame:

design/
  INDEX.md                  ← lista de todos los frames exportados (empieza aquí)
  <frame>/
    spec.md                 ← LÉELO PRIMERO: árbol de capas compacto con valores exactos
    spec.json               ← datos completos (+ CSS por capa desde Figma) cuando spec.md no es suficiente
    tokens.json             ← variables (todos los modos), estilos, recuentos de uso de valores sin procesar
    [email protected]           ← render completo (2x por defecto)
    sections/NN-nombre.png  ← recortes de los bloques de nivel superior a resolución completa
    assets/*.svg            ← iconos/arte vectorial, listos para usar
    images/*                ← mapas de bits originales usados como rellenos de imagen
    compare/                ← escrito por `figma-lens check` (report.md, side-by-side.png, diff.png)
figma-lens.map.json         ← (raíz del proyecto) componente/token de Figma → código real en este proyecto

El comando figma-lens es la CLI del repositorio figma-lens (npm link ahí lo hace global; si no, ejecuta node <figma-lens>/bin/figma-lens.js …). Ejecuta figma-lens help para todos los comandos.

Si aún no hay exportación

  1. Inicia el puente para el proyecto del usuario y mantenlo ejecutándose (en segundo plano): figma-lens bridge --out <proyecto>/design.
  2. Pide al usuario que seleccione los frames en Figma desktop → Plugins → Development → Figma Lens → Exportar a Claude.
  3. Lee design/INDEX.md para confirmar que llegó.

Nunca adivines un diseño a partir de una descripción cuando sea posible una exportación. Pide la exportación.

Flujo de trabajo

  1. Lee spec.md completamente (es pequeño). Anota el tamaño del frame, el árbol de diseño, las variables y estilos, y los recursos.
  2. Mira las imágenes. Lee sections/*.png uno por uno para ver los detalles. Usa [email protected] solo para la vista general, porque las imágenes grandes se reducen al visualizarlas. Los valores siempre provienen de la especificación, nunca de medir píxeles.
  3. Usa el mapa de componentes (ver "Mapa de componentes" más abajo). Cada ⇒ USA … en spec.md es obligatorio: usa ese widget/componente y su mapeo de props, y usa los tokens mapeados ((color/primary ⇒ AppColors.primary)) en lugar de valores sin procesar. Para los elementos marcados como (no en el mapa), busca en el código base el tema y widgets existentes (Flutter ThemeData, AppColors, TextTheme, constantes de espaciado, lib/widgets; web variables CSS, configuración de Tailwind, src/components). Usa valores sin procesar solo cuando no exista ningún token, e informa al usuario cuáles añadiste.
  4. Reutiliza componentes. Una capa marcada como component Button {Type=Primary} debe usar el widget o componente Button existente del proyecto con las props coincidentes. Construye uno nuevo solo si no existe ninguno, hazlo reutilizable y agrégalo al mapa.
  5. Construye de arriba a abajo, siguiendo el árbol. El auto layout se asigna a Row/Column/flex (tablas más abajo). Solo las capas @x,y (sin auto layout, o absolute) necesitan Stack/Positioned o posicionamiento absoluto.
  6. Usa los archivos exportados. Coloca assets/*.svg e images/* en la carpeta de recursos del proyecto y referéncialos. Nunca vuelvas a dibujar iconos ni sustituyas un conjunto de iconos diferente.
  7. Copia el texto exactamente de "…" en spec.md, incluyendo mayúsculas, puntuación y cadenas árabes/RTL. El texto con varias líneas run necesita texto enriquecido (TextSpan / spans anidados).
  8. Verifica con el bucle de comparación y corrección (más abajo). No declares una pantalla terminada solo por leer el código; pruébalo con una comparación de capturas de pantalla.

Bucle de comparación y corrección

Después de construir una pantalla, compara el resultado real con Figma y corrige las diferencias:

  1. Ejecuta la compilación que muestra esa pantalla:
    • Web: inicia el servidor de desarrollo y abre la ruta.
    • Flutter web: flutter run -d web-server --web-port 8080, luego usa esa URL.
    • Flutter Android: ejecuta la aplicación en un emulador/dispositivo y navega a la pantalla.
  2. Verifícala:
    • Web / Flutter web: figma-lens check --design design/<frame> --url http://localhost:<puerto>/<ruta> (el viewport se ajusta automáticamente al tamaño del frame y la escala).
    • Android: figma-lens check --design design/<frame> --adb --crop-top <barra de estado px> [--crop-bottom <barra de navegación px>] (la barra de estado ≈ 24–48 dp × densidad del dispositivo; recórtala para que solo se compare el contenido de la aplicación).
  3. Lee design/<frame>/compare/report.md (porcentaje de desajuste, las áreas que más difieren y los ids de capa de Figma en cada una) y mira compare/side-by-side.png (Figma | compilación | diff, rojo = diferente).
  4. Corrige de arriba a abajo: primero las diferencias de altura o espaciado (desplazan todo lo de abajo), luego tamaños, colores, tipografía, radios, sombras. Busca cada id de capa listado en spec.md para los valores exactos.
  5. Vuelve a ejecutar la verificación. El informe muestra la puntuación anterior, para que puedas ver el progreso.
  6. Detente cuando el desajuste sea ≤ 3% (el anti-aliasing de texto nunca llega a 0) o cuando dos ejecuciones consecutivas dejen de mejorar. Luego informa la puntuación final y cualquier cosa que no hayas podido igualar, y por qué (fuente faltante, renderizado de plataforma, datos dinámicos).

Reglas: corrige el código real, nunca manipules la comparación (sin capturas de pantalla ni imágenes del diseño dentro de la aplicación). Usa los mismos datos/texto que el diseño al verificar (datos simulados si es necesario), de lo contrario las diferencias de texto dominarán la puntuación.

Mapa de componentes

figma-lens.map.json (raíz del proyecto) asigna componentes y tokens de Figma al código de este proyecto:

{
  "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/<nombre>.svg')"
  },
  "tokens": { "color/primary": { "flutter": "AppColors.primary", "web": "var(--color-primary)" } }
}
  • ¿Aún no hay mapa? → Ejecuta figma-lens map --design design. Añade cada componente y token de las exportaciones con valores vacíos ("").
  • Rellénalo tú mismo: busca en el código base cada componente (por nombre, por aspecto, por props) y cada valor de token; escribe ruta#Símbolo (o una expresión). Deja "" solo cuando aún no exista nada. "Prefijo/*" coincide con toda una familia (iconos).
  • Después de editar el mapa, ejecuta figma-lens render design/<frame> para que spec.md muestre las flechas ⇒ USA. El puente también aplica el mapa en cada nueva exportación.
  • Cuando crees un nuevo widget reutilizable para un componente no mapeado, agrégalo al mapa.

Lectura de spec.md

  • Las unidades son px de diseño, que equivalen a px de CSS y px lógicos de Flutter. Nunca multipliques por la escala de la captura de pantalla.
  • row|column gap G pad s,d,i,z main:X cross:Y es auto layout. pad 16 significa que los cuatro lados son 16. gap auto significa espacio entre.
  • w:FILL h:HUG da el tamaño en cada eje: FIXED (tamaño exacto mostrado), HUG (ajustar al contenido) o FILL (ocupar el espacio disponible).
  • @x,y es la posición dentro del padre. absolute significa un hijo con posicionamiento absoluto dentro de un auto layout. pin H/V da restricciones (MIN = izquierda/arriba, MAX = derecha/abajo, STRETCH = ambos, CENTER, SCALE).
  • bg A + B lista las capas de pintura de abajo a arriba. (nombre) es una variable de Figma y [nombre de estilo] es un estilo de Figma.
  • Los colores son #RRGGBB o #RRGGBBAA (alfa al final).
  • El texto usa el formato "caracteres" · Familia Estilo (peso) tamaño/alturaLínea color. alturaLínea es px, % o auto. ls es espaciado entre letras en px, o en % del tamaño de fuente.
  • radius 12 establece cada esquina. radius izq,sup,der,inf establece cada esquina. smoothing es suavizado de esquinas estilo iOS; apruxímalo, o ignóralo en Flutter a menos que se use un paquete squircle.
  • drop-shadow x,y difuminado B propagación S color, inner-shadow, layer-blur R, background-blur R.
  • → assets/x.svg significa que la capa es un icono. Usa el SVG al tamaño indicado.
  • vars{itemSpacing=space/md} significa que la propiedad de la capa está vinculada a esa variable. Usa el token.

Mapeo Flutter

FigmaFlutter
columna / filaColumn / Row (usa spacing: G en Flutter ≥ 3.27, de lo contrario SizedBox como separadores)
wrap, rowGap RWrap(spacing: G, runSpacing: R)
pad s,d,i,zPadding(padding: EdgeInsets.fromLTRB(i, s, z, d)). Cuidado con el orden.
main MIN / CENTER / MAX / SPACE_BETWEENMainAxisAlignment.start / center / end / spaceBetween
cross MIN / CENTER / MAX / BASELINECrossAxisAlignment.start / center / end / baseline (baseline necesita textBaseline)
HUG en el eje principalmainAxisSize: MainAxisSize.min
FILL en el eje principal del padreExpanded (o Flexible); grow N establece flex: N
FILL en el eje transversal del padreCrossAxisAlignment.stretch en el padre, o SizedBox(width: double.infinity)
FIXED a×hSizedBox(width: a, height: h)
@x,y / absoluteStack + Positioned(left: x, top: y); usa pin para derecha/abajo
bg sólidoBoxDecoration(color: Color(0xAARRGGBB)). Mueve el alfa al frente: #11223380 → 0x80112233.
gradiente-lineal desde/hastaLinearGradient(begin: Alignment(fx*2-1, fy*2-1), end: Alignment(tx*2-1, ty*2-1), colors, stops) usando from/to en spec.json
radiusBorderRadius.circular(r) o BorderRadius.only(...)
borde W color interiorBorder.all(width: W, color: …) (interior es el valor predeterminado de Flutter; centro/exterior necesitan strokeAlign)
drop-shadow x,y difuminado B propagación SBoxShadow(offset: Offset(x, y), blurRadius: B, spreadRadius: S, color: …)
background-blur RClipRRect + BackdropFilter(filter: ImageFilter.blur(sigmaX: R/2, sigmaY: R/2))
opacidadOpacity (o alfa de color para pinturas)
text size/lineHeightTextStyle(fontSize: tamaño, height: alturaLínea / tamaño). Para %: height: pct/100. Establece leadingDistribution: TextLeadingDistribution.even para coincidir con el centrado vertical de Figma.
peso 600FontWeight.w600
ls px / ls %letterSpacing: px / letterSpacing: tamaño * pct / 100
ellipsis maxLines NmaxLines: N, overflow: TextOverflow.ellipsis
align CENTERtextAlign: TextAlign.center. Para pantallas RTL, usa TextAlign.start y EdgeInsetsDirectional.
assets/x.svgSvgPicture.asset('assets/…/x.svg', width:, height:) (flutter_svg)
image fill FILL / FITImage.asset(fit: BoxFit.cover / BoxFit.contain)

Mapeo web (CSS / Tailwind / React)

FigmaCSS
columna / filadisplay:flex; flex-direction: column / row; gap: Gpx
wrap, rowGap Rflex-wrap: wrap; column-gap: G; row-gap: R
pad s,d,i,zpadding: s d i z (mismo orden 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 (o simplemente auto)
FILL (eje principal)flex: 1 1 0; min-width: 0
FILL (eje transversal)align-self: stretch
FIXEDwidth: Wpx; height: Hpx; flex-shrink: 0
@x,y / absolutepadre position: relative; hijo position:absolute; left:x; top:y (usa pin para derecha/abajo)
colores #RRGGBBAACSS válido tal cual
gradiente-lineal Ndeglinear-gradient(Ndeg, c1 p1%, c2 p2%)
drop-shadowbox-shadow: x y B S color (inner-shadow añade inset)
layer-blur / background-blur Rfilter: blur(R/2 px) / backdrop-filter: blur(R/2 px)
textfont: peso tamaño/alturaLínea familia; 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> o SVG en línea; mantén el tamaño exportado

spec.json también tiene el CSS generado por Figma (css) para la mayoría de las capas. Úsalo para verificar los valores CSS; los tokens y la estructura del diseño aún provienen del árbol anterior.

Reglas

  • Los valores de la especificación tienen prioridad sobre lo que ves en la imagen. Cuando entren en conflicto, confía en la especificación y menciona el conflicto.
  • No redondees ni "mejores" los valores (14 sigue siendo 14, no 16) a menos que el usuario solicite normalizarlos a tokens.
  • Las capas ocultas no se exportan. No inventes estados (hover, error, vacío) que no estén en la exportación; pide esos frames.
  • Señala las fuentes faltantes. Si la familia de fuentes no está incluida en el proyecto, dilo e indica al usuario qué añadir (fuentes de pubspec / @font-face).
  • Para varios puntos de ruptura o estados, pide al usuario que exporte cada frame. Cada uno se convierte en su propia carpeta.

Skills relacionados