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:

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 40 PrimaryButton(...)-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:

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.