I design token sono il vocabolario condiviso tra designer e sviluppatori. Esistono in varie forme dall'era Salesforce Lightning — Style Dictionary, Theo, la bozza della specifica del W3C Design Token Community Group. Ciò che è cambiato recentemente è che ora sono anche il vocabolario condiviso tra la tua codebase e gli agenti AI di codifica.
Un agente che sa che color.accent = #d96a3a utilizzerà quel valore. Un agente che riceve uno screenshot indovinerà "arancione caldo" e produrrà qualcosa di simile ma sbagliato. La differenza si moltiplica su decine di componenti.
figmascope esporta un tokens.json come parte di ogni bundle di contesto. Questo articolo spiega il formato in dettaglio, come figmascope ricava i token da Figma, il fallback per l'inferenza di frequenza per i file senza Variabili Figma, e come collegare l'output ai framework comuni. Per vedere come i token si inseriscono nel flusso di esportazione completo, visita l'app figmascope o leggi Figma to Cursor e Figma to Claude Code.
Il formato tokens.json
figmascope usa un formato ispirato al W3C Design Token Community Group. Ogni token è un oggetto con campi $value e $type, annidato sotto chiavi di categoria semantica:
{
"color": {
"surface": { "$value": "#f6f2ea", "$type": "color" },
"surface-2": { "$value": "#efe9dc", "$type": "color" },
"ink": { "$value": "#1f1d1a", "$type": "color" },
"ink-muted": { "$value": "#4a4641", "$type": "color" },
"accent": { "$value": "#d96a3a", "$type": "color" },
"accent-soft": { "$value": "#f2c7a8", "$type": "color" },
"good": { "$value": "#6a8f5a", "$type": "color" },
"warn": { "$value": "#c89a3a", "$type": "color" },
"bad": { "$value": "#b8553a", "$type": "color" }
},
"spacing": {
"1": { "$value": "4px", "$type": "dimension" },
"2": { "$value": "8px", "$type": "dimension" },
"3": { "$value": "12px", "$type": "dimension" },
"4": { "$value": "16px", "$type": "dimension" },
"6": { "$value": "24px", "$type": "dimension" },
"8": { "$value": "32px", "$type": "dimension" },
"12": { "$value": "48px", "$type": "dimension" },
"16": { "$value": "64px", "$type": "dimension" }
},
"radius": {
"sm": { "$value": "4px", "$type": "dimension" },
"md": { "$value": "8px", "$type": "dimension" },
"lg": { "$value": "16px", "$type": "dimension" },
"full": { "$value": "9999px", "$type": "dimension" }
},
"typography": {
"body": {
"fontFamily": { "$value": "Inter", "$type": "fontFamily" },
"fontSize": { "$value": "14px", "$type": "dimension" },
"fontWeight": { "$value": 400, "$type": "number" },
"lineHeight": { "$value": 1.45, "$type": "number" }
},
"heading": {
"sm": {
"fontFamily": { "$value": "Inter", "$type": "fontFamily" },
"fontSize": { "$value": "18px", "$type": "dimension" },
"fontWeight": { "$value": 600, "$type": "number" },
"lineHeight": { "$value": 1.25, "$type": "number" }
}
},
"mono": {
"fontFamily": { "$value": "JetBrains Mono", "$type": "fontFamily" },
"fontSize": { "$value": "13px", "$type": "dimension" },
"fontWeight": { "$value": 400, "$type": "number" }
}
}
}
Perché W3C-ish e non la specifica esatta?
La specifica del W3C Design Token Community Group è ancora una bozza. figmascope segue le convenzioni principali ($value, $type, gruppi annidati) ma non implementa tutti i casi limite come i tipi compositi e le catene di risoluzione degli alias. L'output è abbastanza stabile da essere consumato da Style Dictionary, da attraversamento diretto di JSON, o da un modello linguistico — che è il consumatore primario.
Tipi di token in uso
| $type | Categoria | Formato $value | Esempio |
|---|---|---|---|
color |
colore | stringa hex | "#d96a3a" |
dimension |
spaziatura, raggio | stringa CSS con unità | "16px" |
fontFamily |
tipografia | stringa nome font | "Inter" |
number |
tipografia | numero senza unità | 400, 1.45 |
I colori sono sempre emessi come stringhe hex. Se la sorgente Figma usa RGBA con opacità non piena, il canale alpha è preservato in hex a 8 cifre (#d96a3a80).
Come figmascope ricava i token
figmascope usa una strategia di sourcing a due livelli. Le Variabili Figma sono la sorgente preferita; l'inferenza di frequenza è il fallback.
Livello 1: Variabili Figma
Se il file Figma ha Variabili definite (il sistema di token nativo di Figma, disponibile nei piani Professional e Organization), figmascope le legge tramite l'endpoint REST API /v1/files/:key/variables/local. I nomi delle variabili vengono usati come chiavi dei token, normalizzati in kebab-case. Le modalità vengono collassate alla modalità predefinita a meno che il file non abbia una singola modalità, nel qual caso i valori di quella modalità vengono usati direttamente.
Le collezioni di variabili mappano alle chiavi di categoria di livello superiore in tokens.json. Una collezione chiamata "Color" produce tokens.color.*; "Spacing" produce tokens.spacing.*. Se il tuo file Figma usa nomi di collezione non standard, figmascope tenta di inferire la categoria dal tipo risolto della variabile.
Livello 2: Inferenza di frequenza
Molti file Figma — specialmente quelli più vecchi o file da clienti che non hanno adottato le Variabili — non hanno definizioni di variabili. figmascope gestisce questo percorrendo l'intero albero dei nodi e costruendo istogrammi di frequenza per colori di riempimento, valori di spaziatura, raggi degli angoli e proprietà tipografiche.
I valori che appaiono sopra una soglia di frequenza diventano token candidati. Vengono denominati per categoria e un indice sequenziale (color.0, color.1...) a meno che non si possa inferire un nome leggibile dall'uomo da come il valore viene usato (es. un colore usato solo su sfondi in più frame diventa color.surface).
Il manifesto _meta.json registra tokensSource come "variables" o "inferred", così il tuo prompt per l'agente può notare quando l'inferenza è stata usata:
// _meta.json — fallback inferito
{
"tokensSource": "inferred",
"warnings": [
{
"code": "tokens-inferred",
"message": "No Figma Variables found. Tokens were inferred from usage frequency."
}
]
}
I token inferiti sono utili ma non autorevoli. Trattali come punto di partenza, non come specifica di un design system.
Riferimenti ai token nell'IR del layout
I file IR per schermata (screens/*.json) fanno riferimento ai token tramite percorso usando stringhe $ref invece di incorporare valori grezzi. Questo mantiene l'IR compatto e garantisce che l'agente risolva sempre i valori da un'unica fonte di verità:
{
"kind": "stack",
"name": "PrimaryButton",
"direction": "horizontal",
"gap": { "$ref": "spacing.2" },
"padding": {
"top": 10, "right": 16, "bottom": 10, "left": 16
},
"background": { "$ref": "color.accent" },
"radius": { "$ref": "radius.sm" },
"children": [
{
"kind": "leaf",
"name": "ButtonLabel",
"type": "text",
"style": { "$ref": "typography.body" },
"color": { "$ref": "color.surface" }
}
]
}
Un agente che elabora questo nodo risolve color.accent in #d96a3a e spacing.2 in 8px dal file tokens.json parallelo. Nessuna ambiguità, nessuna allucinazione di valori.
Vedi IR per schermata spiegato per la documentazione completa dello schema dei nodi.
Usare tokens.json con Style Dictionary
L'output di figmascope è compatibile con Style Dictionary con configurazione minima. Poiché usa già la convenzione $value / $type, puoi puntare Style Dictionary direttamente a tokens.json:
// style-dictionary.config.js
module.exports = {
source: ['design/tokens.json'],
platforms: {
css: {
transformGroup: 'css',
prefix: 'fs',
buildPath: 'src/styles/',
files: [{ destination: 'tokens.css', format: 'css/variables' }]
},
js: {
transformGroup: 'js',
buildPath: 'src/',
files: [{ destination: 'tokens.js', format: 'javascript/es6' }]
}
}
};
Eseguendo style-dictionary build verranno prodotte proprietà CSS personalizzate e export di moduli ES dallo stesso file sorgente che usa l'agente.
Usare tokens.json con Tailwind
Un piccolo script converte tokens.json in un'estensione del tema Tailwind. La struttura è abbastanza piatta da attraversare senza ricorsione per i casi comuni:
// scripts/tokens-to-tailwind.js
const fs = require('fs');
const tokens = JSON.parse(fs.readFileSync('design/tokens.json', 'utf8'));
function flattenGroup(group) {
return Object.fromEntries(
Object.entries(group).map(([k, v]) => [k, v.$value])
);
}
const extend = {
colors: flattenGroup(tokens.color),
spacing: flattenGroup(tokens.spacing),
borderRadius: flattenGroup(tokens.radius),
};
console.log(JSON.stringify(extend, null, 2));
node scripts/tokens-to-tailwind.js > design/tailwind-extend.json
Poi in tailwind.config.ts:
import extend from './design/tailwind-extend.json';
export default {
content: ['./src/**/*.{ts,tsx}'],
theme: { extend },
};
Usare tokens.json con Jetpack Compose
Per i progetti Android, la struttura dei token si mappa in modo pulito a un object Kotlin. Puoi generarlo programmaticamente o chiedere a Claude Code di farlo. Per i token colore:
// Generated from design/tokens.json
object DesignTokens {
object Color {
val surface = Color(0xFFF6F2EA)
val ink = Color(0xFF1F1D1A)
val accent = Color(0xFFD96A3A)
val accentSoft = Color(0xFFF2C7A8)
}
object Spacing {
val s1 = 4.dp
val s2 = 8.dp
val s4 = 16.dp
val s8 = 32.dp
}
}
Vedi Jetpack Compose da Figma per una guida completa inclusa l'integrazione con MaterialTheme.
Cosa non contiene tokens.json
Conoscere i limiti dell'ambito aiuta a impostare aspettative corrette:
- Ombre — figmascope attualmente non esporta token drop-shadow o inner-shadow. I valori delle ombre appaiono inline sui nodi nell'IR dove presenti.
- Gradienti — i riempimenti con gradiente vengono esportati così come sono sui nodi foglia nell'IR, non come token denominati.
- Animazioni — i valori di timing, easing e transizione sono fuori ambito. Il supporto per le animazioni di Figma è nella modalità Prototype, che figmascope non legge.
- Breakpoint — i vincoli responsive non sono un concetto di Figma a livello di variabile; richiedono decisioni di design separate.
L'array warnings in _meta.json noterà tutti i valori che non hanno potuto essere esportati in modo pulito. Rivedilo prima di consegnare il bundle a un agente.
Come vengono derivati i nomi dei token
Quando figmascope legge le Variabili Figma, il nome della variabile in Figma diventa la chiave del token. Una variabile chiamata Colors/Surface/Primary in una collezione chiamata Color diventa tokens.color.surface.primary in tokens.json — il separatore del percorso è / in Figma, . nelle chiavi annidate JSON.
Figma consente nomi di variabili con spazi, lettere maiuscole e caratteri speciali. figmascope li normalizza:
- Gli spazi diventano trattini:
Primary Surface→primary-surface - Le maiuscole vengono minuscole:
AccentOrange→accent-orange - I caratteri di controllo e i mark Unicode bidi vengono rimossi tramite
sanitizeName - Il cirillico e altri script non-latini vengono traslitterati per compatibilità con gli slug
Il passaggio di traslitterazione è importante per i team internazionali. Un team di design ucraino che usa nomi di variabili in cirillico come Фон (sfondo) ottiene una chiave ASCII stabile (fon) nell'output, che è utilizzabile nei nomi di classi CSS e in JSON senza problemi di codifica. Il nome originale viene preservato come campo $description se presente nei metadati della Variabile Figma.
Verifica della copertura dei token prima della generazione del codice
Prima di consegnare il bundle a un agente, vale la pena verificare che la copertura dei token sembri ragionevole. Un rapido script Node che verifica se tutti i valori colore referenziati negli IR delle schermate si risolvono in voci in tokens.json:
// scripts/check-token-coverage.js
const fs = require('fs');
const glob = require('glob');
const tokens = JSON.parse(fs.readFileSync('design/tokens.json', 'utf8'));
const screenFiles = glob.sync('design/screens/*.json');
function getRef(obj) {
const refs = [];
if (obj && typeof obj === 'object') {
if (obj.$ref) refs.push(obj.$ref);
for (const v of Object.values(obj)) refs.push(...getRef(v));
}
return refs;
}
function resolveRef(ref, tokens) {
return ref.split('.').reduce((o, k) => o?.[k], tokens);
}
let missing = 0;
for (const file of screenFiles) {
const screen = JSON.parse(fs.readFileSync(file, 'utf8'));
for (const ref of getRef(screen)) {
if (!resolveRef(ref, tokens)) {
console.error(`Missing token: ${ref} (in ${file})`);
missing++;
}
}
}
if (missing === 0) console.log('All token refs resolve.');
else console.error(`${missing} unresolved token refs.`);
Zero riferimenti mancanti significa che l'agente sarà in grado di risolvere ogni $ref nell'IR del layout senza inventare valori. Se ci sono riferimenti mancanti, di solito significa che il file Figma è cambiato dopo che il bundle è stato esportato — riesegui figmascope per ottenere un export aggiornato. Puoi anche consultare il blog di figmascope per altri suggerimenti sul mantenimento della copertura dei token attraverso le iterazioni del design.