La differenza tra un file di design e una libreria di componenti è l'identità. Un file di design ha forme. Una libreria di componenti ha parti denominate e riutilizzabili con identificatori stabili. components/inventory.json è la risposta di figmascope alla domanda: "quali parti di questo design sono pensate come componenti, e come si collegano le istanze alle loro definizioni?"

Lo schema

components/inventory.json è un array di oggetti:

[
  {
    "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"
  }
]

Ogni voce ha tre campi:

Questo è lo schema completo. È intenzionalmente minimale.

Come le istanze si collegano all'inventario

Il collegamento dalle istanze all'inventario si trova nell'IR per schermata. Qualsiasi nodo che è un'INSTANCE di un componente porta componentId e componentName:

// screens/home.json
{
  "kind": "stack",
  "id": "555:201",
  "componentId": "789:012",
  "componentName": "PrimaryButton",
  "axis": "horizontal",
  ...
}

Il componentId corrisponde a un id in inventory.json. Il componentName corrisponde al name. Entrambi i campi sono presenti in modo che l'agente non debba caricare inventory.json per ottenere il nome — ma se ha bisogno di sapere che questo componente fa parte di un COMPONENT_SET, può fare riferimento incrociato all'inventario.

Così un agente di codifica sa che il nodo pulsante sullo schermo non è un layout personalizzato da riprodurre in dettaglio — è un'istanza di PrimaryButton, e dovrebbe chiamare il composable PrimaryButton() esistente piuttosto che generarne uno nuovo dai dettagli strutturali dell'IR.

Senza l'identità del componente, un agente genera lo stesso pulsante da zero su ogni schermata. Con essa, l'agente chiama il composable esistente e salta completamente la generazione di codice strutturale. La differenza è se si ottengono 40 blocchi Row { Text(...) Surface { ... } } o 40 chiamate PrimaryButton(...).

Perché questo è importante per la sicurezza del refactoring

I design system vengono sottoposti a refactoring. Un pulsante ottiene una nuova forma, un nuovo padding, un colore diverso. Se tutto il codice generato era strutturalmente letterale, il refactoring significa modificare ogni schermata che ha un pulsante. Se il codice generato usava il riferimento al composable PrimaryButton, il refactoring è in un solo file.

L'inventario rende questo possibile stabilendo il contratto al momento della generazione: "questo nodo non è un layout personalizzato, è un'istanza di un componente noto." L'agente che rispetta questo contratto genera codice già strutturato per il refactoring a livello di componente.

Questo è il principale vantaggio strutturale rispetto agli handoff basati su screenshot. Uno screenshot di un pulsante è pixel. Non ha identità. Un agente che lavora da uno screenshot genererà sempre codice strutturale per il pulsante su ogni schermata. Un agente che lavora dall'IR con il collegamento all'inventario può riconoscere l'istanza e usare invece il riferimento al componente.

COMPONENT vs. COMPONENT_SET

Il sistema di componenti di Figma ha due livelli. Un COMPONENT è una singola definizione. Un COMPONENT_SET è un contenitore per le varianti — quello che Figma chiama "varianti" (ad es., un pulsante con stati Primary/Secondary/Destructive e Default/Hovered/Pressed).

In pratica, un'istanza in una schermata farà sempre riferimento a un COMPONENT (una variante specifica), non al COMPONENT_SET. Il COMPONENT_SET è presente in modo che l'agente conosca l'intera superficie delle varianti quando ha bisogno di implementare la macchina a stati del componente.

// Voci dell'inventario per un set Button
{ "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" }

// L'istanza nell'IR della schermata fa riferimento a una variante specifica
{ "componentId": "890:101", "componentName": "Button/Primary/Default" }

Un agente che genera codice Compose per questo sa: il componente è un Button con stile Primary e stato Default. Può dedurre che la firma della funzione probabilmente include parametri style: ButtonStyle e state: ButtonState, o come minimo usare Button/Primary/Default come riferimento semantico per un pulsante primario nel suo stato predefinito.

Il limite di 300 voci

figmascope limita inventory.json a 300 voci. I file Figma su larga scala — specialmente i design system con librerie di componenti esaustive — possono avere migliaia di componenti. Includerli tutti in un bundle di contesto pensato per essere inviato a un LLM riempirebbe la finestra di contesto con definizioni che l'agente non userà per le schermate da implementare.

Quando viene raggiunto il limite, un campo _truncated appare nell'inventario:

[
  { "id": "...", "name": "...", "type": "COMPONENT" },
  ...
  { "_truncated": true, "totalCount": 847, "included": 300 }
]

Il campo totalCount indica quanti componenti esistono nel file. Il campo included indica quanti sono stati inseriti nell'inventario. L'ordine è basato sul primo incontrato nell'albero dei nodi Figma, quindi i componenti referenziati all'inizio del documento (tipicamente le schermate principali) hanno maggiori probabilità di essere inclusi.

Se si lavora su schermate che usano componenti definiti tardi nel documento e non sono nell'inventario, i nodi IR per quelle istanze hanno comunque componentId e componentName — le informazioni sull'identità sono preservate anche quando il componente non è elencato nell'inventario. L'agente conosce il nome del componente dall'IR, anche senza la voce nell'inventario.

Cosa l'inventario non include

L'inventario è un elenco di identità, non una specifica di implementazione. Indica che esiste un componente chiamato PrimaryButton con ID 789:012. Non indica:

Queste lacune sono intenzionali nella v0.4. L'inferenza completa delle prop dei componenti dalla struttura IR è possibile ma produrrebbe risultati inaffidabili per componenti con logica variante complessa. L'inventario fornisce identità stabile. I dettagli di implementazione provengono dal tuo codice esistente, a cui l'agente ha anch'esso accesso.

Il flusso di lavoro corretto: l'agente vede un componentId: "789:012", lo cerca nell'inventario come PrimaryButton, poi cerca nel tuo codebase Kotlin PrimaryButton per capire la firma effettiva della funzione. L'inventario è il ponte tra il design e il codice, non un sostituto del codice. Puoi esportare un inventario da qualsiasi file Figma su figmascope.dev.

L'identità del componente nell'IR è ciò che separa "genera codice da questo design" da "genera codice che si integra in un codebase esistente." Il primo è un giocattolo. Il secondo è il lavoro vero.

Confronto con l'handoff solo screenshot

Un agente che lavora da un PNG della stessa schermata non ha identità del componente. Vede un rettangolo arrotondato blu con testo centrato e genera:

Box(
    modifier = Modifier
        .background(Color(0xFF7F5CFE), RoundedCornerShape(24.dp))
        .padding(horizontal = 32.dp, vertical = 16.dp)
) {
    Text("Start", color = Color.White, fontWeight = FontWeight.SemiBold)
}

Un agente che lavora dall'IR con inventario vede componentId: "789:012", cerca PrimaryButton, trova il composable esistente nel codebase e genera:

PrimaryButton(
    label = stringResource(R.string.start),
    onClick = { /* TODO */ }
)

Il secondo output si integra con il tuo design system. Il primo crea divergenza. L'inventario è ciò che rende possibile il secondo output. Per ulteriori informazioni su perché gli screenshot falliscono come artefatti di handoff, vedi Perché Gli Screenshot Falliscono.

L'IR per schermata che contiene i riferimenti componentId è trattato in dettaglio in IR Per Schermata — Stack, Overlay, Absolute, Leaf. La struttura completa del bundle di contesto che contiene entrambi gli artefatti è introdotta in Anatomia di CONTEXT.md. Per ottenere il tuo inventario dei componenti, esegui figmascope sul tuo file Figma.