Jeder figmascope-Export enthält tokens.json. Es ist die Brücke zwischen Figmas visuellen Werten und den typisierten Konstanten, die der Code braucht. Dieser Beitrag deckt das Schema ab, wie Keys benannt werden, was passiert, wenn eine Figma-Datei keine Variables hat, und wo das Token-System ehrlich gesagt an seine Grenzen stößt.

Das Schema

Die Top-Level-Struktur hat vier Abschnitte:

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

Das Format ist W3C Design Tokens Community Group-ähnlich: jeder Token ist ein Objekt mit $value und $type. Es ist keine strikte W3C-DTCG-Implementierung — figmascope ist älter als die finale Spec-Veröffentlichung und implementiert keine Composite-Typen wie fontFamily — aber es ist nah genug, dass DTCG-bewusstes Tooling es mit kleiner Anpassung parsen kann.

Das leere typography-Objekt ist kein Bug. Es wird unten behandelt.

Wertabgeleitete Key-Benennung

Wenn eine Figma-Datei Variables hat, kommen Token-Keys aus den Variable-Namen, die der Designer gesetzt hat. spacing.md, color.brand.primary, was auch immer das Design-System verwendet.

Wenn eine Figma-Datei keine Variables hat — was die Mehrheit der realen Figma-Dateien ist — fällt figmascope auf wertabgeleitete Benennung zurück. Ein Spacing-Wert von 16 wird zu spacing.16. Eine Farbe #7f5cfe wird zu color.7f5cfe. Ein Corner Radius von 4 wird zu radius.4.

Das ist ein bewusster Kompromiss. Wertabgeleitete Namen sind hässlich, aber stabil. Sie sind aus dem tatsächlichen Wert abgeleitet, also produzieren zwei verschiedene Läufe derselben Figma-Datei denselben Key. spacing.16 bedeutet immer 16dp. Der Agent kann sich darauf verlassen.

Die Alternative wären positionale Namen wie spacing.1, spacing.2 usw. Diese sind spröde — einen kleineren Spacing-Wert hinzufügen und alles verschiebt sich. Wertabgeleitete Namen verschieben sich nicht.

Wertabgeleitete Namen sind ein Fallback für Dateien, die Variables haben sollten, aber nicht haben. Wenn das Design-System 40 Spacing-Werte hat, die alle semantische Namen brauchen, den Designer dazu bringen, Variables einzurichten. Der Inferenz-Fallback existiert für reale Dateien, nicht als Ersatz für ein echtes Token-System. Man kann figmascope auf der eigenen Datei ausführen, um zu sehen, welchen Sourcing-Pfad es nimmt.

Das tokensSource-Feld und was es bedeutet

_meta.json enthält ein tokensSource-Feld, das angibt, wie die Tokens abgeleitet wurden:

WertBedeutung
"figma-variables" Die Figma-Datei hat Variables und sie wurden direkt verwendet. Token-Namen sind designer-zugewiesen. Vollständige Abdeckung.
"inferred-from-frequency" Keine Variables. figmascope hat alle Nodes gescannt, häufig wiederkehrende Werte gefunden, sie zu Tokens befördert. Abdeckung hängt von der Konsistenz des Designs ab.
"none" Keine Variables und Inferenz ergab nichts Nützliches. tokens.json hat leere oder fast leere Abschnitte.

Die "tokens-inferred-from-frequency"-Warnung in _meta.json spiegelt das wider. Wenn sie zu sehen ist, ist die Token-Abdeckung Best-Effort.

Wenn tokensSource "inferred-from-frequency" ist, ist der Inferenz-Algorithmus: alle Dimensionswerte finden, die in drei oder mehr Nodes' Padding-, Gap- oder cornerRadius-Feldern erscheinen. Diese zu Spacing- oder Radius-Tokens befördern. Dasselbe für Fill-Farben tun. Werte, die nur einmal oder zweimal erscheinen, werden als einmalig behandelt, nicht befördert.

Das funktioniert gut für intern konsistente Designs. Es funktioniert schlecht für explorative Designs, bei denen Spacing frei variiert. Die _meta.json-Warnungen existieren genau damit der Agent weiß, in welcher Situation er sich befindet.

Warum Typografie oft leer ist

Typografie-Tokens erfordern Figma-Variables mit Typ FLOAT oder STRING, um zuverlässig extrahiert zu werden. Text-Styles existieren in Figma als geteilte Styles, nicht als Variables, und die API-Oberfläche für Styles unterscheidet sich von der Variables-API.

figmascope v0.4 extrahiert Typografie, wenn Variables sie abdecken. Es versucht keine häufigkeitsbasierte Inferenz für Typografie, weil die nützlichen Typografie-Tokens — Schriftfamilie, Zeilenhöhe, Buchstabenabstand, Gewichtskombinationen — keine offensichtlichen wertabgeleiteten Namen haben, wie spacing.16 sie hat. Ein fontSize.14-Key ist viel weniger nützlich als typography.body.small, und einen schlechten Namen zu generieren ist schlimmer als keinen zu generieren.

Das Ergebnis ist also ehrlich: wenn die Figma-Datei Typografie-Variables hat, werden Typografie-Tokens ausgegeben. Wenn nicht, wird ein leeres Objekt ausgegeben und der Agent wird über CONTEXT.md informiert, dass die Typografie-Abdeckung möglicherweise partiell ist.

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

Der Agent sieht das und weiß, bei Typografie-Token-Referenzen konservativ zu sein. Er generiert Fallback-Code mit expliziten Werten und einem TODO-Kommentar, anstatt einen Token-Namen zu erfinden.

Wie der Agent tokens.json verwendet

Die CONTEXT.md-Einschränkung ist: "Keine dp-Werte hartcodieren, wenn ein Token innerhalb von ±2dp existiert." Die ±2dp-Toleranz behandelt Rundung. Wenn ein Node paddingLeft: 15 hat und spacing.16 existiert, verwendet der Agent spacing.16. Wenn der nächste Token spacing.24 ist, kein Match — der Agent verwendet den Literal-Wert.

Für Farben ist das Matching exakt auf dem Hex-Wert nach Normalisierung auf 6-stelliges Kleinbuchstaben. #7F5CFE matcht color.7f5cfe.

Für Corner Radius dieselbe ±2dp-Regel wie Spacing.

Der praktische Output für ein Jetpack-Compose-Ziel sieht so aus:

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

// Mit inferred-from-frequency tokensSource (gleicher visueller Output, gleiche Token-Refs)
Surface(
    shape = RoundedCornerShape(Radius.radius8),
    color = Color.color7f5cfe
) { ... }

Die wertabgeleiteten Namen sind weniger lesbar. Sie sind immer noch besser als hartcodierte Werte.

Vergleich mit anderen Token-Extraktionsansätzen

Figmas natives "Inspect"-Panel zeigt Werte pro Node. Es gibt keine exportierte Token-Datei. Man müsste manuell eine erstellen oder ein Plugin wie Tokens Studio verwenden. Beides erfordert Designer-Aufwand und laufende Wartung.

figmascope extrahiert Tokens automatisch bei jedem Export. Wenn sich die Datei ändert, erneut exportieren und die Tokens spiegeln den aktuellen Zustand wider. Der Kompromiss ist, dass ohne Variables die Namen wertabgeleitet statt semantisch sind — aber man bekommt jedes Mal eine Token-Datei, ohne ein Plugin oder einen extra Workflow-Schritt.

Tokens Studio (früher Style Dictionary Integration) erfordert, dass der Designer das Plugin einrichtet, eine JSON-Datei in der Figma-Datei pflegt und sie synchronisiert. Das ist die richtige Lösung für ein ausgereiftes Design-System. figmascopes Ansatz ist die richtige Lösung für Dateien, die noch nicht so weit sind, was die meisten Dateien sind.

Die Token-Extraktion ist ein Best-Effort-Snapshot dessen, was in der Datei existiert. Es ist kein Ersatz für ein Token-first-Design-System. Es ist das, was man verwendet, während man auf eines hinarbeitet.

tokens.json mit der Codebase verdrahten

Die JSON-Struktur ist flach genug, dass das Generieren eines Kotlin-Objekts oder TypeScript-Moduls daraus unkompliziert ist. Ein einfaches Skript:

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

Wenn bereits eine Design-Token-Pipeline verwendet wird, ist das W3C-ähnliche Format nah genug, um es mit einem benutzerdefinierten Transformer für die $value/$type-Keys in Style Dictionary einzubringen.

Der Rest, wie Tokens mit dem IR interagieren, ist in Per-Screen IR beschrieben. Für wie Tokens mit dem breiteren Agenten-Kontext interagieren, siehe Aufbau von CONTEXT.md. Für den Design-Token-Export-Workflow von Anfang bis Ende, siehe Design Token Export. Um Tokens aus der eigenen Figma-Datei zu exportieren, zu figmascope.dev gehen.