Compiler Reference

April 17, 2026 · View on GitHub

The only reference Claude reads at design-time. The compiler enforces all 26 Figma API rules. Claude's job: produce a valid scene graph JSON.


Compiler Iron Laws

Every `$token` reference resolves against the KB or compilation fails with `RESOLVE_TOKEN_NOT_FOUND` (Levenshtein-suggested alternatives included). Every emitted Figma Plugin API call respects all 26 enforced rules. Rule violations are compile errors, never warnings. Compiler output is deterministic for a given (input + KB) pair. No runtime randomness, no time-dependent codegen. Multi-chunk plans preserve nodeId references across chunks via `globalThis` bridging — no chunk may rely on intra-chunk DOM state.

1. Scene Graph JSON Format

Root Document

{
  "version": "3.0",
  "metadata": {
    "name": "Screen Name",
    "width": 1440,
    "height": 900,
    "description": "Optional description",
    "transport": "console",
    "fileKey": "abc123"
  },
  "fonts": [
    { "family": "Inter", "style": "Regular" },
    { "family": "Inter", "style": "Semi Bold" }
  ],
  "nodes": [ ... ]
}
  • transport and fileKey are optional (auto-detected; fileKey required for official transport).
  • fonts must list every font family+style used by text styles in the design.
  • nodes are the top-level children of the root frame.

Token Reference Format

All spacing, color, radius, text style, and effect values MUST be $token references — never raw px or hex.

$spacing/md              → variable: spacing/medium
$color/bg/neutral/default → variable: color/background/neutral/default
$radius/lg               → variable: radius/large
$text/heading/xl         → text style: heading/xl
$effect/shadow/sm        → effect style: shadow/small
$comp/Button             → component: Button
$icon/ArrowRight         → icon component: ArrowRight

Alias shortcuts (expanded automatically by the compiler):

AliasExpands to
bgbackground
fgforeground
xsxsmall
smsmall
mdmedium
lglarge
xlxlarge
xxlxxlarge

2. Node Type Quick Reference

All nodes share these base properties: type, name, id?, children?, fillH?, fillV?, absolute?, visible?, opacity?.

TypeRequiredKey PropertiesMaps To
FRAMEnamelayout, gap, padding, fill, stroke, radius, clip, width, height, primaryAxisSizing, counterAxisSizing, primaryAxisAlign, counterAxisAlign, effectStyle, childrenfigma.createFrame()
TEXTname, characters, textStylefill, autoResize, maxLinesfigma.createText()
INSTANCEname, componentvariant, properties, swapsimportComponentByKeyAsync / importComponentSetByKeyAsync + createInstance()
CLONEname, one of sourceNodeId / sourceRefoverrides[] (each: find.name, set.*)node.clone()
RECTANGLEname, width, heightfill, stroke, strokeWeight, strokeAlign, radiusfigma.createRectangle()
ELLIPSEname, width, heightfill, stroke, strokeWeightfigma.createEllipse()
REPEATname, count, template[]data[] (per-iteration bindings, {{key}} in characters)Expands to N copies (not a Figma node)
CONDITIONALname, whenchildren, else?Include/exclude (not a Figma node)

3. FRAME Properties Detail

{
  "type": "FRAME",
  "name": "Sidebar",
  "layout": "VERTICAL",
  "gap": "$spacing/md",
  "padding": "$spacing/lg",
  "fill": "$color/bg/neutral/default",
  "radius": "$radius/md",
  "clip": true,
  "fillH": true,
  "fillV": true,
  "width": 300,
  "height": 600,
  "primaryAxisSizing": "AUTO",
  "counterAxisSizing": "FIXED",
  "primaryAxisAlign": "MIN",
  "counterAxisAlign": "CENTER",
  "stroke": "$color/border/neutral/default",
  "strokeWeight": 1,
  "strokeAlign": "INSIDE",
  "children": [ ... ]
}
  • padding is shorthand for all four sides. Use paddingTop, paddingRight, paddingBottom, paddingLeft for asymmetric padding.
  • radius is shorthand for all corners. Use radiusTopLeft, etc. for individual corners.
  • width/height set initial resize() dimensions. Sizing modes (primaryAxisSizing, counterAxisSizing) control whether the frame grows.

4. Component Usage

INSTANCE Node

{
  "type": "INSTANCE",
  "name": "Primary Button",
  "component": "Button",
  "variant": { "size": "large", "variant": "primary" },
  "properties": { "label": "Submit", "hasTrailingIcon": true },
  "swaps": { "leadingIcon": "IconArrowRight" },
  "fillH": true
}
  • component: name from the DS registry (case-insensitive).
  • variant: object of variant property keys to values. The compiler validates against known variant options.
  • properties: text and boolean overrides. The compiler handles hash-suffix property key resolution.
  • swaps: instance swap overrides. Values are component names resolved to keys.
  • INSTANCE nodes CANNOT have children (compiler error).

CLONE Node

{
  "type": "CLONE",
  "name": "Sidebar Copy",
  "sourceRef": "sidebar",
  "overrides": [
    {
      "find": { "name": "Title", "type": "TEXT" },
      "set": { "characters": "New Title", "fill": "$color/text/accent/default" }
    }
  ]
}
  • Use sourceRef to reference another node's id field (local clone).
  • Use sourceNodeId for Figma node IDs (reference-based or unpublished components).

5. Compiler Invocation

bridge-ds compile --input <json-file> --kb <kb-path> --transport <console|official> [--dry-run]

(Equivalent: node dist/lib/compiler/cli.js ... after npm run build.)

Output: JSON array of { id, code, description } chunks to stdout. Errors: Structured errors to stderr with fuzzy suggestions for unresolved tokens/components.

Pipeline

Input JSON → PARSE → RESOLVE → VALIDATE → PLAN → CODEGEN → WRAP → Output chunks

The compiler handles: JSON validation, token resolution, structural validation (FILL in AUTO parent, raw shapes matching DS components, orphan clones), chunking for large designs, code generation with all 26 Figma API rules enforced, and transport-specific wrapping.


6. Claude's Workflow

  1. Read CSpec YAML (from spec phase) or generate from user description.
  2. Convert to scene graph JSON (nodes array with $token references).
  3. Write JSON to a temp file.
  4. Run the compiler: bridge-ds compile --input /tmp/scene.json --kb <kb-path> --transport console.
  5. Execute each output chunk via figma_execute (console) or use_figma (official).
  6. Screenshot after the final chunk to verify the result.

7. Key Rules

These are the rules Claude must follow when producing scene graph JSON. The compiler enforces them — but producing correct input avoids round-trips.

  1. Every spacing/padding/radius MUST be a $token ref (never raw px values).
  2. Every color (fill, stroke) MUST be a $token ref (never hex values).
  3. Every TEXT node MUST have a textStyle ref (never hardcode font properties).
  4. DS components MUST be INSTANCE nodes (never recreate as FRAME/RECTANGLE).
  5. INSTANCE nodes CANNOT have children — use properties and swaps for overrides.
  6. Node names become Figma layer names — make them descriptive and unique within their parent.
  7. Use REPEAT for lists and grids with repeated structure.
  8. Use CONDITIONAL sparingly — prefer resolving conditions before producing the scene graph.
  9. RECTANGLE/ELLIPSE are only for raw decorative elements with no DS component equivalent.
  10. fillH/fillV should not be used on children of frames with primaryAxisSizing: "AUTO" (causes collapsed layout).

8. Error Handling

If the compiler returns errors:

  1. Read the error messages and suggestions from stderr.
  2. Fix the scene graph JSON based on the suggestions.
  3. Re-run the compiler.

Common Errors

ErrorCauseFix
RESOLVE_TOKEN_NOT_FOUNDToken path doesn't match any registry entryCheck spelling, use aliases (md not medium), verify token exists in KB
RESOLVE_COMPONENT_NOT_FOUNDComponent name not in registryCheck registry for exact name (case-insensitive)
RESOLVE_VARIANT_INVALIDVariant key or value not recognizedCheck component's known variant properties
VALIDATE_FILL_IN_AUTO_PARENTfillH/fillV on child of AUTO-sized parentChange parent to FIXED sizing or remove fill on child
VALIDATE_RAW_SHAPE_HAS_DS_MATCHRECTANGLE/ELLIPSE name matches a DS componentUse INSTANCE node instead
VALIDATE_TEXT_NO_STYLETEXT node missing textStyleAdd a $text/... reference
VALIDATE_INSTANCE_HAS_CHILDRENINSTANCE node has children arrayRemove children, use properties/swaps instead
PARSE_RAW_VALUE_NOT_ALLOWEDRaw number in spacing/radius/color fieldReplace with $token reference