Skillnaden mellan en designfil och ett komponentbibliotek är identitet. En designfil har former. Ett komponentbibliotek har namngivna, återanvändbara delar med stabila identifierare. components/inventory.json är figmascopes svar på: "vilka delar i den här designen är avsedda att vara komponenter, och hur kopplas instanser tillbaka till dem?"
Schemat
components/inventory.json är en array av objekt:
[
{
"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"
}
]
Varje post har tre fält:
id: Figma-nod-ID:t, stabilt mellan sessioner för samma fil.name: Komponentnamnet från Figma. För varianter inom en COMPONENT_SET använder Figma snedstrecksnotation:Button/Primary/Default.type: Antingen"COMPONENT"(en enda komponentdefinition) eller"COMPONENT_SET"(en grupp varianter).
Det är det fullständiga schemat. Det är avsiktligt minimalt.
Hur instanser kopplar tillbaka
Länken från instanser till inventeringen finns i per-skärms-IR:n. Alla noder som är INSTANCE av en komponent bär componentId och componentName:
// screens/home.json
{
"kind": "stack",
"id": "555:201",
"componentId": "789:012",
"componentName": "PrimaryButton",
"axis": "horizontal",
...
}
componentId matchar ett id i inventory.json. componentName matchar name. Båda fälten finns så att agenten inte behöver ladda inventory.json för att få namnet — men om den behöver veta att den här komponenten är del av en COMPONENT_SET korsrefererar den inventeringen.
Det är så en kodningsagent vet att knappenoden på skärmen inte är en skräddarsydd layout som den ska reproducera i detalj — det är en instans av PrimaryButton, och den bör anropa den befintliga PrimaryButton()-composable snarare än att generera en ny från IR:ns strukturdetaljer.
Utan komponentidentitet genererar en agent samma knapp från grunden på varje skärm. Med den anropar agenten den befintliga composable och hoppar över strukturell kodgen helt. Skillnaden är om du får 40
Row { Text(...) Surface { ... } }-block eller 40PrimaryButton(...)-anrop.
Varför det är viktigt för refaktoreringssäkerhet
Designsystem refaktoreras. En knapp får ny form, ny padding, annan färg. Om all din genererade kod var strukturellt bokstavlig innebär refaktoreringen att röra varje skärm som har en knapp. Om den genererade koden använde PrimaryButton-composable-referensen är refaktoreringen en fil.
Inventeringen gör detta möjligt genom att upprätta kontraktet vid genereringstid: "den här noden är inte en anpassad layout, det är en instans av en känd komponent." Agenten som respekterar det här kontraktet genererar kod som redan är strukturerad för komponentnivårefaktorering.
Det här är den primära strukturella fördelen jämfört med skärmbildsbaserade överlämningar. En skärmbild av en knapp är pixlar. Den har ingen identitet. En agent som arbetar från en skärmbild genererar alltid strukturell kod för knappen på varje skärm. En agent som arbetar från IR:n med inventarielänkning kan känna igen instansen och använda komponentreferensen istället.
COMPONENT vs. COMPONENT_SET
Figmas komponentssystem har två nivåer. En COMPONENT är en enda definition. En COMPONENT_SET är en behållare för varianter — vad Figma kallar "varianter" (t.ex. en knapp med Primary/Secondary/Destructive och Default/Hovered/Pressed-tillstånd).
I praktiken refererar alltid en instans på en skärm en COMPONENT (en specifik variant), inte COMPONENT_SET. COMPONENT_SET finns så att agenten känner till hela variantytan när den behöver implementera komponentens tillståndsmaskin.
// Inventeringsposter för en Button-uppsättning
{ "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" }
// Instans i skärm-IR refererar en specifik variant
{ "componentId": "890:101", "componentName": "Button/Primary/Default" }
En agent som genererar Compose-kod för detta vet: komponenten är en Button med Primary-stil och Default-tillstånd. Den kan härleda att funktionssignaturen troligen involverar style: ButtonStyle och state: ButtonState-parametrar, eller åtminstone använda Button/Primary/Default som semantisk referens för en primärknapp i standardtillstånd.
300-postsgränsen
figmascope begränsar inventory.json till 300 poster. Figma-filer i stor skala — särskilt designsystem med uttömmande komponentbibliotek — kan ha tusentals komponenter. Att inkludera alla dem i ett kontextpaket avsett att skickas till en LLM skulle fylla kontextfönstret med definitioner agenten inte använder för skärmarna som implementeras.
När gränsen nås visas ett _truncated-fält i inventeringen:
[
{ "id": "...", "name": "...", "type": "COMPONENT" },
...
{ "_truncated": true, "totalCount": 847, "included": 300 }
]
totalCount berättar hur många komponenter som finns i filen. included berättar hur många som kom med i inventeringen. Ordningen är efter första förekomst i Figma-nodträdet, så komponenter som refereras tidigt i dokumentet (typiskt primärskärmarna) är mer sannolikt inkluderade.
Om du arbetar på skärmar som använder komponenter definierade sent i dokumentet och de inte finns i inventeringen, har IR-noderna för de instanserna fortfarande componentId och componentName — identitetsinformationen bevaras även om komponenten inte listas i inventeringen. Agenten känner till komponentens namn från IR:n, även utan inventeringsposten.
Vad inventeringen inte innehåller
Inventeringen är en identitetslista, inte en implementeringsspec. Den berättar att en komponent med namnet PrimaryButton med ID 789:012 finns. Den berättar inte:
- Vilka props komponenten accepterar
- Vilka tillstånd den har
- Hur komponenten är internt strukturerad (det finns i IR-noderna som är INSTANCE:er)
- Vilken källfil i Figma komponenten kommer från (om den är från ett länkat bibliotek)
Dessa luckor är avsiktliga i v0.4. Full komponentpropsinferens från IR-struktur är möjlig men skulle ge opålitliga resultat för komponenter med komplex variantlogik. Inventeringen ger stabil identitet. Implementeringsdetaljer kommer från din befintliga kodbas, som agenten också har åtkomst till.
Rätt arbetsflöde: agenten ser ett componentId: "789:012", slår upp det i inventeringen som PrimaryButton, söker sedan din Kotlin-kodbas efter PrimaryButton för att förstå den faktiska funktionssignaturen. Inventeringen är bryggan mellan designen och koden, inte en ersättning för koden. Du kan exportera en inventering från valfri Figma-fil på figmascope.dev.
Komponentidentitet i IR:n är det som skiljer "generera kod från den här designen" från "generera kod som passar in i en befintlig kodbas." Det förra är ett leksak. Det senare är jobbet.
Jämförelse med enbart skärmbildsöverlämning
En agent som arbetar från en PNG av samma skärm har ingen komponentidentitet. Den ser en blå avrundad rektangel med centrerad text och genererar:
Box(
modifier = Modifier
.background(Color(0xFF7F5CFE), RoundedCornerShape(24.dp))
.padding(horizontal = 32.dp, vertical = 16.dp)
) {
Text("Start", color = Color.White, fontWeight = FontWeight.SemiBold)
}
En agent som arbetar från IR:n med inventering ser componentId: "789:012", slår upp PrimaryButton, hittar den befintliga composable i kodbasen och genererar:
PrimaryButton(
label = stringResource(R.string.start),
onClick = { /* TODO */ }
)
Den andra utdatan integreras med ditt designsystem. Den första skapar avvikelse. Inventeringen är det som gör den andra utdatan möjlig. För mer om varför skärmbilder misslyckas som överlämningsartefakter, se Varför skärmbilder misslyckas.
Per-skärms-IR:n som innehåller componentId-referenser täcks i detalj i Per-skärms-IR — Stack, Overlay, Absolute, Leaf. Den fullständiga kontextpaketstrukturen som innehåller båda artefakterna introduceras via CONTEXT.md:s anatomi. För att få din egen komponentinventering, kör figmascope på din Figma-fil.