Der Unterschied zwischen einer Design-Datei und einer Komponentenbibliothek ist Identität. Eine Design-Datei enthält Formen. Eine Komponentenbibliothek enthält benannte, wiederverwendbare Teile mit stabilen Bezeichnern. components/inventory.json ist figmascopes Antwort auf die Frage: „Welche Teile in diesem Design sollen Komponenten sein, und wie verbinden sich Instanzen zurück zu ihnen?"
Das Schema
components/inventory.json ist ein Array von Objekten:
[
{
"id": "789:012",
"name": "PrimaryButton",
"type": "COMPONENT"
},
{
"id": "789:013",
"name": "SecondaryButton",
"type": "COMPONENT"
},
{
"id": "890:100",
"name": "Button",
"type": "COMPONENT_SET"
},
{
"id": "890:101",
"name": "Button/Primary/Default",
"type": "COMPONENT"
},
{
"id": "890:102",
"name": "Button/Primary/Pressed",
"type": "COMPONENT"
}
]
Jeder Eintrag hat drei Felder:
id: Die Figma-Knoten-ID, stabil über Sitzungen hinweg für dieselbe Datei.name: Der Komponentenname aus Figma. Für Varianten innerhalb eines COMPONENT_SET verwendet Figma Slash-Notation:Button/Primary/Default.type: Entweder"COMPONENT"(eine einzelne Komponentendefinition) oder"COMPONENT_SET"(eine Gruppe von Varianten).
Das ist das vollständige Schema. Es ist bewusst minimal gehalten.
Wie Instanzen zurückverlinken
Die Verknüpfung von Instanzen zum Inventar erfolgt im Per-Screen-IR. Jeder Knoten, der eine INSTANCE einer Komponente ist, trägt componentId und componentName:
// screens/home.json
{
"kind": "stack",
"id": "555:201",
"componentId": "789:012",
"componentName": "PrimaryButton",
"axis": "horizontal",
...
}
Die componentId stimmt mit einer id in inventory.json überein. Der componentName stimmt mit dem name überein. Beide Felder sind vorhanden, damit der Agent nicht inventory.json laden muss, um den Namen zu erhalten — aber wenn er wissen muss, ob diese Komponente Teil eines COMPONENT_SET ist, greift er auf das Inventar zurück.
So weiß ein Coding-Agent, dass der Button-Knoten auf dem Screen kein benutzerdefiniertes Layout ist, das er im Detail reproduzieren soll — es ist eine Instanz von PrimaryButton, und er sollte das vorhandene PrimaryButton()-Composable aufrufen, anstatt aus den IR-Strukturdetails ein neues zu generieren.
Ohne Komponentenidentität generiert ein Agent denselben Button von Grund auf für jeden Screen. Mit ihr ruft der Agent das vorhandene Composable auf und überspringt die strukturelle Codegen-Arbeit völlig. Der Unterschied liegt darin, ob Sie 40
Row { Text(...) Surface { ... } }-Blöcke oder 40PrimaryButton(...)-Aufrufe erhalten.
Warum das für die Refactoring-Sicherheit wichtig ist
Design-Systeme werden refaktoriert. Ein Button erhält eine neue Form, neues Padding, eine andere Farbe. Wenn Ihr gesamter generierter Code strukturell wörtlich war, bedeutet das Refactoring das Anfassen jedes Screens, der einen Button enthält. Wenn der generierte Code die PrimaryButton-Composable-Referenz verwendete, ist das Refactoring eine einzige Datei.
Das Inventar macht dies möglich, indem es den Vertrag zur Generierungszeit festlegt: „Dieser Knoten ist kein benutzerdefiniertes Layout, es ist eine Instanz einer bekannten Komponente." Der Agent, der diesen Vertrag respektiert, generiert Code, der bereits für Refactoring auf Komponentenebene strukturiert ist.
Das ist der primäre strukturelle Vorteil gegenüber screenshot-basierten Handoffs. Ein Screenshot eines Buttons sind Pixel. Er hat keine Identität. Ein Agent, der von einem Screenshot arbeitet, wird strukturellen Code für den Button auf jedem Screen generieren, immer. Ein Agent, der aus dem IR mit Inventarverknüpfung arbeitet, kann die Instanz erkennen und stattdessen die Komponentenreferenz verwenden.
COMPONENT vs. COMPONENT_SET
Figmas Komponentensystem hat zwei Ebenen. Ein COMPONENT ist eine einzelne Definition. Ein COMPONENT_SET ist ein Container für Varianten — was Figma „Varianten" nennt (z.B. ein Button mit Primary/Secondary/Destructive- und Default/Hovered/Pressed-Zuständen).
In der Praxis referenziert eine Instanz auf einem Screen immer einen COMPONENT (eine spezifische Variante), nicht das COMPONENT_SET. Das COMPONENT_SET ist vorhanden, damit der Agent die vollständige Variantenoberfläche kennt, wenn er die Zustandsmaschine der Komponente implementieren muss.
// Inventareinträge für ein Button-Set
{ "id": "890:100", "name": "Button", "type": "COMPONENT_SET" }
{ "id": "890:101", "name": "Button/Primary/Default", "type": "COMPONENT" }
{ "id": "890:102", "name": "Button/Primary/Pressed", "type": "COMPONENT" }
{ "id": "890:103", "name": "Button/Secondary/Default", "type": "COMPONENT" }
// Instanz im Screen-IR referenziert eine spezifische Variante
{ "componentId": "890:101", "componentName": "Button/Primary/Default" }
Ein Agent, der Compose-Code dafür generiert, weiß: Die Komponente ist ein Button mit einem Primary-Stil und einem Default-Zustand. Er kann schlussfolgern, dass die Funktionssignatur wahrscheinlich style: ButtonStyle- und state: ButtonState-Parameter enthält, oder zumindest Button/Primary/Default als semantische Referenz für einen primären Button in seinem Standardzustand verwenden.
Die 300-Einträge-Grenze
figmascope begrenzt inventory.json auf 300 Einträge. Figma-Dateien in großem Maßstab — insbesondere Design-Systeme mit erschöpfenden Komponentenbibliotheken — können Tausende von Komponenten haben. Alle in ein Kontext-Bundle aufzunehmen, das an ein LLM gesendet werden soll, würde das Kontextfenster mit Definitionen auffüllen, die der Agent für die implementierten Screens nicht benötigt.
Wenn die Grenze erreicht wird, erscheint ein _truncated-Feld im Inventar:
[
{ "id": "...", "name": "...", "type": "COMPONENT" },
...
{ "_truncated": true, "totalCount": 847, "included": 300 }
]
Das totalCount-Feld zeigt, wie viele Komponenten in der Datei existieren. included zeigt, wie viele es ins Inventar geschafft haben. Die Reihenfolge basiert auf dem ersten Auftreten im Figma-Knotenbaum, sodass früh im Dokument referenzierte Komponenten (typischerweise die primären Screens) eher aufgenommen werden.
Wenn Sie an Screens arbeiten, die spät im Dokument definierte Komponenten verwenden und diese nicht im Inventar sind, haben die IR-Knoten dieser Instanzen trotzdem componentId und componentName — die Identitätsinformation ist auch dann erhalten, wenn die Komponente nicht im Inventar aufgelistet ist. Der Agent kennt den Namen der Komponente aus dem IR, auch ohne den Inventareintrag.
Was das Inventar nicht enthält
Das Inventar ist eine Identitätsliste, keine Implementierungsspezifikation. Es teilt Ihnen mit, dass eine Komponente namens PrimaryButton mit ID 789:012 existiert. Es sagt Ihnen nicht:
- Welche Props die Komponente akzeptiert
- Welche Zustände sie hat
- Wie die Komponente intern strukturiert ist (das steht in den IR-Knoten, die INSTANCEs sind)
- Was die Quellfigma-Datei der Komponente ist (wenn sie aus einer verknüpften Bibliothek stammt)
Diese Lücken sind in v0.4 beabsichtigt. Vollständige Komponenten-Prop-Inferenz aus der IR-Struktur ist möglich, würde aber bei Komponenten mit komplexer Variantenlogik unzuverlässige Ergebnisse liefern. Das Inventar liefert stabile Identität. Implementierungsdetails kommen aus Ihrer vorhandenen Codebasis, auf die der Agent ebenfalls Zugriff hat.
Der richtige Workflow: Der Agent sieht eine componentId: "789:012", schlägt sie im Inventar als PrimaryButton nach, sucht dann in Ihrer Kotlin-Codebasis nach PrimaryButton, um die tatsächliche Funktionssignatur zu verstehen. Das Inventar ist die Brücke zwischen Design und Code, kein Ersatz für den Code. Sie können ein Inventar aus jeder Figma-Datei auf figmascope.dev exportieren.
Komponentenidentität im IR ist das, was „Code aus diesem Design generieren" von „Code generieren, der in eine vorhandene Codebasis passt" trennt. Ersteres ist ein Spielzeug. Letzteres ist die eigentliche Aufgabe.
Vergleich mit reinem Screenshot-Handoff
Ein Agent, der von einem PNG desselben Screens arbeitet, hat keine Komponentenidentität. Er sieht ein blaues abgerundetes Rechteck mit zentriertem Text und generiert:
Box(
modifier = Modifier
.background(Color(0xFF7F5CFE), RoundedCornerShape(24.dp))
.padding(horizontal = 32.dp, vertical = 16.dp)
) {
Text("Start", color = Color.White, fontWeight = FontWeight.SemiBold)
}
Ein Agent, der aus dem IR mit Inventar arbeitet, sieht componentId: "789:012", schlägt PrimaryButton nach, findet das vorhandene Composable in der Codebasis und generiert:
PrimaryButton(
label = stringResource(R.string.start),
onClick = { /* TODO */ }
)
Die zweite Ausgabe integriert sich in Ihr Design-System. Die erste erzeugt Divergenz. Das Inventar ist das, was die zweite Ausgabe möglich macht. Mehr dazu, warum Screenshots als Handoff-Artefakte scheitern, lesen Sie in Warum Screenshots scheitern.
Das Per-Screen-IR, das componentId-Referenzen enthält, wird ausführlich in Per-Screen IR — Stack, Overlay, Absolute, Leaf behandelt. Die vollständige Kontext-Bundle-Struktur, die beide Artefakte enthält, wird über Aufbau von CONTEXT.md eingeführt. Um Ihr eigenes Komponenteninventar zu erhalten, führen Sie figmascope auf Ihrer Figma-Datei aus.