Todo export do figmascope inclui tokens.json. É a ponte entre os valores visuais do Figma e as constantes tipadas que seu código precisa. Este post cobre o schema, como as chaves são nomeadas, o que acontece quando um arquivo Figma não tem Variables e onde o sistema de tokens honestamente fica aquém.

O schema

A estrutura de nível superior tem quatro seções:

{
  "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": {}
}

O formato é estilo W3C Design Tokens Community Group: cada token é um objeto com $value e $type. Não é uma implementação estrita do W3C DTCG — o figmascope é anterior à publicação final da especificação e não implementa tipos compostos como fontFamily — mas é próximo o suficiente para que tooling ciente do DTCG possa analisá-lo com adaptação mínima.

O objeto typography vazio não é um bug. Está coberto abaixo.

Nomenclatura de chave derivada de valor

Quando um arquivo Figma tem Variables, as chaves de token vêm dos nomes de Variable que o designer definiu. spacing.md, color.brand.primary, o que quer que o design system use.

Quando um arquivo Figma não tem Variables — o que é a maioria dos arquivos Figma do mundo real — o figmascope recorre à nomenclatura derivada de valor. Um valor de espaçamento de 16 se torna spacing.16. Uma cor #7f5cfe se torna color.7f5cfe. Um corner radius de 4 se torna radius.4.

Este é um tradeoff deliberado. Nomes derivados de valor são feios mas estáveis. São derivados do valor real, então duas execuções diferentes do mesmo arquivo Figma produzem a mesma chave. spacing.16 sempre significa 16dp. O agente pode contar com isso.

A alternativa seriam nomes posicionais como spacing.1, spacing.2 etc. Esses são frágeis — adicione um valor de espaçamento menor e tudo muda. Nomes derivados de valor não mudam.

Nomes derivados de valor são um fallback para arquivos que deveriam ter Variables mas não têm. Se seu design system tem 40 valores de espaçamento que precisam de nomes semânticos, convença o designer a configurar Variables. O fallback de inferência existe para arquivos do mundo real, não como substituto de um sistema de token real. Você pode rodar o figmascope no seu próprio arquivo para ver qual caminho de sourcing ele toma.

O campo tokensSource e o que ele significa

_meta.json inclui um campo tokensSource que informa como os tokens foram derivados:

ValorSignificado
"figma-variables" O arquivo Figma tem Variables e foram usadas diretamente. Nomes de tokens são atribuídos pelo designer. Cobertura total.
"inferred-from-frequency" Sem Variables. O figmascope escaneou todos os nós, encontrou valores frequentemente recorrentes e os promoveu a tokens. A cobertura depende da consistência do design.
"none" Sem Variables e a inferência não produziu nada útil. tokens.json terá seções vazias ou quase vazias.

O aviso "tokens-inferred-from-frequency" em _meta.json espelha isso. Se você o vir, a cobertura de tokens é melhor-esforço.

Quando tokensSource é "inferred-from-frequency", o algoritmo de inferência é: encontre todos os valores de dimensão que aparecem em três ou mais nós nos campos de padding, gap ou cornerRadius. Promova-os a tokens de spacing ou radius respectivamente. Faça o mesmo para cores de fill. Valores que aparecem apenas uma ou duas vezes são tratados como pontuais, não promovidos.

Isso funciona bem para designs internamente consistentes. Funciona mal para designs exploratórios onde o espaçamento varia livremente. Os avisos de _meta.json existem precisamente para que o agente saiba em qual situação está.

Por que typography frequentemente está vazio

Tokens de typography requerem Figma Variables com tipo FLOAT ou STRING para serem extraídos de forma confiável. Estilos de texto existem no Figma como estilos compartilhados, não Variables, e a superfície de API para estilos é diferente da API de Variables.

O figmascope v0.4 extrai typography quando Variables a cobrem. Ele não tenta inferência baseada em frequência para typography porque os tokens de typography úteis — família de fonte, height de linha, letter spacing, combinações de weight — não têm nomes derivados de valor óbvios da forma que spacing.16 tem. Uma chave fontSize.14 é muito menos útil que typography.body.small, e gerar um nome ruim é pior que não gerar nenhum nome.

Então o resultado é honesto: se seu arquivo Figma tem Variables de typography, você obtém tokens de typography. Se não, você obtém um objeto vazio e o agente é informado via CONTEXT.md que a cobertura de typography pode ser parcial.

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

O agente vê isso e sabe ser conservador sobre referências a tokens de typography. Ele gera código fallback com valores explícitos e um comentário TODO em vez de inventar um nome de token.

Como o agente usa tokens.json

A restrição do CONTEXT.md é: "Nunca hardcode valores dp se um token existe dentro de ±2dp." A tolerância de ±2dp lida com arredondamento. Se um nó tem paddingLeft: 15 e spacing.16 existe, o agente usa spacing.16. Se o token mais próximo é spacing.24, sem correspondência — o agente usa o valor literal.

Para cores, a correspondência é exata no valor hex após normalização para 6 dígitos minúsculos. #7F5CFE corresponde a color.7f5cfe.

Para corner radius, mesma regra ±2dp do spacing.

A saída prática para um alvo Jetpack Compose parece assim:

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

// Com tokensSource inferred-from-frequency (mesma saída visual, mesmas refs de token)
Surface(
    shape = RoundedCornerShape(Radius.radius8),
    color = Color.color7f5cfe
) { ... }

Os nomes derivados de valor são menos legíveis. Ainda são melhores que valores hardcoded.

Comparação com outras abordagens de extração de token

O painel nativo "Inspect" do Figma mostra valores por nó. Não há arquivo de token exportado. Você teria que criar um manualmente ou usar um plugin como Tokens Studio. Ambos exigem esforço do designer e manutenção contínua.

O figmascope extrai tokens automaticamente a cada export. Se o arquivo muda, re-exporte e os tokens refletem o estado atual. O tradeoff é que sem Variables, os nomes são derivados de valor em vez de semânticos — mas você obtém um arquivo de tokens toda vez, sem plugin ou etapa de fluxo extra.

O Tokens Studio (anteriormente integração com Style Dictionary) requer que o designer configure o plugin, mantenha um arquivo JSON no arquivo Figma e o sincronize. Essa é a solução certa para um design system maduro. A abordagem do figmascope é a solução certa para arquivos que ainda não chegaram lá, que são a maioria dos arquivos.

A extração de tokens é um snapshot melhor-esforço do que existe no arquivo. Não é um substituto para um design system token-first. É a coisa que você usa enquanto constrói em direção a um.

Conectando tokens.json ao seu codebase

A estrutura JSON é plana o suficiente para que gerar um objeto Kotlin ou módulo TypeScript a partir dela seja simples. Um script simples:

// tokens.json → objeto Kotlin (simplificado)
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

Se você já usa um pipeline de design tokens, o formato W3C-ish é próximo o suficiente para ser inserido no Style Dictionary com um transformer customizado para as chaves $value/$type.

O restante de como tokens interagem com o IR está coberto em IR por Tela. Para como tokens interagem com o contexto mais amplo do agente, veja Anatomia do CONTEXT.md. Para exportar tokens do seu próprio arquivo Figma, vá ao figmascope.dev.