Documentation Index
Fetch the complete documentation index at: https://docs.uspec.design/llms.txt
Use this file to discover all available pages before exploring further.
V2.3 — May 2026
Typed componentProperties snapshot threaded end-to-end through the Figma plugin, SLOT-binding bug fix, and a renderer rewrite that drops the booleanOverrides projection in favor of the typed snapshot for the Referenced components table
uSpec V2.3
The Figma plugin now captures every placed instance’s full typedcomponentProperties surface (booleans, instance-swaps, text overrides, variant choices) and threads that snapshot end-to-end through the extraction pipeline so the create-component-md renderer’s “Referenced components” override table reads typed values directly instead of guessing from a value-only booleanOverrides projection. The same release fixes a long-standing SLOT-binding bug where the plugin was matching SLOT nodes via the wrong componentPropertyReferences key and silently dropping default-child instances from the classification UI.Typed componentProperties snapshot (Figma plugin 2.4.0)
- Phase E captures
componentPropertieson every walked INSTANCE via the newsnapshotComponentPropertieshelper infigma-plugin/src/safe.ts. The snapshot mirrors Figma’sInstanceNode.componentPropertiesAPI exactly — every entry carries{ type, value }withtypetyped toBOOLEAN | INSTANCE_SWAP | TEXT | VARIANT | SLOT— and strips Figma’s#…clean-key suffix from each property name - Phase F′ (
childComposition.ts) forwards the snapshot into every_childComposition.children[*]entry, and the plugin UI round-trips it back into the sandbox so theextractmerge can attach it to slot-origin entries that bypass the first-guess builder.nullfor non-INSTANCE entries (FRAMEs, vectors, layout wrappers) and for slot-preferred entries (which describe a referenced component, not a placed instance — readpropertyDefinitions.slots[].preferredInstances[]for those defaults) booleanOverridesis now legacy. The field is still emitted on every entry — it’s used by the first-guess fingerprinting that groups identical sub-component placements — but it’s now a booleans-only projection over the typed snapshot instead of an independent read. Slot-default-child entries that previously carried an emptybooleanOverridesnow carry the projected booleans correctly- The new field is documented in
figma-plugin/docs/base-json-schema.mdand the plugin’s post-change checklist
SLOT-binding bug fix (Figma plugin 2.4.0)
- SLOT nodes are now matched to their declared slot property via the new
getSlotPropNamehelper, which prefers the authoritativecomponentPropertyReferences.mainComponentbinding (per Figma’s SlotNode docs) and falls back to the SLOT node’s ownnamewhen that binding is absent — the common case in real files, where SLOTs typically only carry thevisiblebinding to a separate BOOLEAN prop - This replaces a buggy
Object.values(cpRefs)[0]lookup inphaseA.tsandcode.tsthat was picking up thevisiblebinding (e.g., “show leading slot”) instead of the slot binding (e.g., “leading slot”), causing every later lookup-by-slot-prop-name to miss and silently dropping default-child instances from the classification UI - The plugin now also logs a soft
console.warnwhen a declared slot property has no matching SLOT node in the default variant — surfaces designer-side renames or genuinely empty slots so the gap is visible
Renderer rewrite for Referenced components (uspec-skills 0.2.11)
references/component-md/agent-component-md-instruction.mdintroduces three small helpers shared by the Composition bullet rules and the API “Referenced components”####block:displayName(child)prefersparentSetNameover the variant-identifiermainComponentName. When a referenced child is a variant of a COMPONENT_SET, Figma’smainComponentNameis the variant identifier ("layout=icon-only, size=small, color=default") — useful as a configuration but useless as a component name.parentSetNameis the human-readable set name ("action button")slug(child)derives the spec filename fromdisplayName(child)instead of the raw main-component name, so multi-variant references resolve to the right./{slug}.mdslotSuffix(child)appends" (via slot **{slotName}**)"when a referenced child lives inside a SLOT, so the engineer can locate it in the parent’s anatomy without cross-referencing the API’s slot table
- The “Referenced components” override table now reads
child.componentPropertiesexclusively. One row per entry in the typed dict, with per-typevalue formatting:BOOLEAN→true/falseINSTANCE_SWAP→(instance \`)`TEXT→ the literal string in backticksVARIANT→ the bare option, with"Variant axis on the placed instance."in the Notes column
- The legacy
booleanOverridesfield remains on every entry for backward compatibility with the first-guess fingerprinting, but is no longer the source of truth for the rendered table.subCompVariantAxesis also explicitly demoted from the table — it lists what axes the child exposes, not what the parent’s placement chose, and belongs in the referenced child’s own spec - Slot context is folded into the lead paragraph as a participle clause (“…as the default fill of the slot”) so it shows up exactly where the engineer needs it
- Decorative-children rollup is now scoped to top-level entries only — slot-origin entries never appear at the top level and are not part of that count
Documentation
implementation.mdnow documents the two newsafe.tsexports (snapshotComponentProperties,getSlotPropName), the SLOT-binding bug fix that motivated the latter, and the Phase F′ → renderer flow for the typedcomponentPropertiessnapshotfigma-plugin/docs/base-json-schema.mddocuments the newcomponentPropertiesfield on_childComposition.children[], demotesbooleanOverridesto a backward-compat projection, and adds the field to the post-change checklist
npx uspec-skills update to pick up the renderer change. To get the new Figma plugin behavior, rebuild figma-plugin/ locally (cd figma-plugin && npm install && npm run build) and re-import the manifest in Figma Desktop. The plugin doesn’t ship via npm — it’s built per-machine.V2.2 — May 2026
Render-meta JSON appendix for component-md, layer-identity stamping in extract-structure, borderWidth/borderAlign row pair, and Figma plugin 2.3.0 with node-id stamping and boolean-gated layer fallback
uSpec V2.2
Component Markdown specs now ship with a machine-readable render-meta appendix, structure extraction stamps Figma layer identity on every section and group header, and border rows are emitted as aborderWidth + borderAlign pair. The release ships a new Figma plugin (uspec-extract 2.3.0) that stamps Figma node ids on every walk entry, captures strokeAlign, and resolves boolean-gated layers even when they’re absent from the default variant. Two follow-up fixes to the structure skill (revert to unified flow, gate borderWidth on a painted stroke, forbid node-id / TODO stubs in Notes) ship in the same release.Render-meta appendix in Component Markdown
- The
component-mdtemplate gains a fenced JSON block delimited by<!-- render-meta:start v=1 -->/<!-- render-meta:end -->carrying machine-readable component metadata:schemaVersion,extractedAt,sourceHash,fileKey,nodeId,component,variantAxes/variantAxesDefaults,propertyDefs,booleanDefs,subComponents,slotContents,sectionTargets,groupTargets - Downstream
create-*skills (structure, color, anatomy, property, …) read this block to resolve sections, row-groups, and boolean-gated layers back to live Figma layers — no more fuzzy name matching againstlayoutTreeand no need to re-extract through MCP schemaVersionis pinned at"1.0"for V2.2; future breaking changes will bump it.sourceHashis a SHA-256 of the underlying_base.jsonso consumers can detect drift between the.mdand the extraction it was rendered from- The block is mechanical pass-through of
_base.jsonand the structure cache — no interpretation, no synthesis. Twocreate-component-mdruns against the same_base.jsonproduce byte-identical render-meta
Layer identity stamped on structure output
extract-structure’s new R6 rule populatessection._anchor({ layerName, layerId }) on every section androw._layerName/row._layerIdon every group-header row, reading directly from_base.json.variants[<default>].layoutTree- Composition sections anchor to the variant root with
layerName: "__root__"; sub-component sections anchor to the in-context INSTANCE node (NOT the canonicalsubCompSetId, which is already covered by render-metasubComponents[]); slot-content sections anchor to the slot’s host frame; zone-specific sections anchor to the named FRAME - Group-header rows (any row where
isSubProperty !== trueANDspecis a zone descriptor, not a property family) carry the literal Figma layer name and node id. Layers present only inrevealedByVariantName[*](e.g., aclear buttonparked understate=active) emit_layerId: nullwith an explanatorynotesentry — the row is still present, just unpinned - The
create-component-mdorchestrator now reads these fields directly into render-meta. A legacy fallback (name-walk againstlayoutTree) covers caches produced before this release; re-runningextract-structureis recommended to regenerate the cache with the new fields
borderWidth + borderAlign row pair
- Whenever a
borderWidthrow is queued (gate:strokePaintToken != null), a siblingborderAlignrow is queued fromdimensions.strokeAlign.display(inside/outside/center). The two rows share the same gate — emit both, or neither - The coverage matrix (
_extractionArtifacts.coverageMatrix) acceptsborderAlignas a first-class family alongsideborderWidth, with identical R4/R5 detection rules - Legacy fallback: when
dimensions.strokeAlignis absent from a_base.jsonproduced by a pre-2.3.0 plugin build,borderAlignemits as"—"withprovenance: "not-measured"andgeneralNotessurfaces a single line recommending re-extraction. No row is silently dropped
Figma plugin 2.3.0 (uspec-extract)
- Boolean-gated layer fallback (Phase A). Boolean property → gated layer resolution now walks
componentPropertyReferences.visibleinstead of relying on the default variant’scomponentPropertieskeys. When the gated layer is absent from the default variant (e.g., a “clear” button that only appears when input is active), the resolver falls back to scanning every sibling variant in the COMPONENT_SET. First match wins; the resultingassociatedLayerIdis canonical and downstream-consumable strokeAligncapture (Phase E).extractDims()now emitsstrokeAlignas{ value, token: null, display }wherevalueis the raw Figma enum ("INSIDE"/"OUTSIDE"/"CENTER") anddisplayis the lower-cased prose form. Present onvariants[].dimensions,variants[].treeHierarchical[*].dimensions, and everysubComponentVariantWalksentry. Not onvariants[].revealedTree[*].dimensions— Phase G uses a minimaldim()extractor focused on topology; dimensional ground truth always comes from the baselinetreeHierarchical- Node ids on every walk entry.
treeHierarchical,layoutTree,treeFlat,colorWalk,revealedTree,revealedColorWalk, and Phase I’smeasureHierarchicalall carry the Figma nodeid(ornodeIdfor color entries) of the source layer. Downstream consumers resolve walk entries back to live layers without name- or path-based search - Rebuild locally to pick up the changes:
cd figma-plugin && npm install && npm run build, then re-import the manifest in Figma Desktop. The plugin doesn’t ship via npm — it’s built per-machine
borderWidth gate fix and authoring discipline
borderWidthrows now requirestrokeWeight.value > 0. The extractor emitsstrokeWeight: { value: 0 }for nodes that have the property set but no paint innode.strokes; without this gate the agent emitted a phantomborderWidth: 0row even though no border is painted on the component- The structure rendering rules now forbid Figma node ids and
TODO: confirm with Figmastubs inNotescolumns. Notes is engineer-facing implementation context — when a value cannot be confirmed, skip the row or surface the gap ingeneralNotesrather than leak extraction-time artifacts into the rendered spec - The Mode A / Mode B split, per-group annotation resolver, and cross-variant 4d/4e drivers added on top of V2.1.4’s
7d2e7f4baseline are reverted — they made the workflow brittle without improving output.create-structureis back on the unifiedrootOnly/fullTreeannotation model with cleaner output
Housekeeping
maintaining.mdupdated for npm’s current web-based 2FA flow —npm publishnow opens a browser tab for approval and no longer requires--otp=…. The authenticator-app fallback is documented for accounts not on web-based 2FA- New root-level
.npmrcmirrorspackages/cli/.npmrcand pins the registry to public npm at the repo level. The layered registry safety (publish config +.npmrc+ prepublish guard) still aborts mis-pointed publishes with a clear error utils/README.mdremoved (utils/is no longer a meaningful directory in the repo)README.mdandimplementation.mdprose tightened — the canvas-measurements paragraph now documents therootOnlyvsfullTreeannotation policy explicitly and the new{ success, plannedColumns }return semantics
npx uspec-skills update to pick up the skill changes. To get the new Figma plugin behaviour, rebuild figma-plugin/ locally and re-import the manifest in Figma Desktop. No action needed on existing Figma libraries.V2.1.4 — May 2026
create-structure accepts an authoritative .md input, ships an explicit reasoning-discipline contract, gates borderWidth on strokePaintToken, and adds use_figma string-escaping guidance
uSpec V2.1.4
Thecreate-structure skill now accepts an authoritative components/<name>.md (produced by create-component-md) as its highest-precedence input. When provided, the .md is the source of truth for every property it documents — borderWidth, padding, cornerRadius, sizing modes, slot dimensions, sub-component identity, bound token names. Figma extraction is demoted to node-ID resolution and drift detection. Alongside this, the structure instruction file gains an explicit reasoning-discipline contract, borderWidth rows now require evidence of a painted stroke, the architecture doc captures a use_figma script-escaping rule, and the Figma plugin manifest carries its registration id..md-authoritative mode (Structure)
skills/create-structure/SKILL.mdadds Step 0 — Detect Input Mode. Mode A is description-only (today’s behavior). Mode B readscomponents/<name>.mdin full and persists it asMD_SPECbefore any extraction runs- Step 4 (visual context, enhanced extraction, cross-variant comparison, non-dimensional axis diff) still runs in Mode B, but its output is demoted to a node-ID resolver and drift detector. Extraction values that disagree with the
.mdare logged ingeneralNotesand the.mdvalue wins - Step 6 in Mode B is reduced to (1) mapping each
.mdrow to extraction nodes for annotation rendering, (2) reconciling each.mdrow against the corresponding extraction value, (3) skipping the cross-section pattern recognition pass (create-component-mdalready did it) - Every emitted row now carries a required
provenancefield:"md"(value came from the.md),"measured"(.mdwas silent, value came from extraction),"user-rule"(value came from a user adjustment rule), or"inferred"(with an accompanying note explaining what was inferred from what). Rows without a defensible provenance are not emitted - When both a description and an authoritative
.mdare provided, the.mdwins for properties it documents and the description applies only to anything the.mdis silent on
Reasoning discipline (Structure)
references/structure/agent-structure-instruction.mdadds a Reasoning Discipline section that applies at every step — extraction interpretation through rendering. Five rules: (1) the.mdis the source of truth when provided, (2) every row needs provenance, (3) no confabulation — skip rows or surface gaps ingeneralNotesrather than fill in defaults, (4) screenshots verify layout intent only, not paints/strokes/spacings/radii/tokens, (5)strokeWeightalone is not evidence of a border- The Conflicts table grows a new top row covering authoritative
.mdprecedence, and the existing “Figma contradicts description” row is qualified to “no.mdprovided” - The Common Mistakes section adds matching entries: hand-rolling canvas measurements, hand-curating the annotation plan, treating
strokeWeightas evidence of a border, citing screenshots for paint or border decisions - The Do NOT list adds: overriding an authoritative
.mdvalue with anything inferred from extraction or screenshots, emittingborderWidthwhenstrokePaintToken == null, citing a screenshot as evidence for paints/strokes/spacing/radii/tokens, inventing values to fill rows
strokeWeight no longer implies a border (Structure)
- The Stroke weight reading reference in
references/structure/agent-structure-instruction.mdis rewritten around a newstrokePaintTokensignal co-emitted by the extractor. A frame can carrystrokeWeight: 1withstrokes: []— no border is painted, and a phantomborderWidthrow should never be emitted from such a node - New emission rule: emit a
borderWidthrow only whenstrokePaintToken != null. The Inspect Reference table’s Stroke width row is updated to match - The collapsed dimensional schema description in
## Dimensional Dataclarifies thatstrokeWeightis only authoritative as evidence of a border when paired with a non-nullstrokePaintToken
use_figma / figma_execute script escaping (architecture)
implementation.mdadds a new “Authoringcodestrings foruse_figma/figma_execute” subsection under Figma MCP Tools. Both providers serialize thecodeargument through JSON before the Figma sandbox runs it, so\'inside a'...'JS string is a recurring source ofSyntaxErrorafter re-escape- Rule: when authoring note text, descriptions, or any content with apostrophes (clear-button copy like
"Visible when value isn't empty", contracted English in design-intent notes), wrap the JS string in"..."(double quotes) or use template literals (backticks). Never reach for\'inside a'...'string. This applies to every skill that ships note-bearing rows through__ROWS_JSON__or its equivalents
Figma plugin manifest id
figma-plugin/manifest.jsonnow declares its registrationid: "1635184425006534227". This is the plugin’s permanent identity in the Figma plugin registry — it does not change anything about how the plugin runs locally or what_base.jsonit produces, but it stabilises the manifest for future plugin distribution work
Scope
- No changes to extraction shape, table contents, sub-component walks, slot handling, or canvas measurement overlay behavior beyond the
borderWidth-gating rule above - Already-rendered Figma structure specs are unaffected — the new mode and the new emission rule only change future
create-structureruns
npx uspec-skills update to pick up the new skill content. No action needed on Figma libraries.0.2.8 — May 2026
CLI build script wipes templates/ before each build so deleted files no longer ship as zombies
uspec-skills 0.2.8
Thepackages/cli/scripts/build.mjs build now wipes templates/ before re-syncing it from the source skills/ and references/ trees. Previously the build only overlaid via cpSync, so any file ever copied stayed forever — files deleted from the source persisted in templates/, shipped in the npm tarball, and were resurrected into consumer references/ directories on every npx uspec-skills update.What you might notice after updating
- Running
npx uspec-skills updatemay delete stale files in your localreferences/directory that were never part of the current source tree (e.g., files likereferences/_shared/mcp-adapter.mdorreferences/structure/scripts/*.jsthat were removed from the source long ago but kept resurrecting). This is the cleanup catching up - No skill or spec behavior changes. This is a packaging hygiene fix only
npx uspec-skills update to pick up the change.V2.1.3 — May 2026
create-structure extraction no longer crashes on TEXT children when reading auto-layout properties
uSpec V2.1.3
Thecreate-structure skill’s variant-walk and cross-variant comparison scripts now tolerate non-container children (TEXT, VECTOR, GROUP, …) when reading auto-layout properties such as itemSpacing, counterAxisSpacing, and the padding* family. Previously, the first TEXT child encountered during the walk threw a synchronous TypeError and aborted the entire extraction — leaving the spec unrenderable.Why the walk could throw (Structure)
- Step 4b
extractDimensionsand Step 4dmeasureNoderecurse into every child viaextractChildren/measureChildren. Children include heterogeneous node types — TEXT, VECTOR, GROUP — that do not support auto-layout properties - The Figma plugin API throws synchronously when you read
itemSpacing(or other layout-only properties) on a node that doesn’t support them. The previous guardnode[p] !== undefined && node[p] !== figma.mixedran the access first, so the throw fired before the comparison - Step 4e already used the correct defensive pattern (per-access
try/catchplus anisContainer = 'layoutMode' in nodegate); Steps 4b and 4d now match it
Defensive read pattern (Structure)
- Every property read in Steps 4b and 4d is now wrapped in
try { ... } catch {}, mirroring thesg(node, prop)accessor infigma-plugin/src/safe.ts - Layout-only property groups (padding,
itemSpacing,counterAxisSpacing,layoutMode, primary/counter axis aligns,layoutSizing*,clipsContent) are gated onisContainer = 'layoutMode' in nodeso leaf nodes skip them entirely instead of throwing - The collapsed dimensional schema (
padding,cornerRadius,strokeWeight,typography) is unchanged — Steps 5, 6, and 11 read the same shape they always did
Documentation (uspec-skills 0.2.7)
skills/create-structure/SKILL.mdadds a maintainer note above the Step 4b script explaining the throw-on-leaf hazard and thetry/catch+isContainerpattern, so future script edits stay safe by default
Scope
- No changes to extraction shape, plan-building, table contents, sub-component walks, or canvas measurement overlays
- Already-rendered Figma structure specs are unaffected — this fix unblocks future runs on components whose default variant has TEXT children at the root or inside auto-layout containers
npx uspec-skills update to pick up the fix. No action needed on Figma libraries.V2.1.2 — May 2026
create-structure padding measurement overlays now match autolayout values on cross-axis-centered children
uSpec V2.1.2
Thecreate-structure skill now picks the right anchor child when drawing native Figma measurement overlays for hardcoded padding rows, so canvas labels match the autolayout values documented in the table — even when other children are HUG-sized and centered along the cross axis. This corrects a divergence introduced when the measurement overlays were restored in V2.1 (uspec-skills 0.2.5).Why the labels could disagree with the table (Structure)
- Hardcoded padding rows draw a measurement line whose pixel length is what Figma renders as the label. Until V2.1.2 the line always anchored to the first or last visible child, so on a horizontal capsule with
counterAxisAlignItems: CENTERand HUG-sized children the line measured the centering offset rather than the autolayout padding - Token-bound padding rows were unaffected —
freeTextcarries the token name regardless of geometry — and gap /itemSpacingrows were unaffected because consecutive children sit edge-to-edge with the gap by definition. Only hardcoded counter-axis padding rows misread
Padding anchor rule (Structure)
- The Step 11c annotation script now picks the child whose edge sits on the container’s inner-content edge for that side (within a 0.5-px epsilon of
paddingTop/paddingBottom/paddingLeft/paddingRight) and draws the line against that child. Figma’s default numeric label then matches the autolayout value the table documents - When no child aligns to that edge, the line falls back to the first/last visible child but carries a
freeTextoverride of the autolayout value so the label still matches the table - Implemented inline as a new
findEdgeAnchorhelper aboveannotate; no per-row configuration is required
Documentation (uspec-skills 0.2.6)
references/structure/agent-structure-instruction.mdsplits thefreeTextpolicy bullet into “hardcoded padding row” (anchor + fallback) vs “hardcoded gap/itemSpacing row” (default label) so the contract the agent reads matches what the SKILL implementsimplementation.mdupdates the “Canvas measurements (Structure)” architecture summary to describe the anchor +freeText-fallback policy
Scope
- No changes to extraction, plan-building, table contents, or the markdown spec
- Already-rendered Figma structure specs keep their old labels until they are explicitly re-annotated; the fix changes only future runs and any explicit re-annotation pass
npx uspec-skills update to pick up the fix. No action needed on Figma libraries.0.2.5 — May 2026
Native Figma measurement overlays restored in create-structure with high-fidelity preview rendering
uspec-skills 0.2.5
Thecreate-structure skill restores native Figma measurement overlays on its preview instances and renders previews with full slot content and recursive boolean state. This closes the loop on the temporary pause from V1.6.0 — the Figma MCP use_figma tool now supports page.addMeasurement(...), so measurement lines appear directly on the canvas alongside table-driven token rows. No edits to create-component-md; this is a rendering-layer patch.Native canvas measurements (Structure)
- Step 11c emits
page.addMeasurement(...)for the allow-listed auto-layout properties documented in the section table:paddingTop/paddingRight/paddingBottom/paddingLeft,itemSpacing,minWidth/maxWidth, andminHeight/maxHeight. Other properties (corner radius, typography, color) remain table-only by design - Token-bound rows pass the token name as
freeTextso the measurement label reads as the token, not just the resolved pixel value. Hardcoded rows render Figma’s default numeric label. Min/max constraints render with a"min N"/"max N"prefix - Per-instance idempotency is provided by
getMeasurementsForNode(...)+deleteMeasurement(...)before each annotation pass, so re-running a section never duplicates overlays - Both
figma-console(figma_execute) andfigma-mcp(use_figma) execute the identical script — no MCP-specific branching
Preview fidelity (Structure)
- Slot content previews now nest the preferred component instance into the actual
SLOTnode inside the preview, so the slot region renders with real content instead of an empty placeholder. IfappendChildfails (for example in a read-only context), the preview falls back to a 0.6-opacity ghost overlay positioned at the slot bbox - Recursive boolean enabling reaches every nested instance in the preview except inside boolean-toggled sections, so optional children documented in the table actually appear in the rendered preview
- Step 12 verification adds a
measurementCount/plannedColumnscontract check on the value returned by Step 11c. Measurement overlays are a canvas layer that does not appear infigma_take_screenshot/get_screenshotoutput, so visual screenshot review is no longer the source of truth for measurement coverage
Documentation
references/structure/agent-structure-instruction.mdadds a Canvas Measurements subsection covering the allow-list,freeTextsemantics, annotation scope, and the screenshot caveatimplementation.mddocuments the render-time slot nesting and canvas measurement architecture parallel to the existing marker positioning notes
npx uspec-skills update to pick up the change. No action needed on Figma libraries.uSpec V2.1.1
Transient interactive state names now use the past-participle form (hovered, pressed, focused) so they read in parallel with persistent ones (enabled, disabled). Previously the recommendation mixed hover with the participle forms, which read inconsistently in property tables, color spec column headers, and prompt examples. This is a non-breaking change: existing Figma libraries that name their state-axis options hover continue to be recognized.Recommendation update
references/api/api-library.mdnow recommendshoveredalongsidepressedandfocused. The recommendation table also explicitly documents that earlier docs and many existing Figma libraries usehover, and that both forms are recognized by the extractor.- All instruction files (
agent-api,agent-color,agent-structure,agent-anatomy) and skill prose updated to useHovered/hoveredin state listings, JSON examples, and worked examples. - Mintlify spec pages, Getting started examples, and Troubleshooting prompt suggestions updated to match.
Backwards compatibility (figma-plugin 2.1.1)
- The
stateKeywordsmatcher infigma-plugin/src/phaseF.tsandskills/create-color/SKILL.mdaccepts bothhoverandhoveredas state-axis option names, so designers who keep the legacy name continue to get correct axis classification. - Real design-token identifiers (
hoverOverlayAlpha,interactivePrimaryHover, etc.) are unchanged — these are platform variable names, not state labels. - Generated specs continue to render whichever form the source Figma file uses; output is truthful pass-through, not a silent rewrite.
npx uspec-skills update to pick up the recommendation. No action needed on Figma libraries unless you want to rename your state-axis options to match.uSpec V2.1
The uSpec Extract Figma plugin now handles layout-wrapper FRAMEs and repeated sub-component placements correctly, so the classification checklist surfaces the real sub-components and arrays of identical instances are documented as one entry with a count instead of N duplicates. A coordinateduspec-skills patch keeps create-component-md from misreading the new entry shapes.Layout-wrapper descent (Figma plugin 2.1.0)
- Designers commonly wrap a component’s real sub-components in a single auto-layout FRAME for clipping, scroll, padding, or grouping (for example, a Button group’s
groupwrapper for theoverflow=scrollvariant). The plugin now descends through these wrappers so the classification UI surfaces the actual sub-components instead of the wrapper - Each wrapper is recorded as an explicit decorative entry in
_childComposition.children[]withtopLevelInstanceId: "wrapper:<depth>"andclassificationEvidence: ["layout-wrapper"], so layout chrome remains visible to downstream consumers idx:NintopLevelInstanceIdnow indexes into the effective container (post wrapper descent), not the variant root. Phase I andtreeHierarchicalare unaffected
Sub-component placement dedup (Figma plugin 2.1.0)
- Repeated placements of the same sub-component (for example, six Selection Button instances inside a Button group) now collapse to one
_childCompositionentry instead of N. The designer classifies once; multiplicity is recorded in three new fields:placementCount— number of sibling placements that share the entry’s identityplacementIndices— original positions in the effective container’s childrenplacementsVary—truewhen at least two placements differ in main component or boolean overrides, signalling a heterogeneous array
- The plugin UI surfaces a
× Nbadge on grouped rows and avaries in statetag whenplacementsVaryis true, so the designer can spot heterogeneous arrays at a glance - Equivalence fingerprint covers
mainComponentName(which encodes variant choice for component-set members) andbooleanOverrides— instance-swap and text-override differences are intentionally not in the fingerprint and remain visible intreeHierarchical
create-component-md Step 4.5 fix (uspec-skills 0.2.3)
- The post-extract review previously flagged any
_childCompositionentry withoutuser-selectedevidence as malformed. The new wrapper FRAME entries legitimately carry["layout-wrapper"]evidence, so the check is now scoped tonodeType === "INSTANCE"— the only entries the plugin UI asks the designer to confirm - Prevents a spurious “the plugin UI did not reach the designer’s confirmation step” warning and a redundant override pass on every plugin run that contains a layout wrapper
- Run
npx uspec-skills updateto pick up the fix
uspec-skills 0.2.2
Fixed the first run experience so the skip option works as intended. Runnpx uspec-skills update to pick up the fix.V2.0 — April 2026
New create-component-md skill, uSpec Extract Figma plugin, and uspec-skills install CLI
uSpec V2.0
A major milestone release. uSpec now supports two rendering paths: the original Figma-native annotations, and a new Component Markdown path that produces a single self-contained.md specification you can hand to any LLM. The release ships with a new Figma plugin that captures every variant, token binding, and sub-component deterministically inside Figma’s sandbox, and a new uspec-skills CLI that replaces the clone-and-copy install flow.New: uspec-skills install CLI (0.2.0)
- Run
npx uspec-skills initfrom any project root. The CLI prompts for your agent host (Cursor, Claude Code, or Codex) and your Figma MCP provider, installs every skill into the matching platform directory (.cursor/skills/,.claude/skills/, or.agents/skills/), copies references into./references/, and writesuspecs.config.json npx uspec-skills install --platform <cursor|claude-code|codex>reinstalls or repairs skills non-interactivelynpx uspec-skills updatere-renders skills against the current package versionnpx uspec-skills doctorvalidates your install and reports missing skills, missing references, or broken cross-referencesinitbootstraps a fresh uSpec project into the current directory when no project root marker (.git/,package.json, oruspecs.config.json) is found above it, so the documented “create a new folder, then run init” walkthrough works from an empty directory. A one-line note (bootstrapping a new uSpec project here.) is printed when this happensuspec-skills installpoints you atnpx uspec-skills initwhen run from a directory with no project root, instead of failing with a generic message- All CLI error and log prefixes consistently say
uspec-skills(the legacyuspecshorthand has been removed) - The previous flow (cloning the repo and running
utils/sync-skills.sh) is no longer required. Existing users can keep their clone, but new setups should usenpx uspec-skills initfrom their own project root uspecs.config.jsonnow records the chosen platform and MCP provider sofirstrunreads them from disk instead of asking again
New skill: create-component-md
- Orchestrator skill that turns a plugin-produced
_base.jsoninto a singlecomponents/{componentSlug}.mdfile - Runs four interpretation specialists:
extract-api(serial, produces the shared property dictionary), thenextract-structure,extract-color, andextract-voicein a parallel batch - Deterministic reconciliation gate catches typed disagreements between specialists (conflicting child classifications, mismatched axes, missing states) and serially re-dispatches only the specialist that owns the mismatch
- Integrity gate validates cache-file shapes, axis consistency, and structure coverage matrix before rendering the Markdown
- Output sections: Overview, API, Structure, Color, Voice / Screen reader, Provenance. Everything needed to implement the component from scratch without opening Figma
- Cost envelope: 50k–200k tokens per run. Recommended model: Opus 4.7 High or above
- Full guide →
uSpec Extract Figma plugin
- New Figma plugin that captures a component’s complete extractable state in one pass
- Walks every variant (no default-variant sampling), resolves library-linked variables with name,
codeSyntax, alias chains, and remote collection metadata, and captures inline font properties alongside text style IDs - Phase I: sub-component variant walks. Constitutive sub-components are measured across their own variant axes, not only the configuration the parent embeds, so a Button inside a Text Field is specified at every size and density
- Designer-in-the-loop classification checklist: confirm or flip whether each top-level child is constitutive, referenced, or decorative before extraction
- Runs entirely inside the Figma plugin sandbox with no network access. Nothing is stored, nothing leaves your machine. To build locally, clone the uSpec repo, run
npm install && npm run buildinsidefigma-plugin/, then import the manifest in Figma Desktop. See the install walkthrough - Output is a validated
_base.json(Ajv schema atfigma-plugin/docs/base-json-schema.md) that becomes the sole input forcreate-component-md
Documentation
- New Component Markdown spec page covering install, usage, the four-specialist pipeline, and skill-side troubleshooting
- New Figma Extract plugin tab on the Troubleshooting page covering build steps, Node version requirements, the watch-mode dev loop, and common install failure modes
- Getting Started rewritten around the CLI flow with platform-specific tabs
- Troubleshooting updated with
npx uspec-skills doctorand per-platform repair commands
Structure skill: coverage matrix artifact
extract-structurenow emits a_extractionArtifacts.coverageMatrixartifact listing every auto-layout frame walked, the non-zero layout properties found on it, and whether a corresponding row was emitted in the final spec- The orchestrator’s integrity step asserts
coverageMatrix.complete === trueand independently recounts frames walked, so silently dropped padding or spacing is caught before rendering - Fixes a class of bugs where inner wrapper frames with non-zero
horizontalPaddingoritemSpacingcould be measured but not emitted
Dual-path architecture
implementation.mdfully rewritten to describe both rendering paths, the plugin phases (A–I), the orchestrator workflow, the.uspec-cache/layout, and theextract-*interpretation skillsuspecs.config.jsongainsextractionSource: "plugin"andreconciliation: { autoRetry: true }to control the new path.uspec-cache/{componentSlug}/directory stages the plugin payload and caches each specialist’s JSON output. Useful for debugging and for re-running only part of the pipeline
V1.8.1 — April 2026
Recursive nested container measurement and wrapper frame padding coverage in structure specs
uSpec V1.8.1
The structure skill now recursively measures nested auto-layout containers and enforces per-wrapper padding documentation — no more collapsed padding notes on parent groups.Recursive nested container measurement (Structure)
measureChildrennow calls itself recursively instead of using a flat loop for grandchildren — deeply nested wrapper frames (e.g., icon containers insidetrailingContent) are fully measured and surfaced as__childrenentries in the cross-variant data- Fixes cases where intermediate auto-layout frames with their own padding were invisible to the completeness check
Wrapper frame padding coverage (Structure)
- New verification procedure in the completeness judgment: for each sub-component section, walk
__childrenentries recursively — every entry with non-zero padding is an auto-layout container that needs its own group with dedicated rows - Catches content areas (e.g.,
leadingContent,trailingContent) whose children each have individual padding that was previously collapsed into a single note on the parent - Cross-checks against
enrichedTreewhen available for redundant validation
Common mistake guidance (Structure)
- New “Collapsing wrapper frame padding into notes” entry in the instruction file — documents the anti-pattern of merging per-child padding into a parent group header note instead of giving each wrapper its own group
V1.8.0 — April 2026
Composite color specs, context-aware property exhibits, non-dimensional axis coverage, and sub-pixel precision
uSpec V1.8.0
The color skill now specs composite paint styles — gradients, multi-layer fills, and blended overlays — with nested hierarchy rows breaking down each layer. The property skill gains a new exhibit planning system with context axis rendering, sparse matrix chapters, and a dedicated instruction file. Structure now diffs every variant axis for structural or property-level changes, and measurements preserve sub-pixel precision.Composite style support (Color)
- New
buildCompositeDetailfunction in the extraction script detects paint styles with 2+ visible fill layers and emits acompositeDetailobject with layer stacking order, blend modes, opacities, and gradient stops - Token resolution priority updated: paint/stroke style names (
fillStyleId,strokeStyleId) now take precedence over variable bindings (boundVariables.color), matching how effect styles are already handled - AI interpretation builds
compositeChildrenarrays on elements — solid layers, gradient layers with per-stop detail, and image layers — rendered as nested rows with hierarchy indicators (#hierarchy-indicatorframe toggled per child row) - Both Strategy A (simple) and Strategy B (state-consolidated) rendering scripts support composite child rows with
showIndicatorfor middle/last-child visual connectors - Instruction file adds composite breakdown guidance, worked examples, rendering rules, and validation checklist items
Exhibit planning and context axis rendering (Property)
- New Step 1 reads a dedicated instruction file (
agent-property-instruction.md) containing data validation, exhibit planning, pre-render checklist, common mistakes, and do-not rules — previously inline in SKILL.md - Step 4e now includes exhibit planning (Phase B) that produces an
exhibitPlanarray routing each property to the correct rendering template - New context axis system: when a variant axis qualifies as a visual context (e.g.,
variant: primary/subtle), all other illustrated chapters render grouped rows per context value using new6a-ctxand6b-ctxtemplates - New 6a-matrix template for sparse variant matrices — absolute-positioned grid with N/A placeholders for missing combinations, plus standalone chapters for both axes
- Step renumbering (1–11) with a new Step 5 audit pass that re-reads the instruction file’s pre-render checklist before rendering
- All implementation notes moved from the SKILL.md Notes section to the instruction file, reducing SKILL.md scope to pure orchestration
Non-dimensional axis coverage (Structure)
- New Step 4e runs a diff script measuring root and direct children across every variant axis not already covered by size/density/shape extraction
- Step 6 classifies each axis as structural (children differ → separate sections per configuration), property-variant (dimensional properties differ → state-conditional section), or visual-only (skip)
- New Step 6b runs targeted follow-up extractions for structural axes, giving each configuration complete dimensional data across all sizes
- Instruction file adds non-dimensional variant axis guidance, decision table entries, and common mistake warnings for skipped diffs and missing property-variant sections
- User-provided value adjustments now replace extracted values in existing rows with explanatory notes instead of creating duplicate rows
Sub-pixel precision (Structure)
- All rounding functions updated from
Math.round()to arv()helper that preserves one decimal place (Math.round(v * 10) / 10) — values like 1.5px stay 1.5 instead of rounding to 2 - Applied across both Step 4b enhanced extraction and Step 4d cross-variant comparison scripts
- Instruction file updated: “Preserve one decimal place; whole numbers stay whole”
Anatomy refinements
- Root variant fills/effects now fold into the container note when a container synthetic already exists, instead of always creating a separate statelayer/backplate element
- Ghost overlays for failed slot insertions deferred to after auto-layout reflow so they use final positioning
instAbsX/instAbsYrecomputed after centering to fix absolute transform drift
Element naming (Color)
- Fill-bearing elements now consistently use a property qualifier: “Container fill” instead of “Container”, “Background fill” instead of “Background” — removes ambiguity when the same element also has a stroke
V1.7.4 — April 2026
Evidence-based API reasoning with ownership hints, override promotion, and compound component guidance
uSpec V1.7.4
The API skill now separates deterministic evidence from AI reasoning with a structured evidence model, ownership hints, and an explicit override promotion pass. The instruction file adds compound component ownership rules, nested property grouping heuristics, and a worked Text Field example demonstrating state decomposition and child override promotion.Evidence-based API reasoning
- New
ownershipHintsarray in the extraction script collects deterministic ownership cues from root properties, child overrides, text nodes, and variable collections — each hint includesevidenceType,suggestedExposure, and arationale - New Step 4c requires assembling a structured
ComponentEvidenceobject before reasoning about the API — keeping raw facts separate from semantic interpretation relevantVariableCollectionsare now extracted inline during property extraction, with component-name and generic-property matching to discover mode-controlled capabilities like density and shape- The instruction file introduces a
ComponentEvidenceTypeScript interface as the required intermediate model between extraction and API generation
Override promotion pass
- Step 5 now includes a mandatory override promotion pass: every
composableChildrenoverride key is classified as parent-owned, child-only, or shared - Master boolean + sub-boolean combinations are merged into single enums (e.g.,
leadingContent: none, icon, text, iconAndText) instead of being exposed as separate boolean properties - New validation checklist items verify that parent-owned properties are not buried in sub-component tables and that broad state axes are decomposed
Compound component guidance
- New “Critical Rules” quick-reference section at the top of the instruction file highlights the five most commonly violated rules
- New ownership rules table for compound components with tie-breaker heuristics (parent vs child vs both)
- New “Choosing Top-Level vs Nested Rows” section with heuristics for
isSubPropertyusage - New “Do NOT” section replaces the former “Common Property Categories” with explicit anti-patterns
- New worked example: Text Field with state axis decomposition, promoted child overrides, and sub-component tables
API library updates
- Added compound component ownership guidance with decision table and examples
- Added nested property grouping patterns (
trailingContentType→ nestedlabel,variant) - Added
showCharacterCountto the Text field canonical API - Added
validationStateenum guidance for components with multiple validation-like states
V1.7.3 — April 2026
Screen reader specs now handle preferred slot fills in focus-order planning and artwork previews
uSpec V1.7.3
This update extends the voice and screen reader workflow so slot-hosted controls can be documented from the right scenario. The skill now distinguishes default slot children from preferred interactive fills, carries that decision into preview rendering, and validates that the rendered artwork matches the documented focus order.Preferred slot fills for screen reader specs
create-voicenow resolves SLOTpreferredValuesto local components during extraction and records both preferred instances and default slot children- Focus-order planning can choose between the default slot content and a representative preferred interactive fill when a slot-hosted control changes the traversal order
- Slot metadata now includes visibility bindings, descriptions, raw keys, and contextual child overrides so the agent can reason about conditional focus stops more accurately
Slot-aware artwork rendering
- Screen reader previews now support
slotInsertions, allowing the render step to populate slot content before marker resolution and bbox capture - The focus-order fallback logic reapplies slot insertions while searching for the richest preview state, improving marker placement for slot-hosted actions
- States with zero focus stops still render the component preview, while slot-populated states can now show the correct interactive control instead of a default placeholder scenario
Clearer guidance and validation
- The screen reader instruction file now frames focus order as a single top-level section and removes anatomy-specific language from the task definition
- Validation guidance is split into pre-render and post-render checks, including explicit checks for slot-hosted focus stops and slot-populated previews
implementation.mdnow documents the voice skill’s preferred-slot extraction and insertion flow alongside the existing SLOT support across other skills
V1.7.2 — April 2026
Figma slot support refined with ownership-aware structure planning and hosting-context slot sections
uSpec V1.7.2
This update sharpens the structure skill’s Figma slot support. Section planning now resolves ownership before rendering, so parent-owned roles stay on the sub-component path while true preferred slot content gets slot-specific documentation. Slot content sections also stay focused on hosting context and placement-specific deltas instead of duplicating another component’s full structure spec.Ownership-aware structure planning
- Section planning now treats
subComponents,slotContents,enrichedTree, andlayoutTreeas discovery inputs instead of final section types - New ownership resolution classifies each candidate onto exactly one path:
subComponent,slotContent, or composition/root-only - Parent-owned structural roles remain sub-components even when they are placed through a slot or slot-like composition
- Generic library-owned preferred content stays on the
slotContentpath, and overlapping candidates are deduplicated before any sections are emitted
Clearer slot content boundaries
- Slot content sections now render only for preferred instances that still classify as
slotContentafter ownership resolution slotContextis the primary source for hosting-container properties such as sizing mode, padding, and alignment- The preferred component’s measured
selfvalues are used only for placement-specific deltas caused by slot context, not as a second full structure spec - Section descriptions now explicitly defer component internals to the referenced component spec
Stronger validation and authoring guidance
- Validation checks now confirm that every instance still classified as a sub-component is covered after ownership resolution
- Slot-related validation also checks that each surfaced instance is documented on exactly one section path
- Structure guidance adds clearer examples for container-only rows in slot sections and for single-path ownership decisions
V1.7.1 — April 2026
Slot-aware previews, sub-component token ownership, composition Pattern B, and slot mutation safety
uSpec V1.7.1
API configuration examples now render live slot content and text overrides in previews. Color applies a token ownership framework to sub-component entries. Structure gains Pattern B composition sections for standalone components, boolean-toggled previews, and section ID-based rendering. All slot-traversing scripts use a crash-safe recursive collector.Slot-aware API configuration previews
- Configuration examples now support
textOverrides— a map of Figma TEXT node layer names to replacement text, applied to the main instance so previews show the example’s actual text instead of default placeholders - New
slotInsertionsparameter populates named SLOT nodes with fresh component instances: specify the slot name, a component node ID, and optionalnestedOverrides/textOverrideson the inserted child - All overrides are applied before
appendChildinto the slot — after adoption, child nodes get compound IDs and become inaccessible (see slot mutation ordering constraint below) - Extraction returns
textNodeMap— an array of{ name, characters, parentName }for every TEXT node in the default variant — eliminating guesswork fortextOverrideskeys
Sub-component token ownership (Color)
- New token ownership decision framework in the color instruction file — evaluate each
subComponentNameentry against four signals (full component vs leaf instance, slot-hosted, parent override) before including or excluding - Leaf instances (icon fills, divider strokes) stay in the parent spec; full sub-components (buttons, badges, checkboxes) are excluded and noted in
generalNotes - Worked examples table covers common cases (MicroButton → exclude, Chevron icon → include, Divider → include, IconButton → exclude)
- Slot-based component guidance: document default slot content tokens, note slot architecture and preferred instances in
generalNotes, explain extraction behavior with nested booleans
Composition Pattern B (Structure)
- New Pattern B — Structural map for standalone components or components without a size axis (e.g., Section Heading with leading slot + heading area + trailing slot)
- Uses
Spec | Default | Notescolumns with group rows for the host container and each structural zone — replaces the need for a separate “container” section - Boundary rule: when any section says “See X spec”, only document the hosting container (sizing mode, padding, spacing, alignment) — never re-document the component’s own internals
- Slot container properties (sizing mode, alignment, clipsContent) belong as group rows in the composition section, not repeated in each slotContent section
- HUG-sized container guidance: document
widthMode: huginstead of reporting measured pixel dimensions, which are artifacts of current content
Boolean-toggled previews (Structure)
- New preview type for standalone components with booleans controlling structural elements (slots, accessories, subtext)
- Shows meaningful boolean combinations as labeled instances (e.g., Default, With subtext, Full)
PROPERTY_OVERRIDESarray drives per-column boolean configurations in the preview script
Section ID-based rendering (Structure)
- Step 11b now returns the rendered section’s node ID (
sectionId) - Step 11c preview script locates the section by ID instead of by name — eliminates name-collision issues when multiple sections share similar names
- Page context is loaded explicitly via
figma.setCurrentPageAsyncfor stable child traversal
Slot-safe tree traversal
loadAllFontsacross API, color, and structure skills now uses a manual recursive collector with per-node try-catch instead offindAll— prevents crashes on SLOT nodes with compound IDs- Color extraction adds
figma.setCurrentPageAsyncbefore traversal for stable child resolution enableNestedBooleansanddirectUnhidein the color skill wrapped with try-catch guards for slot-hosted instancesimplementation.mddocuments the slot mutation ordering constraint: all mutations on a child instance must happen beforeappendChildinto a SLOT, with code examples for both correct and incorrect patterns, plus the default-slot-child replacement workaround
Response truncation guidance (Structure)
- Added guidance for handling MCP response truncation (>~20KB): run targeted follow-up extraction for missing fields instead of re-running the full script
V1.7.0 — April 2026
Figma slot detection, nearest-edge marker placement, component-relative spec placement, and improved rendering
uSpec V1.7.0
All seven skills now detect and handle native Figma SLOT nodes — preferred instances, boolean visibility bindings, and slot content population. Marker placement uses a new nearest-edge algorithm with collision avoidance, specs are placed next to the source component, and rendering is more resilient with dynamic font loading and font-family fallbacks.Figma SLOT node support
- Anatomy extraction detects SLOT-type properties, resolves
preferredValuesto local component nodes, readscomponentPropertyReferences.visiblefor boolean bindings, and surfacesslotDefaultChildrenfor default content. Step 4 enriches slot notes with preferred component names, marks hidden/empty slots for artwork population, and sets section eligibility for sub-component anatomy sections. - API extraction collects
slotPropswith preferred instances anddefaultChildrenincluding contextual overrides. Sub-component table defaults now reflect values the designer set in the slot context, not the standalone component’s global defaults. Descriptions reference the source component. - Property extraction detects boolean-to-slot linkage — when a boolean controls a SLOT’s visibility, the description reads “Controls slot: (accepts: )” instead of the generic “Controls layer”.
- Structure resolves SLOT properties with
preferredValuesand generates dedicatedslotContentsections per preferred component, measuring contextual dimensions when each preferred component is placed inside the slot across all parent sizes. - Voice deep-recurses into SLOT nodes during extraction so interactive elements inside slots appear as separate focus stop entries for merge analysis. Reads
slotVisibilityfor conditional focus stop detection across states.
Nearest-edge marker placement with collision avoidance
- Replaces the previous clockwise / left-stagger / alternating strategy system with a unified nearest-edge algorithm across anatomy, per-child, and voice skills
- For each element, all four sides are scored by distance to the component boundary — the marker is placed on the shortest side
- Before placing, overlap with already-placed markers is checked (8 px minimum gap); on collision, perpendicular offsets are applied, falling back to the next-best side if bounds are exceeded
- Inline markers for nested elements — elements visually contained inside another annotated element get a short stub line (16 px) on their nearest edge instead of a perimeter marker
Component-relative spec placement
- Specs are now placed on the same page as the source component, positioned to its right with a 200 px gap — no more viewport-center placement
- The script resolves the component node, walks up to its PAGE ancestor, activates the page, and positions the frame at
compNode.x + compNode.width + 200 - Cross-file destination URLs retain the existing viewport-center behavior
Completion link
- Every skill now prints a clickable Figma deep-link URL to the rendered spec frame at the end of the run
- URL format:
https://www.figma.com/design/{fileKey}/?node-id={frameId}
Improved example rendering
- Dynamic font loading (
loadAllFonts) runs after every mutation that may reveal new text nodes —createInstance,setProperties,appendChildinto slots, anddirectUnhide— preventing “unloaded font” errors on components using non-template fonts - Font-family fallback (
loadFontWithFallback) discovers exact font style strings vialistAvailableFontsAsyncinstead of hardcoding style names, with graceful fallback through preferred → fallback → first-available → Inter - Template font loading moved from hardcoded family to discovery from existing marker and section text nodes
- API configuration example preview now finds SLOT nodes via
findOne(n => n.type === 'SLOT')instead of assumingchildren[0]
Variant selection evaluation (Anatomy)
- New Step 4 sub-step 0 evaluates whether the default variant is the best representative — when it yields only 1–2 elements and variant axis option names suggest a structurally richer alternative, the extraction re-runs with
PREFERRED_VARIANT_PROPS - Does not re-extract for purely stylistic differences (color, size, theme)
Brief description header
- Anatomy and property specs now compose a 1-sentence
briefDescription(max ~15 words) describing what the component IS and does, placed in the#brief-component-descriptionheader field - Replaces the previous generic “Anatomy breakdown of…” and “Configurable properties of…” text
Root container detection (Anatomy)
- New
childContainerIsVariantflag indicates when the extraction traversed past the root container — a synthetic container element is always inserted when traversal occurred - When the root container was not traversed, the agent evaluates architectural significance (composable slots, conditional visibility, mixed layout) to decide whether annotation is warranted
hasStrokeson the root variant no longer triggers a separate synthetic element — strokes are described in the container note instead
Voice rendering improvements
- Removed
artworkLabelsand the detach-and-replace-text workflow — artwork instances stay live throughout rendering findStopNodenow uses ancestor-aware visibility matching (isEffectivelyVisible) for the Focus Order entry, correctly triggering the richest-variant fallback when boolean-enable alone cannot surface all focus stops- Preview wrapper width reads from
previewPlaceholder.widthto match the template layout instead of computing independently - Conditional focus stops and disabled/non-focusable states documented in merge analysis guidance
V1.6.2 — April 2026
FRAME-wrapped text detection, frame icon indicators, and effect style consolidation
uSpec V1.6.2
Anatomy now detects FRAME-wrapped TEXT nodes and displays a dedicated frame icon indicator, while color consolidates effect style entries into a single token reference.FRAME-wrapped TEXT detection (Anatomy)
- Frames containing a single TEXT child are now classified as
textinstead ofcontainer— the frame name is preserved inoriginalNameand the element carriesnodeType: 'TEXT' - Short text content (up to 30 characters) is included in the element notes for richer context in the attribute table
- Applies to both extraction and the
name/originalNamedocumentation in the instruction file
Frame icon indicator (Anatomy)
- New
#frameindicator icon for FRAME and GROUP node types, added alongside the existing#instance,#text, and#sloticons - Applied to both composition-level and per-child artwork rendering scripts — FRAME/GROUP elements now display their own icon instead of falling through to the default (no icon) case
Name field semantics (Anatomy)
namenow consistently returns the designer-facing layer name across all classifications- For
instance-unwrappedelements,nameis the wrapper frame’s name (e.g., “Thumb”) — the inner component name is available viawrappedInstance.componentSetName - Previously, unwrapped instances overwrote
namewith the inner component’scomponentSetName, losing the original frame label
Effect style consolidation (Color)
- When a node has an
effectStyleId, extraction now emits a single"effect style"entry with the style name as the token, instead of iterating individual shadow layers - Individual
drop shadow/inner shadowentries are still emitted when no effect style is applied - The
variantColorDatacontract documents the new"effect style"property value and its semantics
Effect and elevation token category (Color)
- Added
Effect/Elevationrow to the token-naming reference table with common style names (low,medium,high) - Added
Effectsrow to the element-naming reference table with common layer names (Shadow,Elevation,Drop shadow)
uSpec V1.6.1
Anatomy and voice reader artwork rendering are now more robust — both skills use a dedicated wrapper frame for absolute positioning and voice gains dynamic preview sizing with smarter marker placement.Wrapper frame for artwork (Anatomy)
- Artwork elements (component instance, outlines, markers, lines) are now placed inside a dedicated inner wrapper frame instead of directly on the preview placeholder
- The wrapper uses
layoutMode = 'NONE'with transparent fills andclipsContent = true, keeping absolute positioning isolated from the template’s auto-layout - Applied to both composition-level and per-child artwork scripts
Dynamic preview sizing (Voice)
- Preview dimensions are now calculated from the live instance’s
width/heightplus marker margins, replacing the staleROOT_SIZEparameter - Eliminates centering drift when variant switching changes the component’s rendered size
- Sizing formula accounts for the number of focus stops so left-stagger markers never run out of room
- Removed the
ROOT_SIZEplaceholder from the rendering template and instruction file
Marker positioning strategies (Voice)
- Voice artwork now uses the same three-strategy marker placement as anatomy: clockwise, left stagger, and alternating
- Strategy is auto-detected by clustering focus stop centers — consistent with anatomy’s approach
- Replaces the previous simple alternating-only placement, producing cleaner annotations for concentric and vertically stacked components
Pre-detach bounding box capture (Voice)
- Bounding boxes for focus stops are now captured from the live instance before any
detachInstance()call - Avoids fragility of post-detach name matching where SLOT nodes reorganize and
findStopNodemay fail
V1.6.0 — April 2026
Synthetic layer detection, clockwise markers, measurement annotation pause, and two-layer architecture
uSpec V1.6.0
Anatomy now handles concentric components (checkbox, radio, toggle) with synthetic element detection and clockwise marker placement. Structure gains icon/component reference rows and temporarily removes measurement annotations until Figma MCP supports them natively. All seven skills follow a two-layer architecture separating orchestration from domain knowledge.Measurement annotation paused (Structure)
- Temporarily removed measurement annotations (
TOKEN_MAPS,annotateNode, and all native FigmaaddMeasurementcalls) from the structure skill - The
addMeasurementAPI is not yet exposed through Figma MCP — annotations will return once native support is available - Table-driven spec rows and token references are unaffected; only the visual measurement lines on preview instances are paused
Synthetic element detection (Anatomy)
- New
hasVisuals()utility detects fills, strokes, and effects on any node — used to identify visually meaningful frames that wrapper traversal would otherwise skip rootVariantVisualsandtraversedFramesare now returned by the extraction script, surfacing visual layers (statelayers, backplates, shape containers) that exist on the root variant or intermediate wrapper frames- Step 4 inserts synthetic elements (
isSynthetic: true) for skipped visual layers, with re-indexing — concentric components like checkbox now show all structural layers in the anatomy table - Instruction file adds note-writing guidelines, worked examples, and validation checklist items for synthetic elements
Clockwise marker placement (Anatomy)
- Three marker placement strategies based on element center clustering: clockwise (concentric/overlapping), left stagger (vertical stack), and alternating (mixed layouts)
- Clockwise strategy rotates markers around the component (left → top → right → bottom) — ideal for concentric components where all elements share the same center
- Both composition and per-child artwork scripts use the same
isClustereddetection and strategy selection
Richest variant fallback (Anatomy)
- When the default variant produces 0 elements after wrapper traversal (e.g., an unchecked checkbox with an empty structure frame), extraction falls back to the variant with the most descendant children
selectedVariantIdis returned by extraction and reused by the rendering step, ensuring artwork matches the extraction dataresolveChildContainerrefactored into a reusable function shared by the fallback logic
Icon and component references (Structure)
- INSTANCE children now carry
parentSetName— the component set name (e.g.,"checkmark","chevron-down") — at all tree depths, not just depth 0 - New
iconName/leadingIcon/trailingIconspec rows document which component is used, placed before the corresponding size row - Instruction file adds a Component References section, decision-table entry, common-mistake warning, and validation checklist item
Two-layer skill architecture
- SKILL.md is now strictly the orchestration layer — step-by-step workflow, MCP adapter mapping, Plugin API scripts, script output contracts, intermediate data structures, and template mechanics
- Instruction files are now strictly the domain knowledge layer — interpretation guidance, decision frameworks, naming conventions, value formatting rules, worked examples, edge cases, and validation checklists
- Every skill retains its two-tier extraction model: deterministic scripts for data gathering, AI reasoning for interpretation and enrichment
Housekeeping
- Deleted
data-example.json— no longer referenced by any skill - Updated
api/api-library.mdwith improved reference patterns - Updated
implementation.mdwith variant selection and marker positioning docs
uSpec V1.5.0
All seven skills now handle composable slot components (button groups, tab bars, chip groups) — with new SLOT node traversal, composition-level deduplication, blown-out child rendering, and realistic artwork labels.Composable slot support across skills
- New
slotclassification type in the anatomy extraction script — SLOT nodes are detected, traversed, and annotated with a dedicated#slotindicator in the table - Slot traversal added to all three wrapper-walking paths (extraction, composition artwork, per-child artwork) so components using Figma’s composable slot pattern are handled consistently
- Voice/screen reader extraction recurses into slot containers with identically-named children, assigning
slotIndexfor index-based matching across focus stop resolution
Composition-level deduplication
- Multiple instances of the same sub-component (e.g., 4 buttons in a button group) are collapsed into a single representative element with an
(xN)suffix at the composition level - Prevents redundant markers, outlines, and table rows — one entry per unique sub-component, with a note explaining the repeated pattern
- Per-child sections are also deduplicated by
mainComponentSetIdso only one anatomy section is created per unique sub-component
Blown-out child rendering (property skill)
- New rendering mode creates instances directly from a child’s component set instead of modifying nested instances in a parent — immune to sparse variant matrices and nested-instance property access issues
- Automatic fallback: when
setProperties()fails on a nested instance, the chapter is re-rendered in blown-out mode - Sparse variant matrix detection added to AI validation — identifies missing axis combinations and adds
constrainedBymetadata for correct base variant selection - Coupled axis detection improved with heuristics for semantically coupled axes where option names differ
Artwork label replacement (voice skill)
- Artwork previews now replace generic “Label” placeholder text with realistic, state-specific labels (e.g., “Day”, “Week”, “Month”, “Year”)
- Labels are passed per-state via
artworkLabelsand applied by detaching the instance and its nested sub-instances before modifying text nodes - Focus stop outlines (pink dashed rectangles) added to voice artwork for visual consistency with the anatomy skill
Color token resolution improvements
- Token resolution now prefers
codeSyntax.WEBover raw variable names, producing cleaner developer-ready token references - Paint style fallback added for fills, strokes, and effects — when no variable binding exists but a Figma paint style is applied, the style name is used as the token
- Container/slot component detection: when the parent has no direct color entries, extraction re-targets to the sub-component automatically
- Mode token maps updated to use web code syntax
API child overrides for slot components
- Configuration examples now support
childOverrides— per-child property overrides applied to composable slot children by index - Item-level properties (e.g.,
item 1 isSelected) can be documented in example tables to reflect the preview state
Figma MCP compatibility (property skill)
- Added method restriction table and replacement helpers (
findByName,findAllText, font-loading viatn.fontName) forfigma-mcpwherefindAll,findOne, andgetRangeAllFontNamesthrowTypeError - Page-loading block updated to use explicit page name lookup instead of parent traversal
User-provided design context
- Anatomy and property skills now integrate user-provided notes (behavioral descriptions, usage constraints, coupling hints) into semantic notes and validation logic
- Voice skill documents behavioral states from user context (e.g., single-select vs. multi-select) as separate entries when they produce different semantic properties
Robustness
- Font loading wrapped in try/catch across all rendering scripts to prevent crashes on mixed-font or empty text nodes
- Instance-wrapper terminology standardized from “slot-wrapper” to “instance-wrapper” across all skills and instruction files
uSpec V1.4.1
Documentation now covers both Figma MCP providers — Figma Console MCP (Southleft) and native Figma MCP (Figma) — across the entire docs site.Dual MCP documentation
- All references to “Figma Console MCP” replaced with MCP-agnostic phrasing throughout spec pages, diagrams, and prerequisites
- Architecture overview in How It Works rewritten to show both MCP paths in a single diagram
- Mermaid diagrams across all 7 spec pages and the How It Works page updated to use generic “Figma MCP” nodes
- Removed tool-specific labels (
figma_execute) from diagram nodes — tool names are implementation details
Expanded troubleshooting
- Figma connection troubleshooting restructured into Console MCP and Native Figma MCP tabs
- Added native MCP troubleshooting for connection issues, token validation errors, and file/node resolution
- Updated multiple-agent guidance to cover both MCP models
Pre-verification callout
- Added a prominent warning between MCP setup and firstrun in Getting Started — test your MCP connection before running firstrun
- MCP-specific verification instructions with links to each provider’s documentation
MCP documentation freshness notices
- Added notes throughout setup and troubleshooting pages reminding readers that MCP providers update their instructions frequently
- Direct links to Figma Console MCP docs and native Figma MCP docs wherever configuration is discussed
Global navigation
- Removed the Figma Console MCP anchor from the global nav — with dual MCP support, a single provider link is misleading
uSpec V1.4
Thecreate-color skill now uses a single consolidated extraction script and a clearer AI interpretation layer — replacing the previous multi-step flow with a faster, more accurate pipeline.Consolidated extraction script
- A single
figma_executecall (Step 4b) replaces the previous multi-step flow (token extraction + separate boolean enrichment + separate axis classification), handling everything in one pass - The script walks the component tree, resolves color variable bindings, classifies variant axes by token fingerprint, detects boolean-gated elements, and discovers mode-controlled collections
Sub-component tagging
- Nested instances are now tagged with their parent component set name, producing richer and more descriptive element labels in the output tables
Nested boolean enablement
- Live preview instances now show all optional elements (icons, prefix/suffix, clear button, hints) by recursively enabling boolean properties on nested instances, so the artwork matches the documented tokens
Updated AI interpretation layer
- Step 4c strategy selection logic is clearer — the two-gate model (variant count and token similarity) now has explicit thresholds and reasoning guidance for choosing Strategy A vs Strategy B
uSpec V1.3
Thecreate-voice screen reader skill now produces more detailed, more accurate specs while using fewer tokens — smarter extraction, better artwork fidelity, and automatic state deduplication.More detailed screen reader output
- Focus stop discovery uses deep traversal (
findOne) instead of shallow children lookup — correctly resolves nested elements like a clear button inside an Input child instance - Focus Order artwork now maximizes element visibility: boolean properties are force-enabled and the richest state variant is selected automatically, so all documented focus stops appear in the preview even when the default variant hides some of them
booleanDefsextracted alongsidevariantAxesin the component scan, giving the rendering step full knowledge of toggleable sub-elements
Fewer tokens via state grouping
- States with identical accessibility semantics (same focus stops, roles, labels, and announcements) are collapsed into a single entry with a combined title — e.g., “Text field Enabled / Pressed / Active” instead of three separate sections
- Cuts redundant output for components like Text field that have many visual-only state differences but identical screen reader behavior
- Guidance added to both the skill workflow and the agent instruction file, with a new validation checklist row and common-mistake entry
Housekeeping
- Added
FONT_FAMILYplaceholder to the rendering template for consistent font resolution across specs
uSpec V1.2
Major overhaul of thecreate-structure skill with smarter measurements, template-driven layout, and a clear deterministic/AI split.Smarter measurement annotations
- Padding and spacing now use Figma’s native measurement display instead of custom text labels — cleaner output with no mislabeled annotations
- Min/max constraints show actual node values (e.g.,
min 32,max 200)
Template-driven previews
- Preview layout is defined by the template; the script no longer overrides direction or spacing
- Section template hidden by default, eliminating an extra manual step
Clearer agent instructions
- Removed ambiguous language that caused layout direction changes
- Updated validation rules for new measurement behavior
Deterministic vs AI split (~60/40)
- ~60% deterministic scripts handle extraction, cross-variant comparison, and rendering
- ~40% AI reasoning handles section planning, design-intent notes, and anomaly detection
- Output is highly consistent across runs
uSpec V1.1.0
Added support for Claude Code CLI and Codex CLI alongside Cursor, and improved anatomy and property skills for complex components.Multi-platform support
- Claude Code CLI and Codex CLI are now supported as agent hosts alongside Cursor
- New
firstrunskill handles environment setup — run/firstrunin Claude Code or$firstrunin Codex to get started - Skills are deployed to the chosen platform on demand, keeping each environment clean
CLAUDE.mdandAGENTS.mdprovide platform-specific project instructions
Improved layer detection
- Anatomy and Property skills now handle complex component structures with better layer detection and classification
- More accurate marker placement for deeply nested or auto-layout-heavy components
Infrastructure
sync-skills.shsupports--targetflag for platform-specific skill deploymentuspecs.config.jsonnow stores the active environment alongside template keys.gitignoreupdated to keep generated skill copies out of version control
uSpec V1
First public release of uSpec — an agentic system that generates design system documentation directly in Figma, powered by AI agent skills in Cursor.Spec types
- Anatomy: numbered markers and attribute tables for component structure, with AI-driven element classification, per-child sections, and property-aware unhide
- Properties: variant axes, boolean toggles, variable mode exhibits, and child component chapters with live instance previews
- API: property tables with values, defaults, required status, sub-component tables, and configuration examples
- Color Annotation: design token mapping for fills, strokes, and shadows across states and variants, with automatic strategy selection
- Structure: dimensions, spacing, and padding across density, size, and shape variants with token references
- Screen Reader: VoiceOver (iOS), TalkBack (Android), and ARIA (Web) accessibility specs with focus order and merge analysis
- Motion: animation timeline bars and easing detail tables from After Effects keyframe data, with pre-computed segments and color-coded easing visualization
Infrastructure
- Agent skills architecture running in Cursor via
.cursor/skills/ - Figma Console MCP integration for real-time component data extraction
- Template library system with one-time
@firstrunconfiguration - Documentation site at docs.uspec.design