Das Standard-Exportziel von figmascope ist Jetpack Compose. Aber das Bundle ist agenten-agnostisch — die IR-Node-Arten, das Token-Format und String-Refs bilden genauso sauber auf React + Tailwind ab. Man muss dem Agenten nur sagen, JSX statt Kotlin zu verwenden.

Dieser Leitfaden deckt das IR-zu-JSX-Mapping ab, wie man tailwind.config.js mit Tokens aus tokens.json erweitert, und die Prompting-Muster, die auf der React-Seite die geringste Drift produzieren.

Ein wichtiger Vorbehalt vorab

Compose ist das, was figmascope am meisten testet. Das IR, das Token-Format und die CONTEXT.md-Einschränkungen wurden mit Compose im Hinterkopf designed. React + Tailwind funktioniert — das IR bildet sauber ab — aber man sieht etwas mehr Drift, besonders bei Typografie und Overlay-Layouts. Alles, was falsch aussieht, markieren und nach dem ersten Durchgang einen Token-Check durchführen.

Schritt 1: Bundle generieren und entzippen

unzip ~/Downloads/context-bundle.zip -d ./design/

ls design/
# CONTEXT.md  _meta.json  components/  screens/  strings.json  tokens.json

Schritt 2: Tailwind-Config mit Design-Tokens erweitern

Vor dem Prompting tokens.json in die tailwind.config.js mappen. Das ist der Schlüsselschritt, der Tailwind token-bewusst macht — statt hartcodierter Hex-Werte in className-Strings erhält man semantische Namen, die auf das Design zurückverfolgbar sind.

// tailwind.config.js
const tokens = require('./design/tokens.json')

// Farb-Map aufbauen: { 'brand-7f5cfe': '#7F5CFE', ... }
const colors = Object.fromEntries(
  Object.entries(tokens.color).map(([key, val]) => [
    `brand-${key}`, val
  ])
)

// Spacing-Map aufbauen: { 'ds-4': '4px', 'ds-8': '8px', ... }
const spacing = Object.fromEntries(
  Object.entries(tokens.spacing).map(([key, val]) => [
    `ds-${key}`, `${val}px`
  ])
)

// Border-Radius-Map aufbauen
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,
    }
  }
}

Das produziert Tailwind-Klassen wie bg-brand-7f5cfe, p-ds-16, rounded-ds-12. Nicht die schönsten Klassenamen, aber sie sind nachverfolgbar — jede Klasse mappt zurück auf einen Token-Key.

Wenn man lieber semantische Aliase hätte, eine Aliasing-Schicht hinzufügen:

// in theme.extend.colors:
primary: tokens.color['7f5cfe'],
background: tokens.color['f6f2ea'],
surface: tokens.color['ffffff'],

Dem Agenten beides geben — die rohe Token-Config und die semantischen Aliase — damit er den richtigen Namen im Kontext wählen kann.

Schritt 3: Den Agenten auf React + Tailwind prompen

CONTEXT.md sagt, das Standard-Ziel ist Compose. Explizit im Prompt überschreiben:

Implementiere ./design/screens/home.json als React-Funktionskomponente mit Tailwind CSS.

Framework-Überschreibung: ignoriere die Compose-Anweisungen in CONTEXT.md. Ziel: React + Tailwind.

Regeln:
- ./design/tokens.json lesen. Die Tokens sind in die Tailwind-Config erweitert —
  Tailwind-Klassen verwenden, die Token-Keys entsprechen (z.B. bg-brand-7f5cfe, p-ds-16).
- UI-Strings kommen aus ./design/strings.json. Importieren und per Key referenzieren.
- IR-Node-Art-Mapping:
    stack (axis:vertical)   → <div className="flex flex-col gap-[Xpx]">
    stack (axis:horizontal) → <div className="flex flex-row gap-[Xpx]">
    overlay                 → <div className="relative"> mit absolut positionierten Kindern
    absolute                → <div className="absolute" style={{"{{"}}top, left, width, height{{"}}"}}>
    leaf (text)             → <span> oder <p> mit Tailwind-Text-Klassen
    leaf (rectangle)        → <div> mit bg- und rounded-Klassen
- Keine Hex-Werte hartcodieren. Alle Farben müssen Tailwind-Klassen aus der Token-Config verwenden.
- Keine Strings hartcodieren. strings.json-Keys verwenden.

Output nach: src/screens/HomeScreen.tsx

Das IR-zu-JSX-Mapping

Hier ist die vollständige Mapping-Tabelle für React + Tailwind:

IR-ArtEigenschaftenJSX-Muster
stackaxis: "vertical"<div className="flex flex-col gap-ds-{n}">
stackaxis: "horizontal"<div className="flex flex-row gap-ds-{n}">
overlaygeschichtete Kinder<div className="relative"> mit className="absolute ..."-Kindern
absolutex, y, w, h<div className="absolute" style={{"{{"}}top: y, left: x, width: w, height: h{{"}}"}}>
leaftype: "text"<span className="text-{size} font-{weight} leading-{lh} text-brand-{color}">
leaftype: "rectangle"<div className="bg-brand-{color} rounded-ds-{r}">

Gap- und Padding-Werte: die ds-{n}-Spacing-Klassen aus der Tailwind-Config-Erweiterung verwenden. Wenn der Gap-Wert kein sauberer Token-Key ist, Tailwinds Arbitrary-Value-Syntax verwenden: gap-[20px].

Ein echtes Beispiel: Home-Screen-IR zu JSX

Mit demselben IR aus dem Compose-Walkthrough:

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>
  )
}

Jeder className ist nachverfolgbar. gap-ds-24spacing.24 → 24px. text-brand-7f5cfecolor.7f5cfe#7F5CFE. Wenn ein Wert driftet (z.B. der Agent schreibt gap-6 statt gap-ds-24), ist das sofort in einem Code-Review sichtbar.

Warum tokens.json + Tailwind-Config funktioniert

Beide Systeme sind token-first. Tailwind erweitert eine Basis-Config mit benutzerdefinierten Werten; tokens.json ist bereits als benutzerdefinierte Wertkarte strukturiert. Der Erweiterungsschritt (Schritt 2 oben) ist ein einmaliges Setup — danach verwendet der Agent Tailwind-Klassenamen, die semantisch mit dem Design-System verbunden sind, anstatt beliebige Utility-Klassen.

Das Ergebnis: wenn sich der Design-Token ändert (z.B. Primärfarbe wechselt von #7F5CFE zu #6B4EE6), aktualisiert man einen Wert in tokens.json, führt den Config-Import erneut aus, und Tailwind regeneriert. Der Komponentencode ändert sich nicht.

Token-Drift-Check

Nach der Implementierung den Agenten bitten, auf Drift zu prüfen:

Prüfe src/screens/HomeScreen.tsx auf Token-Drift.

Überprüfen:
1. Alle Hex-Farbwerte, die nicht durch eine Tailwind-Klasse aus der Token-Config referenziert werden.
2. Alle hartcodierten px- oder rem-Spacing-Werte, die ds-{n}-Klassen sein sollten.
3. Alle UI-Strings, die nicht aus design/strings.json stammen.

Verstöße auflisten. Ein Diff produzieren, das sie behebt.

Overlay und absolute — die schwierigen Fälle

Overlay-Nodes brauchen einen relative-Elternteil und absolute-positionierte Kinder. Das IR listet Kinder in Z-Reihenfolge (erstes = untere Ebene). Den Agenten anweisen, diese Reihenfolge im JSX beizubehalten — React rendert in DOM-Reihenfolge und CSS-position: absolute stapelt entsprechend.

Absolute Nodes verwenden rohe Pixel-Koordinaten aus Figma. Diese kommen fast immer aus Designs, die nicht mit Auto-Layout gebaut wurden. Wenn viele absolute Nodes zu sehen sind, bedeutet das meist, dass die Figma-Datei manuelle Positionierung hat — der generierte Code wird bei verschiedenen Viewport-Größen spröde sein. Das markieren und Refactoring zu Flex-Layouts in Betracht ziehen.

String-Handling in React

Im Gegensatz zu Android (wo strings.json-Keys auf R.string.*-Ressourcen-IDs mappen) importiert man in React das JSON direkt:

import strings from '../../design/strings.json'

// Verwendung
{strings['home.title'].value}
// oder mit Fallback
{strings['home.title']?.value ?? strings['home.title']?.fallback ?? 'Untitled'}

Wenn man i18n-Bibliotheken verwendet (react-i18next, next-intl), mappen die Punkt-Notation-Keys in strings.json direkt auf Translation-Key-Namespaces. Dem Agenten sagen, welche i18n-Bibliothek verwendet wird, damit er das richtige Aufruf-Muster generiert.

Ehrliche Lücken auf der React-Seite

Typografie-Utilities. Tailwinds Text-Utilities (text-xs, text-2xl) bilden nicht 1:1 auf die typography-Tokens in tokens.json ab. Tailwind hat eine feste Typ-Skala; die Token-Datei hat beliebige Größen. Entweder Tailwinds fontSize-Config mit Token-Werten erweitern oder Arbitrary Values verwenden (text-[24px]). Beides funktioniert; die Config zu erweitern ist sauberer.

Line Height. Gleiches Problem — Tailwinds Leading-Utilities stimmen nicht mit beliebigen lineHeight-Werten überein. leading-[{value}] verwenden oder die Config erweitern.

Verläufe. Im IR nicht unterstützt. Jeder Verlaufs-Fill erscheint als Warnung in _meta.json und wird aus der Fill-Eigenschaft des Nodes weggelassen. Manuell handhaben.

Keine dieser Punkte ist ein Blocker — es sind bekannte Lücken. Das token-bewusste Fundament ist solide; die Ränder brauchen einfach manuelles Handling.

Mit figmascope beginnen, um das Bundle zu exportieren, dann diesen Leitfaden zusammen mit dem Cursor-Workflow oder dem Claude Code Workflow verwenden, um die Implementierung voranzutreiben.