El objetivo de exportación predeterminado de figmascope es Jetpack Compose. Pero el bundle es agnóstico respecto al agente — los tipos de nodos IR, el formato de tokens y las refs de cadenas se mapean igual de limpiamente a React + Tailwind. Solo tienes que decirle al agente que apunte a JSX en lugar de Kotlin.

Esta guía cubre el mapeo IR a JSX, cómo extender tailwind.config.js con tokens de tokens.json, y los patrones de prompting que producen la menor desviación en el lado de React.

Una advertencia importante desde el principio

Compose es lo que figmascope prueba más. El IR, el formato de tokens y las restricciones de CONTEXT.md fueron diseñados con Compose en mente. React + Tailwind funciona — el IR se mapea limpiamente — pero verás algo más de desviación, especialmente alrededor de la tipografía y los layouts overlay. Marca cualquier cosa que parezca incorrecta y ejecuta una verificación de tokens después del primer pase.

Paso 1: Generar y descomprimir el bundle

unzip ~/Downloads/context-bundle.zip -d ./design/

ls design/
# CONTEXT.md  _meta.json  components/  screens/  strings.json  tokens.json

Paso 2: Extender la configuración de Tailwind con tokens de diseño

Antes de hacer prompts, mapea tokens.json en tu tailwind.config.js. Este es el paso clave que hace que Tailwind sea consciente de los tokens — en lugar de valores hex hardcodeados en cadenas de className, obtienes nombres semánticos que se remontan al diseño.

// tailwind.config.js
const tokens = require('./design/tokens.json')

// Build color map: { 'brand-7f5cfe': '#7F5CFE', ... }
const colors = Object.fromEntries(
  Object.entries(tokens.color).map(([key, val]) => [
    `brand-${key}`, val
  ])
)

// Build spacing map: { 'ds-4': '4px', 'ds-8': '8px', ... }
const spacing = Object.fromEntries(
  Object.entries(tokens.spacing).map(([key, val]) => [
    `ds-${key}`, `${val}px`
  ])
)

// Build border-radius map
const borderRadius = Object.fromEntries(
  Object.entries(tokens.radius).map(([key, val]) => [
    `ds-${key}`, val === 9999 ? '9999px' : `${val}px`
  ])
)

module.exports = {
  content: ['./src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors,
      spacing,
      borderRadius,
    }
  }
}

Esto produce clases de Tailwind como bg-brand-7f5cfe, p-ds-16, rounded-ds-12. No son los nombres de clase más bonitos, pero son trazables — cada clase se remonta a una clave de token.

Si prefieres alias semánticos, añade una capa de alias:

// en theme.extend.colors:
primary: tokens.color['7f5cfe'],
background: tokens.color['f6f2ea'],
surface: tokens.color['ffffff'],

Dale al agente ambos — la configuración de tokens raw y los alias semánticos — para que pueda elegir el nombre correcto en contexto.

Paso 3: Hacer prompt al agente para apuntar a React + Tailwind

CONTEXT.md dice que el objetivo predeterminado es Compose. Sobreescríbelo explícitamente en tu prompt:

Implement ./design/screens/home.json as a React functional component using Tailwind CSS.

Framework override: ignore the Compose instructions in CONTEXT.md. Target React + Tailwind.

Rules:
- Read ./design/tokens.json. The tokens are extended into Tailwind config —
  use Tailwind classes that correspond to token keys (e.g. bg-brand-7f5cfe, p-ds-16).
- UI strings come from ./design/strings.json. Import and reference them by key.
- IR node kind mapping:
    stack (axis:vertical)   → <div className="flex flex-col gap-[Xpx]">
    stack (axis:horizontal) → <div className="flex flex-row gap-[Xpx]">
    overlay                 → <div className="relative"> with absolute-positioned children
    absolute                → <div className="absolute" style={{"{{"}}top, left, width, height{{"}}"}}>
    leaf (text)             → <span> or <p> with Tailwind text classes
    leaf (rectangle)        → <div> with bg and rounded classes
- Do not hardcode hex values. All colors must use Tailwind classes from the token config.
- Do not hardcode strings. Use the strings.json keys.

Output to: src/screens/HomeScreen.tsx

El mapeo IR a JSX

Aquí está la tabla de mapeo completa para React + Tailwind:

Tipo IRPropiedadesPatrón JSX
stackaxis: "vertical"<div className="flex flex-col gap-ds-{n}">
stackaxis: "horizontal"<div className="flex flex-row gap-ds-{n}">
overlayhijos superpuestos<div className="relative"> con hijos className="absolute ..."
absolutex, y, w, h<div className="absolute" style={{"{{"}}top: y, left: x, width: w, height: h{{"}}"}}>
leaftype: "text"<span className="text-{size} font-{weight} leading-{lh} text-brand-{color}">
leaftype: "rectangle"<div className="bg-brand-{color} rounded-ds-{r}">

Valores de gap y padding: usa las clases de espaciado ds-{n} de la extensión de configuración de Tailwind. Si el valor de gap no es una clave de token limpia, usa la sintaxis de valor arbitrario de Tailwind: gap-[20px].

Un ejemplo real: IR de pantalla de inicio a JSX

Usando el mismo IR del recorrido de Compose:

import strings from '../../design/strings.json'

export function HomeScreen() {
  return (
    <div className="flex flex-col gap-ds-24 p-ds-16 bg-brand-f6f2ea min-h-screen">
      <h1 className="text-2xl font-bold leading-tight text-brand-1a1a2e">
        {strings['home.title'].value}
      </h1>
      <div className="flex flex-col gap-ds-12">
        <div className="bg-white rounded-ds-12 p-ds-16">
          <span className="text-xs font-medium text-brand-7f5cfe">
            {strings['home.card.label'].value}
          </span>
        </div>
      </div>
    </div>
  )
}

Cada className es trazable. gap-ds-24spacing.24 → 24px. text-brand-7f5cfecolor.7f5cfe#7F5CFE. Si un valor se desvía (por ejemplo, el agente escribe gap-6 en lugar de gap-ds-24), es visible inmediatamente en una revisión de código.

Por qué tokens.json + configuración de Tailwind funciona

Ambos sistemas son token-first. Tailwind extiende una configuración base con valores personalizados; tokens.json ya está estructurado como un mapa de valores personalizados. El paso de extensión (Paso 2 anterior) es una configuración única — después de eso, el agente usa nombres de clases de Tailwind que están semánticamente vinculados al sistema de diseño en lugar de clases de utilidad arbitrarias.

El resultado: cuando el token de diseño cambia (digamos que el color primario pasa de #7F5CFE a #6B4EE6), actualizas un valor en tokens.json, vuelves a ejecutar la importación de configuración y Tailwind regenera. El código del componente no cambia.

Verificación de desviación de tokens

Después de la implementación, pide al agente que audite la desviación:

Audit src/screens/HomeScreen.tsx for token drift.

Check:
1. Any hex color values not referenced through a Tailwind class from the token config.
2. Any hardcoded px or rem spacing values that should be ds-{n} classes.
3. Any UI strings not sourced from design/strings.json.

List violations. Produce a diff that fixes them.

Overlay y absolute — los casos complicados

Los nodos overlay necesitan un padre relative e hijos posicionados absolute. El IR lista los hijos en orden z (primero = capa inferior). Dile al agente que preserve este orden en el JSX — React renderiza en orden del DOM y CSS position: absolute apila en consecuencia.

Los nodos absolute usan coordenadas de píxeles raw de Figma. Casi siempre provienen de diseños que no se construyeron con auto-layout. Si ves muchos nodos absolute, generalmente significa que el archivo de Figma tiene posicionamiento manual — el código generado será frágil con diferentes tamaños de viewport. Considera marcar esto y refactorizar a layouts flex.

Manejo de cadenas en React

A diferencia de Android (donde las claves de strings.json se mapean a IDs de recursos R.string.*), en React importas el JSON directamente:

import strings from '../../design/strings.json'

// uso
{strings['home.title'].value}
// o con fallback
{strings['home.title']?.value ?? strings['home.title']?.fallback ?? 'Untitled'}

Si estás usando bibliotecas i18n (react-i18next, next-intl), las claves en notación de puntos en strings.json se mapean directamente a los espacios de nombres de claves de traducción. Dile al agente qué biblioteca i18n estás usando para que genere el patrón de llamada correcto.

Brechas honestas en el lado de React

Utilidades de tipografía. Las utilidades de texto de Tailwind (text-xs, text-2xl) no se mapean 1:1 a los tokens de typography en tokens.json. Tailwind tiene una escala tipográfica fija; el archivo de tokens tiene tamaños arbitrarios. Necesitarás extender la configuración de fontSize de Tailwind con valores de tokens o usar valores arbitrarios (text-[24px]). Ambos funcionan; extender la configuración es más limpio.

Altura de línea. El mismo problema — las utilidades de leading de Tailwind no coinciden con valores de lineHeight arbitrarios. Usa leading-[{value}] o extiende la configuración.

Degradados. No están soportados en el IR. Cualquier fill de degradado aparece como advertencia en _meta.json y se omite de la propiedad fill del nodo. Manéjalos manualmente.

Ninguna de estas es un bloqueador — son brechas conocidas. La base con conciencia de tokens es sólida; los bordes solo necesitan manejo manual.

Comienza con figmascope para exportar tu bundle, luego usa esta guía junto con el flujo de trabajo de Cursor o el flujo de trabajo de Claude Code para impulsar la implementación.