Het verschil tussen een ontwerpbestand en een componentenbibliotheek is identiteit. Een ontwerpbestand bevat vormen. Een componentenbibliotheek heeft benoemde, herbruikbare onderdelen met stabiele identificatoren. components/inventory.json is het antwoord van figmascope op de vraag: "welke onderdelen in dit ontwerp zijn bedoeld als componenten, en hoe verbinden instanties terug naar hen?"
Het schema
components/inventory.json is een array van objecten:
[
{
"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"
}
]
Elk item heeft drie velden:
id: De Figma node-ID, stabiel over sessies heen voor hetzelfde bestand.name: De componentnaam uit Figma. Voor varianten binnen een COMPONENT_SET gebruikt Figma schuine-streep-notatie:Button/Primary/Default.type: Ofwel"COMPONENT"(een enkele componentdefinitie) of"COMPONENT_SET"(een groep varianten).
Dat is het volledige schema. Het is opzettelijk minimaal.
Hoe instanties terugkoppelen
De koppeling van instanties naar de inventaris zit in de per-scherm IR. Elke node die een INSTANCE is van een component draagt componentId en componentName:
// screens/home.json
{
"kind": "stack",
"id": "555:201",
"componentId": "789:012",
"componentName": "PrimaryButton",
"axis": "horizontal",
...
}
De componentId komt overeen met een id in inventory.json. De componentName komt overeen met de name. Beide velden zijn aanwezig zodat de agent inventory.json niet hoeft te laden om de naam te krijgen — maar als de agent wil weten of dit component deel uitmaakt van een COMPONENT_SET, raadpleegt het de inventaris.
Zo weet een coding agent dat de knopnode op het scherm geen op maat gemaakte layout is die in detail gereproduceerd moet worden — het is een instantie van PrimaryButton, en de agent moet de bestaande PrimaryButton()-composable aanroepen in plaats van een nieuwe te genereren op basis van de structurele details van de IR.
Zonder component-identiteit genereert een agent dezelfde knop vanaf nul op elk scherm. Met component-identiteit roept de agent de bestaande composable aan en slaat structurele codegeneratie volledig over. Het verschil is of je 40
Row { Text(...) Surface { ... } }-blokken krijgt of 40PrimaryButton(...)-aanroepen.
Waarom dit belangrijk is voor refactorveiligheid
Ontwerpsystemen worden gerefactord. Een knop krijgt een nieuwe vorm, nieuwe opvulling, een andere kleur. Als al je gegenereerde code structureel letterlijk was, betekent de refactor het aanpassen van elk scherm met een knop. Als de gegenereerde code de PrimaryButton-composablereferentie gebruikte, is de refactor één bestand.
De inventaris maakt dit mogelijk door het contract bij generatietijd vast te leggen: "deze node is geen aangepaste layout, het is een instantie van een bekend component." De agent die dit contract respecteert, genereert code die al gestructureerd is voor refactoring op componentniveau.
Dit is het primaire structurele voordeel ten opzichte van overdrachten op basis van schermafbeeldingen. Een schermafbeelding van een knop bestaat uit pixels. Het heeft geen identiteit. Een agent die werkt vanuit een schermafbeelding zal structurele code genereren voor de knop op elk scherm, altijd. Een agent die werkt vanuit de IR met inventariskoppeling kan de instantie herkennen en in plaats daarvan de componentreferentie gebruiken.
COMPONENT versus COMPONENT_SET
Het componentsysteem van Figma heeft twee niveaus. Een COMPONENT is een enkelvoudige definitie. Een COMPONENT_SET is een container voor varianten — wat Figma "variants" noemt (bijv. een knop met Primair/Secundair/Destructief en Standaard/Hover/Ingedrukt-staten).
In de praktijk zal een instantie op een scherm altijd verwijzen naar een COMPONENT (een specifieke variant), niet de COMPONENT_SET. De COMPONENT_SET is er zodat de agent het volledige variantoppervlak kent wanneer het de toestandsmachine van het component moet implementeren.
// Inventarisitems voor een 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" }
// Instantie in scherm-IR verwijst naar een specifieke variant
{ "componentId": "890:101", "componentName": "Button/Primary/Default" }
Een agent die Compose-code genereert voor dit voorbeeld weet: het component is een Button met een Primary-stijl en een Default-staat. Het kan afleiden dat de functiehandtekening waarschijnlijk style: ButtonStyle- en state: ButtonState-parameters bevat, of minimaal Button/Primary/Default gebruiken als semantische referentie voor een primaire knop in zijn standaardstaat.
De 300-itemslimiet
figmascope beperkt inventory.json tot 300 items. Figma-bestanden op schaal — met name ontwerpsystemen met uitgebreide componentenbibliotheeken — kunnen duizenden componenten bevatten. Het opnemen van al die componenten in een contextbundel die bedoeld is om naar een LLM te sturen, zou het contextvenster vullen met definities die de agent niet zal gebruiken voor de te implementeren schermen.
Wanneer de limiet bereikt is, verschijnt een _truncated-veld in de inventaris:
[
{ "id": "...", "name": "...", "type": "COMPONENT" },
...
{ "_truncated": true, "totalCount": 847, "included": 300 }
]
Het totalCount-veld toont hoeveel componenten er in het bestand zijn. Het included-veld toont hoeveel er in de inventaris zijn opgenomen. De volgorde is op volgorde van eerste ontmoeting in de Figma-nodeboom, dus componenten die vroeg in het document worden gerefereerd (doorgaans de primaire schermen) hebben meer kans om opgenomen te worden.
Als je werkt aan schermen die componenten gebruiken die laat in het document zijn gedefinieerd en die niet in de inventaris staan, bevatten de IR-nodes voor die instanties nog steeds componentId en componentName — de identiteitsinformatie blijft behouden, zelfs als het component niet in de inventaris staat. De agent kent de naam van het component uit de IR, ook zonder het inventarisitem.
Wat de inventaris niet bevat
De inventaris is een identiteitslijst, geen implementatiespecificatie. Het vertelt je dat een component genaamd PrimaryButton met ID 789:012 bestaat. Het vertelt je niet:
- Welke props het component accepteert
- Welke staten het heeft
- Hoe het component intern is gestructureerd (dat staat in de IR-nodes die INSTANCE zijn)
- Wat het bronbestand van het component is (als het uit een gekoppelde bibliotheek komt)
Deze hiaten zijn intentioneel in v0.4. Volledige component-prop-inferentie uit IR-structuur is mogelijk, maar zou onbetrouwbare resultaten opleveren voor componenten met complexe variantlogica. De inventaris biedt stabiele identiteit. Implementatiedetails komen uit je bestaande codebase, waar de agent ook toegang tot heeft.
De juiste werkwijze: de agent ziet een componentId: "789:012", zoekt het op in de inventaris als PrimaryButton, zoekt vervolgens in je Kotlin-codebase naar PrimaryButton om de werkelijke functiehandtekening te begrijpen. De inventaris is de brug tussen het ontwerp en de code, geen vervanging voor de code. Je kunt een inventaris exporteren van elk Figma-bestand op figmascope.dev.
Component-identiteit in de IR is wat "genereer code uit dit ontwerp" scheidt van "genereer code die past in een bestaande codebase." Het eerste is een speelgoed. Het tweede is het echte werk.
Vergelijking met alleen-schermafbeelding-overdracht
Een agent die werkt vanuit een PNG van hetzelfde scherm heeft geen component-identiteit. Het ziet een blauw afgerond rechthoek met gecentreerde tekst en genereert:
Box(
modifier = Modifier
.background(Color(0xFF7F5CFE), RoundedCornerShape(24.dp))
.padding(horizontal = 32.dp, vertical = 16.dp)
) {
Text("Start", color = Color.White, fontWeight = FontWeight.SemiBold)
}
Een agent die werkt vanuit de IR met inventaris ziet componentId: "789:012", zoekt PrimaryButton op, vindt de bestaande composable in de codebase, en genereert:
PrimaryButton(
label = stringResource(R.string.start),
onClick = { /* TODO */ }
)
De tweede uitvoer integreert met je ontwerpsysteem. De eerste creëert divergentie. De inventaris is wat de tweede uitvoer mogelijk maakt. Zie Waarom schermafbeeldingen falen voor meer informatie over waarom schermafbeeldingen falen als overdrachtsartefacten.
De per-scherm IR die componentId-referenties bevat, wordt in detail behandeld in Per-scherm IR — Stack, Overlay, Absolute, Leaf. De volledige contextbundelstructuur die beide artefacten bevat, wordt geïntroduceerd via Anatomie van CONTEXT.md. Voor je eigen componentinventaris, voer figmascope uit op je Figma-bestand.