Il target di esportazione predefinito di figmascope è Jetpack Compose. Ma il bundle è agnostico rispetto all'agente — i tipi di nodi IR, il formato dei token e i riferimenti alle stringhe si mappano altrettanto bene a React + Tailwind. Devi solo dire all'agente di puntare a JSX invece di Kotlin.
Questa guida copre il mapping IR-to-JSX, come estendere tailwind.config.js con token da tokens.json, e i pattern di prompt che producono meno deriva sul lato React.
Un'importante avvertenza iniziale
Compose è quello che figmascope testa di più. L'IR, il formato dei token e i vincoli di CONTEXT.md sono stati progettati con Compose in mente. React + Tailwind funziona — l'IR si mappa in modo pulito — ma vedrai leggermente più deriva, specialmente intorno alla tipografia e ai layout overlay. Segnala qualsiasi cosa che sembri sbagliata e esegui un controllo dei token dopo il primo passaggio.
Passaggio 1: Genera e decomprimi il bundle
unzip ~/Downloads/context-bundle.zip -d ./design/
ls design/
# CONTEXT.md _meta.json components/ screens/ strings.json tokens.json
Passaggio 2: Estendi la config Tailwind con i design token
Prima di fare il prompt, mappa tokens.json nel tuo tailwind.config.js. Questo è il passaggio chiave che rende Tailwind consapevole dei token — invece di valori hex hardcoded nelle stringhe className, ottieni nomi semantici che risalgono al design.
// tailwind.config.js
const tokens = require('./design/tokens.json')
// Costruisci mappa colori: { 'brand-7f5cfe': '#7F5CFE', ... }
const colors = Object.fromEntries(
Object.entries(tokens.color).map(([key, val]) => [
`brand-${key}`, val
])
)
// Costruisci mappa spaziatura: { 'ds-4': '4px', 'ds-8': '8px', ... }
const spacing = Object.fromEntries(
Object.entries(tokens.spacing).map(([key, val]) => [
`ds-${key}`, `${val}px`
])
)
// Costruisci mappa border-radius
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,
}
}
}
Questo produce classi Tailwind come bg-brand-7f5cfe, p-ds-16, rounded-ds-12. Non i nomi di classe più belli, ma sono tracciabili — ogni classe si ricollega a una chiave token.
Se preferisci alias semantici, aggiungi un layer di aliasing:
// in theme.extend.colors:
primary: tokens.color['7f5cfe'],
background: tokens.color['f6f2ea'],
surface: tokens.color['ffffff'],
Dai all'agente entrambi — la config token grezza e gli alias semantici — in modo che possa scegliere il nome giusto nel contesto.
Passaggio 3: Chiedi all'agente di puntare a React + Tailwind
CONTEXT.md dice che il target predefinito è Compose. Sovrascrivilo esplicitamente nel tuo prompt:
Implementa ./design/screens/home.json come componente funzionale React usando Tailwind CSS.
Override del framework: ignora le istruzioni Compose in CONTEXT.md. Punta a React + Tailwind.
Regole:
- Leggi ./design/tokens.json. I token sono estesi nella config Tailwind —
usa classi Tailwind che corrispondono alle chiavi token (es. bg-brand-7f5cfe, p-ds-16).
- Le stringhe UI vengono da ./design/strings.json. Importale e referenziale per chiave.
- Mapping del tipo di nodo IR:
stack (axis:vertical) → <div className="flex flex-col gap-[Xpx]">
stack (axis:horizontal) → <div className="flex flex-row gap-[Xpx]">
overlay → <div className="relative"> con figli posizionati in assoluto
absolute → <div className="absolute" style={{"{{"}}top, left, width, height{{"}}"}}>
leaf (text) → <span> o <p> con classi di testo Tailwind
leaf (rectangle) → <div> con classi bg e rounded
- Non hardcodare valori hex. Tutti i colori devono usare classi Tailwind dalla config token.
- Non hardcodare stringhe. Usa le chiavi di strings.json.
Output in: src/screens/HomeScreen.tsx
Il mapping IR-to-JSX
Ecco la tabella di mapping completa per React + Tailwind:
| Tipo IR | Proprietà | Pattern JSX |
|---|---|---|
stack | axis: "vertical" | <div className="flex flex-col gap-ds-{n}"> |
stack | axis: "horizontal" | <div className="flex flex-row gap-ds-{n}"> |
overlay | figli sovrapposti | <div className="relative"> con figli className="absolute ..." |
absolute | x, y, w, h | <div className="absolute" style={{"{{"}}top: y, left: x, width: w, height: h{{"}}"}}> |
leaf | type: "text" | <span className="text-{size} font-{weight} leading-{lh} text-brand-{color}"> |
leaf | type: "rectangle" | <div className="bg-brand-{color} rounded-ds-{r}"> |
Valori gap e padding: usa le classi di spaziatura ds-{n} dall'estensione della config Tailwind. Se il valore del gap non è una chiave token pulita, usa la sintassi per valori arbitrari di Tailwind: gap-[20px].
Un esempio reale: da IR della schermata home a JSX
Usando lo stesso IR dalla guida 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>
)
}
Ogni className è tracciabile. gap-ds-24 → spacing.24 → 24px. text-brand-7f5cfe → color.7f5cfe → #7F5CFE. Se un valore diverge (ad es., l'agente scrive gap-6 invece di gap-ds-24), è visibile immediatamente in una code review.
Perché tokens.json + config Tailwind funziona
Entrambi i sistemi sono token-first. Tailwind estende una config base con valori personalizzati; tokens.json è già strutturato come una mappa di valori personalizzati. Il passaggio di estensione (Passaggio 2 sopra) è una configurazione una-tantum — dopo di che, l'agente usa nomi di classe Tailwind che sono semanticamente legati al design system invece di classi utility arbitrarie.
Il risultato: quando il token del design cambia (diciamo, il colore primario passa da #7F5CFE a #6B4EE6), aggiorni un valore in tokens.json, esegui di nuovo l'importazione della config, e Tailwind rigenera. Il codice del componente non cambia.
Controllo deriva dei token
Dopo l'implementazione, chiedi all'agente di verificare la deriva:
Verifica src/screens/HomeScreen.tsx per deriva dei token.
Controlla:
1. Qualsiasi valore di colore hex non referenziato tramite una classe Tailwind dalla config token.
2. Qualsiasi valore di spaziatura px o rem hardcoded che dovrebbe essere una classe ds-{n}.
3. Qualsiasi stringa UI non proveniente da design/strings.json.
Elenca le violazioni. Produci un diff che le corregge.
Overlay e absolute — i casi difficili
I nodi overlay necessitano di un genitore relative e figli posizionati in absolute. L'IR elenca i figli in ordine z (primo = layer inferiore). Di' all'agente di preservare questo ordine nel JSX — React esegue il rendering nell'ordine DOM e CSS position: absolute si sovrappone di conseguenza.
I nodi absolute usano coordinate pixel grezze da Figma. Questi quasi sempre provengono da design non costruiti con auto-layout. Se vedi molti nodi absolute, di solito significa che il file Figma ha posizionamento manuale — il codice generato sarà fragile a diverse dimensioni del viewport. Considera di segnalarlo e di fare refactoring verso layout flex.
Gestione delle stringhe in React
A differenza di Android (dove le chiavi di strings.json si mappano a ID di risorse R.string.*), in React importi il JSON direttamente:
import strings from '../../design/strings.json'
// utilizzo
{strings['home.title'].value}
// o con fallback
{strings['home.title']?.value ?? strings['home.title']?.fallback ?? 'Senza titolo'}
Se usi librerie i18n (react-i18next, next-intl), le chiavi in notazione punto in strings.json si mappano direttamente ai namespace delle chiavi di traduzione. Di' all'agente quale libreria i18n stai usando in modo che generi il pattern di chiamata corretto.
Lacune oneste sul lato React
Utilità tipografiche. Le utilità di testo di Tailwind (text-xs, text-2xl) non si mappano 1:1 ai token typography in tokens.json. Tailwind ha una scala tipografica fissa; il file token ha dimensioni arbitrarie. Dovrai estendere la config fontSize di Tailwind con i valori dei token o usare valori arbitrari (text-[24px]). Entrambi funzionano; estendere la config è più pulito.
Line height. Stesso problema — le utilità leading di Tailwind non corrispondono a valori lineHeight arbitrari. Usa leading-[{value}] o estendi la config.
Gradienti. Non supportati nell'IR. Qualsiasi riempimento a gradiente appare come avviso in _meta.json e viene omesso dalla proprietà fill del nodo. Gestisci manualmente.
Nessuno di questi è un blocco — sono lacune note. La base consapevole dei token è solida; i bordi richiedono solo una gestione manuale.
Inizia con figmascope per esportare il tuo bundle, poi usa questa guida insieme al flusso di lavoro Cursor o al flusso di lavoro Claude Code per guidare l'implementazione.