Chaque export de figmascope inclut tokens.json. C'est le pont entre les valeurs visuelles de Figma et les constantes typées dont votre code a besoin. Cet article couvre le schéma, comment les clés sont nommées, ce qui se passe quand un fichier Figma n'a pas de Variables, et où le système de tokens est honnêtement limité.

Le schéma

La structure de niveau supérieur a quatre sections :

{
  "spacing": {
    "spacing.4":  { "$value": 4,  "$type": "dimension" },
    "spacing.8":  { "$value": 8,  "$type": "dimension" },
    "spacing.12": { "$value": 12, "$type": "dimension" },
    "spacing.16": { "$value": 16, "$type": "dimension" },
    "spacing.24": { "$value": 24, "$type": "dimension" }
  },
  "radius": {
    "radius.4":  { "$value": 4,  "$type": "dimension" },
    "radius.8":  { "$value": 8,  "$type": "dimension" },
    "radius.12": { "$value": 12, "$type": "dimension" }
  },
  "color": {
    "color.7f5cfe": { "$value": "#7f5cfe", "$type": "color" },
    "color.ffffff": { "$value": "#ffffff", "$type": "color" },
    "color.1a1a2e": { "$value": "#1a1a2e", "$type": "color" }
  },
  "typography": {}
}

Le format est proche du W3C Design Tokens Community Group : chaque token est un objet avec $value et $type. Ce n'est pas une implémentation stricte du W3C DTCG — figmascope est antérieur à la publication finale de la spec et n'implémente pas les types composites comme fontFamily — mais c'est suffisamment proche pour que les outils compatibles DTCG puissent le parser avec une adaptation mineure.

L'objet typography vide n'est pas un bug. Il est couvert ci-dessous.

Nommage des clés dérivé des valeurs

Quand un fichier Figma a des Variables, les clés de tokens viennent des noms de Variable que le designer a définis. spacing.md, color.brand.primary, selon ce qu'utilise le système de design.

Quand un fichier Figma n'a pas de Variables — ce qui est le cas de la majorité des fichiers Figma réels — figmascope se rabat sur le nommage dérivé des valeurs. Une valeur d'espacement de 16 devient spacing.16. Une couleur #7f5cfe devient color.7f5cfe. Un rayon de coin de 4 devient radius.4.

C'est un compromis délibéré. Les noms dérivés des valeurs sont laids mais stables. Ils sont dérivés de la valeur réelle, donc deux exécutions différentes du même fichier Figma produisent la même clé. spacing.16 signifie toujours 16dp. L'agent peut s'y fier.

L'alternative serait des noms positionnels comme spacing.1, spacing.2, etc. Ceux-ci sont fragiles — ajoutez une valeur d'espacement plus petite et tout décale. Les noms dérivés des valeurs ne décalent pas.

Les noms dérivés des valeurs sont un fallback pour les fichiers qui devraient avoir des Variables mais n'en ont pas. Si votre système de design a 40 valeurs d'espacement qui ont toutes besoin de noms sémantiques, encouragez le designer à configurer des Variables. Le fallback par inférence existe pour les fichiers réels, pas comme substitut à un vrai système de tokens. Vous pouvez exécuter figmascope sur votre propre fichier pour voir quel chemin de sourcing il prend.

Le champ tokensSource et ce qu'il signifie

_meta.json inclut un champ tokensSource qui vous indique comment les tokens ont été dérivés :

ValeurSignification
"figma-variables" Le fichier Figma a des Variables et elles ont été utilisées directement. Les noms de tokens sont assignés par le designer. Couverture complète.
"inferred-from-frequency" Pas de Variables. figmascope a scanné tous les nœuds, trouvé des valeurs fréquemment récurrentes, et les a promus en tokens. La couverture dépend de la cohérence du design.
"none" Pas de Variables et l'inférence n'a rien produit d'utile. tokens.json aura des sections vides ou quasi-vides.

L'avertissement "tokens-inferred-from-frequency" dans _meta.json reflète cela. Si vous le voyez, la couverture des tokens est au mieux.

Quand tokensSource est "inferred-from-frequency", l'algorithme d'inférence est : trouver toutes les valeurs de dimension qui apparaissent dans les champs padding, gap ou cornerRadius de trois nœuds ou plus. Promouvoir celles-ci en tokens d'espacement ou de rayon respectivement. Faire de même pour les couleurs de fill. Les valeurs qui n'apparaissent qu'une ou deux fois sont traitées comme des cas uniques, non promus.

Cela fonctionne bien pour les designs qui sont cohérents en interne. Cela fonctionne mal pour les designs exploratoires où l'espacement varie librement. Les avertissements _meta.json existent précisément pour que l'agent sache dans quelle situation il se trouve.

Pourquoi la typographie est souvent vide

Les tokens de typographie nécessitent des Variables Figma de type FLOAT ou STRING pour être extraits de manière fiable. Les styles de texte existent dans Figma comme styles partagés, pas comme Variables, et la surface API pour les styles est différente de l'API Variables.

figmascope v0.4 extrait la typographie quand les Variables la couvrent. Il ne tente pas l'inférence basée sur la fréquence pour la typographie parce que les tokens de typographie utiles — famille de polices, hauteur de ligne, espacement des lettres, combinaisons de graisse — n'ont pas de noms dérivés des valeurs évidents comme spacing.16 en a. Une clé fontSize.14 est beaucoup moins utile que typography.body.small, et générer un mauvais nom est pire que de n'en générer aucun.

Donc le résultat est honnête : si votre fichier Figma a des Variables de typographie, vous obtenez des tokens de typographie. Sinon, vous obtenez un objet vide et l'agent est informé via CONTEXT.md que la couverture de typographie peut être partielle.

// _meta.json
{
  "tokensSource": "inferred-from-frequency",
  "warnings": [
    "tokens-inferred-from-frequency"
  ]
}

L'agent voit cela et sait être conservateur concernant les références de tokens de typographie. Il génère du code de fallback avec des valeurs explicites et un commentaire TODO plutôt qu'inventer un nom de token.

Comment l'agent utilise tokens.json

La contrainte CONTEXT.md est : « Ne jamais coder en dur des valeurs dp si un token existe à ±2dp près. » La tolérance de ±2dp gère les arrondis. Si un nœud a paddingLeft: 15 et que spacing.16 existe, l'agent utilise spacing.16. Si le token le plus proche est spacing.24, pas de correspondance — l'agent utilise la valeur littérale.

Pour les couleurs, la correspondance est exacte sur la valeur hex après normalisation en minuscules à 6 chiffres. #7F5CFE correspond à color.7f5cfe.

Pour le rayon de coin, même règle de ±2dp que pour l'espacement.

La sortie pratique pour une cible Jetpack Compose ressemble à ceci :

// Avec tokensSource figma-variables
Surface(
    shape = RoundedCornerShape(Radius.radius8),
    color = Color.Brand.Primary
) {
    Column(
        verticalArrangement = Arrangement.spacedBy(Spacing.spacing16),
        modifier = Modifier.padding(horizontal = Spacing.spacing24)
    ) { ... }
}

// Avec tokensSource inferred-from-frequency (même sortie visuelle, mêmes refs de token)
Surface(
    shape = RoundedCornerShape(Radius.radius8),
    color = Color.color7f5cfe
) { ... }

Les noms dérivés des valeurs sont moins lisibles. Ils sont toujours meilleurs que des valeurs codées en dur.

Comparaison avec d'autres approches d'extraction de tokens

Le panneau « Inspect » natif de Figma montre les valeurs par nœud. Il n'y a pas de fichier token exporté. Vous devriez en créer un manuellement ou utiliser un plugin comme Tokens Studio. Les deux nécessitent un effort du designer et une maintenance continue.

figmascope extrait les tokens automatiquement à chaque export. Si le fichier change, ré-exportez et les tokens reflètent l'état courant. Le compromis est que sans Variables, les noms sont dérivés des valeurs plutôt que sémantiques — mais vous obtenez un fichier token à chaque fois, sans plugin ni étape de workflow supplémentaire.

Tokens Studio (anciennement intégration Style Dictionary) nécessite que le designer configure le plugin, maintienne un fichier JSON dans le fichier Figma, et le synchronise. C'est la bonne solution pour un système de design mature. L'approche de figmascope est la bonne solution pour les fichiers qui n'en sont pas encore là, ce qui représente la plupart des fichiers.

L'extraction de tokens est un instantané au mieux de ce qui existe dans le fichier. Ce n'est pas un substitut à un système de design token-first. C'est ce que vous utilisez pendant que vous construisez vers un tel système.

Câbler tokens.json à votre codebase

La structure JSON est suffisamment plate pour qu'il soit simple de générer un objet Kotlin ou un module TypeScript à partir de celle-ci. Un script simple :

// tokens.json → objet Kotlin (simplifié)
const tokens = JSON.parse(fs.readFileSync('tokens.json', 'utf-8'));

let output = 'object Spacing {\n';
for (const [key, token] of Object.entries(tokens.spacing)) {
    const name = key.replace('spacing.', 'spacing').replace('.', '_');
    output += `    val ${name} = ${token.$value}.dp\n`;
}
output += '}';
// → val spacing16 = 16.dp

Si vous utilisez déjà un pipeline de tokens de design, le format proche W3C est suffisamment proche pour être intégré dans Style Dictionary avec un transformateur personnalisé pour les clés $value/$type.

Le reste de comment les tokens interagissent avec l'IR est couvert dans l'IR par écran. Pour comment les tokens interagissent avec le contexte d'agent plus large, voir Anatomie de CONTEXT.md. Pour exporter les tokens de votre propre fichier Figma, rendez-vous sur figmascope.dev.