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
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": [ ... ]
}
transportandfileKeyare optional (auto-detected;fileKeyrequired for official transport).fontsmust list every font family+style used by text styles in the design.nodesare 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):
| Alias | Expands to |
|---|---|
bg | background |
fg | foreground |
xs | xsmall |
sm | small |
md | medium |
lg | large |
xl | xlarge |
xxl | xxlarge |
2. Node Type Quick Reference
All nodes share these base properties: type, name, id?, children?, fillH?, fillV?, absolute?, visible?, opacity?.
| Type | Required | Key Properties | Maps To |
|---|---|---|---|
| FRAME | name | layout, gap, padding, fill, stroke, radius, clip, width, height, primaryAxisSizing, counterAxisSizing, primaryAxisAlign, counterAxisAlign, effectStyle, children | figma.createFrame() |
| TEXT | name, characters, textStyle | fill, autoResize, maxLines | figma.createText() |
| INSTANCE | name, component | variant, properties, swaps | importComponentByKeyAsync / importComponentSetByKeyAsync + createInstance() |
| CLONE | name, one of sourceNodeId / sourceRef | overrides[] (each: find.name, set.*) | node.clone() |
| RECTANGLE | name, width, height | fill, stroke, strokeWeight, strokeAlign, radius | figma.createRectangle() |
| ELLIPSE | name, width, height | fill, stroke, strokeWeight | figma.createEllipse() |
| REPEAT | name, count, template[] | data[] (per-iteration bindings, {{key}} in characters) | Expands to N copies (not a Figma node) |
| CONDITIONAL | name, when | children, 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": [ ... ]
}
paddingis shorthand for all four sides. UsepaddingTop,paddingRight,paddingBottom,paddingLeftfor asymmetric padding.radiusis shorthand for all corners. UseradiusTopLeft, etc. for individual corners.width/heightset initialresize()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
sourceRefto reference another node'sidfield (local clone). - Use
sourceNodeIdfor 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
- Read CSpec YAML (from spec phase) or generate from user description.
- Convert to scene graph JSON (
nodesarray with$tokenreferences). - Write JSON to a temp file.
- Run the compiler:
bridge-ds compile --input /tmp/scene.json --kb <kb-path> --transport console. - Execute each output chunk via
figma_execute(console) oruse_figma(official). - 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.
- Every spacing/padding/radius MUST be a
$tokenref (never raw px values). - Every color (fill, stroke) MUST be a
$tokenref (never hex values). - Every TEXT node MUST have a
textStyleref (never hardcode font properties). - DS components MUST be INSTANCE nodes (never recreate as FRAME/RECTANGLE).
- INSTANCE nodes CANNOT have children — use
propertiesandswapsfor overrides. - Node names become Figma layer names — make them descriptive and unique within their parent.
- Use REPEAT for lists and grids with repeated structure.
- Use CONDITIONAL sparingly — prefer resolving conditions before producing the scene graph.
- RECTANGLE/ELLIPSE are only for raw decorative elements with no DS component equivalent.
fillH/fillVshould not be used on children of frames withprimaryAxisSizing: "AUTO"(causes collapsed layout).
8. Error Handling
If the compiler returns errors:
- Read the error messages and suggestions from stderr.
- Fix the scene graph JSON based on the suggestions.
- Re-run the compiler.
Common Errors
| Error | Cause | Fix |
|---|---|---|
RESOLVE_TOKEN_NOT_FOUND | Token path doesn't match any registry entry | Check spelling, use aliases (md not medium), verify token exists in KB |
RESOLVE_COMPONENT_NOT_FOUND | Component name not in registry | Check registry for exact name (case-insensitive) |
RESOLVE_VARIANT_INVALID | Variant key or value not recognized | Check component's known variant properties |
VALIDATE_FILL_IN_AUTO_PARENT | fillH/fillV on child of AUTO-sized parent | Change parent to FIXED sizing or remove fill on child |
VALIDATE_RAW_SHAPE_HAS_DS_MATCH | RECTANGLE/ELLIPSE name matches a DS component | Use INSTANCE node instead |
VALIDATE_TEXT_NO_STYLE | TEXT node missing textStyle | Add a $text/... reference |
VALIDATE_INSTANCE_HAS_CHILDREN | INSTANCE node has children array | Remove children, use properties/swaps instead |
PARSE_RAW_VALUE_NOT_ALLOWED | Raw number in spacing/radius/color field | Replace with $token reference |