# Getting Started
Source: https://docs.uspec.design/getting-started
Set up your AI agent, the uSpec Extract plugin, and Figma, then run the pipeline: generate a Component Markdown spec and render it into Figma
This page covers everything you need to go from zero to your first generated spec.
Every spec flows through one pipeline: the **uSpec Extract** plugin captures your component, `create-component-md` turns that capture into a `.md` spec, and the `create-*` skills render that `.md` into Figma. The full plugin install and `create-component-md` walkthrough lives on the [Component Markdown page](/specs/component-md).
**Before you start:** Make sure your agent has an active Figma MCP connection if you plan to run `firstrun` or render specs into Figma. Install and configure Figma MCP by following its current setup instructions. uSpec records your MCP choice, but it does not install or configure the connection for you.
Install your AI agent, connect Figma, and configure your template library.
Prompt format, available skills, and tips for better output.
***
## Setup instructions
uSpec runs one pipeline end to end: extract a component, generate its `.md` spec, then render that spec into Figma. To run the full pipeline you need four pieces, all set up once:
1. **AI agent host**: the coding environment that runs uSpec skills (Cursor, Claude Code, or Codex)
2. **uSpec Extract plugin**: the Figma Community plugin that captures a component to `_base.json`,
which `create-component-md` turns into canonical `.json` and `.md` artifacts. Install it from the
[Figma Community](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) — no
local build required. The public plugin asks for the selected component's Figma link on first
use, then remembers it for that document. The
[Component Markdown install guide](/specs/component-md#what-you-need) covers it in detail.
3. **Figma MCP**: an active connection that lets the `create-*` skills render annotation frames back into your Figma file
4. **Template library**: the Figma file containing the documentation templates those render skills clone from
`create-component-md` only needs the agent host and the uSpec Extract plugin — it does not use the Figma MCP or `firstrun`. The MCP and template library are for the `create-*` render skills, which read the `.md` and draw annotations in Figma.
You only need to complete this setup once. After that, you can generate specs anytime by opening the project in your agent host.
### 1. Set up your agent host
Cursor is an AI code editor. All uSpec skills run inside Cursor's chat.
Go to [cursor.com](https://cursor.com) and download the app for your platform.
uSpec installs into your existing project — you do not need to clone the uSpec repo. Open any folder where you want to use uSpec.
In the project's terminal, run:
```bash theme={null}
npx uspec-skills init
```
Choose **Cursor** when prompted. The CLI installs all skills into `.cursor/skills/` and references into `./references/`, then writes `uspecs.config.json`.
uSpec skills are token-intensive and require a model with high context capacity. In Cursor's chat, select **OpenAI GPT 5.4 High** or **Opus 4.6 High** or above. OpenAI 5.4 High is more economical to use.
Lower-capacity models may truncate instructions mid-skill, producing incomplete or broken specs. **OpenAI GPT 5.4 High** or **Opus 4.6 High** is the minimum recommended model.
Verify skills are available by typing `@create-voice` or `@create-component-md` in Cursor's chat. Either should autocomplete to the skill file.
Claude Code is Anthropic's terminal-based coding agent.
Follow the [Claude Code installation guide](https://code.claude.com/docs/en/overview) to install the CLI.
uSpec installs into your existing project. `cd` into any folder where you want to use uSpec.
```bash theme={null}
npx uspec-skills init
```
Choose **Claude Code CLI** when prompted. The CLI installs all skills into `.claude/skills/` and references into `./references/`, then writes `uspecs.config.json`.
Use **OpenAI GPT 5.4 High** or **Opus 4.6 High** or above. uSpec skills are token-intensive and require high context capacity. OpenAI 5.4 High is more economical to use.
Run `claude` in the project directory. Claude Code should discover the `firstrun` skill from `.claude/skills/firstrun/`.
Codex is OpenAI's coding agent.
Follow the [Codex setup guide](https://developers.openai.com/codex/) to install the CLI.
uSpec installs into your existing project. `cd` into any folder where you want to use uSpec.
```bash theme={null}
npx uspec-skills init
```
Choose **Codex CLI** when prompted. The CLI installs all skills into `.agents/skills/` and references into `./references/`, then writes `uspecs.config.json`.
Use **OpenAI GPT 5.4 High** or **Opus 4.6 High** or above. uSpec skills are token-intensive and may produce incomplete output with lower-capacity models. OpenAI 5.4 High is more economical to use.
Codex should discover the `firstrun` skill from `.agents/skills/firstrun/`. Type `$firstrun` to get started, or use `/skills` to browse what's available.
**Using more than one agent host?** Run `npx uspec-skills install --platform ` for each additional host in the same project. The CLI installs into the host's directory without touching the others, so you can have `.cursor/skills/`, `.claude/skills/`, and `.agents/skills/` side by side.
```bash theme={null}
npx uspec-skills install --platform claude-code
npx uspec-skills install --platform codex
```
***
### 2. Set up Figma MCP
Figma MCP is an external prerequisite for `firstrun` and every skill that renders documentation into Figma. Install and configure it in your agent host before continuing. Because MCP setup changes independently of uSpec, follow the current instructions provided with your Figma MCP.
Complete the setup instructions for your agent host and Figma MCP.
Open the Figma file you want to use, then ask your agent to confirm that it can access the file.
Continue when your agent confirms that the Figma MCP connection is active.
***
### 3. Run firstrun
The `firstrun` skill configures your Figma template library. Platform selection and skill installation are handled by `npx uspec-skills init` (Step 1) — `firstrun` only handles the Figma side.
You only need to run `firstrun` once per project. It reads your platform and MCP choice from `uspecs.config.json` and uses them to extract template keys from your Figma library.
#### Get the template file
uSpec renders documentation using Figma component templates. You need to add the templates to your Figma organization before running `firstrun`.
Uber designers use the built-in template library. When `firstrun` asks whether you are an Uber employee, answer **Yes**.
Go to the [uSpec Template](https://www.figma.com/community/file/1603925462078533207/uspec-template) on Figma Community.
Click **Open in Figma** to add a copy to your drafts.
Move the file to your team or organization project, then publish it as a library:
1. Open the file in Figma
2. Go to the **Assets** panel
3. Click the book icon and select **Publish library**
4. Confirm the publish
This makes the templates available for uSpec to import.
If you're working solo or testing, you can skip publishing and use the file directly. The `firstrun` skill will still work as long as you have the file open.
#### Run the firstrun skill
Open your Figma template library file and make sure your agent can access it through Figma MCP.
In Cursor's chat, type:
```
@firstrun
```
Invoke the skill directly or let Claude auto-discover it:
```
/firstrun
```
Invoke the skill with `$` or let Codex match it from the description:
```
$firstrun
```
When the agent asks whether you are an Uber employee:
* Answer **Yes** to use the built-in Uber template library.
* Answer **No**, then paste the link to your Figma template library.
`npx uspec-skills init` recorded your Figma MCP choice and platform in `uspecs.config.json`, so the agent does not ask for them again.
The agent extracts component keys from your templates and merges them into `uspecs.config.json` automatically.
When you see "Setup complete! You are now ready to use uSpec", your environment and template library are configured.
***
## Create your first spec
The pipeline has two stages. Stage 1 produces the canonical `.json` contract and its concise `.md`
view; stage 2 renders any section of the Markdown into Figma. Run them in order.
**Before stage 1 (generate the `.md`):**
1. Your agent host is open in the project where you ran `npx uspec-skills init` and skills are available
2. The **uSpec Extract** plugin is installed from the [Figma Community](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) (see the [Component Markdown install guide](/specs/component-md#what-you-need))
3. You have a `_base.json` file produced by running the plugin on a component
**Before stage 2 (render into Figma):**
1. You have a component `.md` from stage 1
2. Your Figma MCP connection is active
3. You've run `firstrun`. The template library is configured (`uspecs.config.json` has your template keys and MCP provider)
### Stage 1: generate the Component Markdown
Reference `create-component-md` and point it at the `_base.json` produced by the plugin. No Figma link is required — the plugin capture is the input.
```
@create-component-md baseJsonPath=~/Downloads/text-field-_base.json
```
```
/create-component-md baseJsonPath=~/Downloads/text-field-_base.json
```
```
$create-component-md baseJsonPath=~/Downloads/text-field-_base.json
```
This writes `./components/text-field.md`. That file is the input for every render skill below.
See the [Component Markdown guide](/specs/component-md) for the full plugin install, usage, and cost walkthrough.
### Stage 2: render a section into Figma
Reference a `create-*` skill, pass the component `.md`, and add anything the agent can't infer from the spec: which Figma node to render next to, or behavior and interaction details. The skill reads the `.md` — it does not re-extract from a Figma link.
```
@create-voice ./components/text-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
Focus moves label, then field, then the clear button.
```
```
/create-voice ./components/text-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
Focus moves label, then field, then the clear button.
```
You can also skip the `/` and describe what you need. Claude auto-discovers the skill from its description.
```
$create-voice ./components/text-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
Focus moves label, then field, then the clear button.
```
Type `$` to mention a skill explicitly, or use `/skills` to browse what's available. Codex can also match skills implicitly from their description.
### Available skills
The skills split into two groups based on their place in the pipeline.
**Stage 1 — produces the canonical contract and its Markdown view:**
| Skill | What it generates |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create-component-md` | Schema-valid `.json` contract plus concise `.md` covering API, structure, color tokens, and screen-reader behavior. Takes a `_base.json` from the uSpec Extract Figma plugin. [Full guide →](/specs/component-md) |
**Stage 2 — render a section of the `.md` into Figma:**
| Skill | What it renders |
| ------------------ | --------------------------------------------------------------- |
| `create-anatomy` | Numbered markers on a component with an attribute table |
| `create-property` | Variant axis and boolean toggle exhibits with instance previews |
| `create-voice` | Screen reader specs for VoiceOver, TalkBack, and ARIA |
| `create-color` | Color token annotations for all elements and states |
| `create-api` | Property tables with values, defaults, and examples |
| `create-structure` | Dimensional specs for spacing, padding, and sizing |
Each stage-2 skill takes the component `.md` from stage 1 as its required input and renders that section as Figma annotations. They do not re-extract from a Figma link.
**Exception — `create-motion`:** renders an animation timeline and easing spec from an After Effects export. It is the one skill outside the Component Markdown pipeline. See the [Motion guide](/specs/motion).
### What happens when you run a skill
Each stage runs a different pipeline.
The orchestrator validates `_base.json`, stages it into `.uspec-cache/{componentSlug}/`,
and prepares compact evidence slices with deterministic obligations.
`extract-api` runs first and writes `api-dictionary.json`. The dictionary keeps the three downstream specialists aligned on property names and states.
`extract-structure`, `extract-color`, and `extract-voice` run as three parallel subagents in a single batch.
The CLI validates specialist caches and evidence obligations. The orchestrator compares
typed disagreements and re-dispatches the owning specialist when needed.
The CLI compiles validated semantics into `components/{componentSlug}.json`, then renders
`components/{componentSlug}.md` deterministically from that contract.
If sibling `.json` and `.md` files appear under `./components/`, your setup is working
correctly.
The skill parses the component `.md` you pass in for the section it owns (anatomy, API, color, structure, properties, or voice) plus the render-meta that ties each section to Figma nodes.
The agent imports the matching documentation template into your current Figma page.
Component name, guidelines, properties, and tables are filled in from the `.md` — no re-extraction from the live file.
Sections are cloned for each variant, state, or property recorded in the `.md`.
A screenshot is captured and verified. Issues are fixed automatically.
If a documentation frame appears in your Figma file, your setup is working correctly.
### Tips for better output
* **Be specific about states**: Mention all states (selected, disabled, expanded) when you generate the `.md` — either in the plugin's design-intent field or in your `create-component-md` prompt. The render skills can only show what the `.md` records.
* **Describe the parts**: For complex components, describe the interactive elements (e.g., *"This is a tooltip. The bell icon triggers it, and the bubble appears on hover and focus."*)
***
## Best practices
### Do (all skills)
* **Start a new agent session for every prompt.** Each skill consumes significant context. A fresh session ensures the model has full capacity and avoids degraded output.
* **Run on a high-capacity model.** Render skills work on OpenAI GPT 5.4 High or Opus 4.6 High. `create-component-md` uses parallel subagents and needs Opus 4.7 High or better.
### Do (stage 2 render skills)
* **Generate the `.md` first.** Every `create-*` render skill takes a component `.md` as its required input. Run `create-component-md` before reaching for any of them.
* **Confirm the MCP connection before running a skill.** Ask your agent to verify that it can access your Figma file. If the agent can't reach Figma, the render will fail.
* **Run one agent per Figma file at a time.** Concurrent writes can conflict and corrupt the output. Finish one render before starting the next.
### Don't (stage 2 render skills)
* **Interact with the Figma frame while a skill is running.** The agent writes to the frame in multiple steps. Clicking, selecting, or editing mid-generation can break node references and corrupt the output.
* **Run multiple agents on the same file simultaneously.** They override each other's page navigation and produce corrupted specs. If you need parallel generation, use separate Figma files.
### Don't (all skills)
* **Reuse a long chat session for multiple skills.** Accumulated history reduces available context and degrades output quality. Start fresh each time.
`create-component-md` does not write to Figma, so the Figma-interaction caveats above do not apply to stage 1. You can run multiple `create-component-md` skills in parallel against different components safely.
***
## Setup issues
Run `npx uspec-skills doctor` from your project root. It reports any missing skills, missing references, or broken links.
* Confirm the project folder is open in Cursor (not a parent directory)
* Check that `.cursor/skills/` contains the skill folders. If empty, re-run `npx uspec-skills install --platform cursor`.
* Restart Cursor after running `npx uspec-skills init` so it picks up the new skills.
* Confirm you're running `claude` from the project root where you ran `npx uspec-skills init`
* Check that `.claude/skills/` contains the skill folders. If empty, re-run `npx uspec-skills install --platform claude-code`.
* Confirm you're in the project directory where you ran `npx uspec-skills init`
* Check that `.agents/skills/` contains the skill folders. If empty, re-run `npx uspec-skills install --platform codex`.
* Confirm Figma and your Figma MCP are running
* Check the MCP connection and credentials in your agent host
* Ask your agent to verify that it can access your Figma file
* Follow the current troubleshooting instructions provided with your Figma MCP
For issues with skills or Figma connection, see the [Troubleshooting guide](/help/troubleshooting).
# Changelog
Source: https://docs.uspec.design/help/changelog
Product updates and release history
## What's new
Component Markdown now writes a canonical JSON contract, then a concise `.md` you can hand to an
LLM. The public Extract plugin captures every variant, not just the default.
* **`component-md validate`**, **`contract`**, and **`render`** — validate specialist evidence,
write `components/{slug}.json`, then render the sibling `.md`. Concise is the default; pass
`--view audit` for diagnostics.
* Untraceable rows fail instead of silently entering the spec. Details live in
[Component Markdown](/specs/component-md).
* **uSpec Extract 2.7.0** records children, revealed trees, and ownership across all variants.
Schema stays at version 1; older extractions still prepare.
## Upgrade
Run `npx uspec-skills@0.3.3 update`, then update **uSpec Extract** from the
[Figma Community](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract).
Re-extract a component to pick up cross-variant evidence. The Community plugin still needs the
component link on first use in a document.
## uSpec V2.6
The [Component Markdown](/specs/component-md) pipeline now opens with a **deterministic CLI prepare stage** before any AI interpretation runs. `uspec-skills component-md prepare` validates the plugin's `_base.json`, stages it into `.uspec-cache/{componentSlug}/`, and writes a prepare manifest plus four compact evidence slices — one per specialist domain. The orchestrator and `extract-*` skills consume those slices directly, so the agent no longer re-derives the same facts from the full 500 KB+ base file on every pass.
### New CLI command: `component-md prepare`
* **`npx uspec-skills component-md prepare --base [--json]`** validates against the bundled Ajv schema (same contract as the Figma plugin validator), stages `{componentSlug}-_base.json`, and writes:
* `{componentSlug}-prepare-manifest.json` — hash, paths, readiness flags, one-line summary
* `{componentSlug}-evidence-{api,structure,color,voice}.json` — compact domain slices for the four specialists
* **`create-component-md` Step 1** now shells out to this command instead of manually validating and staging. The skill resolves the CLI in order: local monorepo build → published npm → version-pinned `@0.3.2`.
* **`extract-*` evidence fast path** — when a prepare evidence file's `_meta.baseSourceHash` matches the staged base, the specialist uses the slice for Step 3 instead of rebuilding from the full `_base.json`.
### Why this matters
* Prepare runs in \~200 ms and is fully deterministic — two runs against the same `_base.json` produce byte-identical evidence slices.
* The four AI interpretation passes start from compact, pre-classified inputs, reducing token load and eliminating repeated schema validation work.
* npm consumers no longer need the `figma-plugin/` package on disk to validate exports.
Run `npx uspec-skills update` to pick up the skill changes (this release ships as `uspec-skills` 0.3.2). No action needed on Figma libraries or the uSpec Extract plugin.
## uSpec V2.5
Two refinements to the [Component Markdown](/specs/component-md) pipeline. The generated `.md` now opens its Structure section with a compact **Anatomy** tree so you can read the component's layer nesting before the dimensional tables, and the reconciliation pass no longer reports top-level booleans (such as `isDisabled` or `isLoading`) or decomposed states as Known gaps. Both changes are deterministic and require no re-extraction.
### Anatomy scaffold in the Structure section
* Every `components/{componentSlug}.md` now renders an `### Anatomy` block at the top of its Structure section — a compact, text-based tree of the component's parent→child layer composition
* The tree is a mechanical pass-through of the plugin's layer walk: real layer names and ids, no measurements and no inferred nodes. Top-level children carry their `constitutive` / `referenced` / `decorative` classification, and a layer named in a Voice "Do NOT announce" rule is tagged `a11y-hidden`
* It gives engineers and downstream LLMs an at-a-glance map of the component before they read the measured tables
### Fewer false-positive Known gaps
* The reconciliation pass now recognizes that top-level booleans and Figma states decomposed into runtime conditions are part of the API surface, not unexplained extras. A documented Disabled or Loading section that traces back to a real boolean or state is treated as a **match**, not a gap
* `extract-api` now publishes a canonical `booleanProps[]` list in the API dictionary, giving the Structure, Color, and Voice specialists a name to reconcile against. Each specialist resolves an observed value against the full dictionary before flagging it
* Genuine semantic conflicts — a value that traces to nothing in the API or the design — are still surfaced as high-severity Known gaps. Only the systemic boolean false-positive is removed
Run `npx uspec-skills update` to pick up the skill changes (this release ships as `uspec-skills` 0.3.1). No action needed on Figma libraries or the uSpec Extract plugin.
## uSpec V2.4
The **uSpec Extract plugin is now on the [Figma Community](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract)** — no more local build — and the `create-*` render skills now **consume the [Component Markdown](/specs/component-md) source of truth** (`components/.md`) instead of re-extracting from Figma. Each render skill requires the `.md`, fails fast when it's missing, treats it as read-only, and renders the Figma frame from the `.md` body + its `render-meta` block — with only a small per-skill whitelisted live read. `create-component-md` produces the `.md` from a `_base.json` and remains the single extraction path; the `create-*` skills are now pure renderers.
### `create-*` skills consume the Component Markdown
* **`create-structure`**, **`create-color`**, **`create-api`**, and **`create-voice`** parse their respective section of the `.md` (Structure, Color, API, Voice / Screen reader) plus the shared `render-meta` block, then render the frame. They no longer walk the component through MCP to extract dimensions, tokens, properties, or focus stops — those values are read from the `.md`
* **`create-property`** and **`create-anatomy`** have no dedicated `.md` body section, so they take the component's identity from `render-meta`: `create-property` rebuilds the property model (variant axes, boolean defs, variable modes, child component properties) from `render-meta`, and `create-anatomy` seeds element identity from `render-meta` and runs only a bounded minimal child/variant walk to confirm live layer geometry
* Every skill **fails fast** if `components/.md` is absent — there is no silent fallback to re-extraction
* Whitelisted per-skill live reads are deliberately minimal: `create-color` calls `getLocalVariableCollectionsAsync()` only to render variable-mode previews, and `create-api` runs a bounded `<=30-line` TEXT-node listing only to source preview text for configuration examples. Markers, measurements, and exhibits resolve by `render-meta` layer id with a name-match (+ live bbox where relevant) fallback on the rendered instance
### `voice-render-meta` focus-stop carry (`create-voice`)
* A hidden `voice-render-meta` block now carries the focus-stop layer-name mapping through the `.md`, so `create-voice` resolves focus markers exactly against the rendered instance instead of re-deriving them by traversal
### uSpec Extract plugin on the Figma Community
* The **uSpec Extract** plugin is now published on the [Figma Community](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract). Install it directly from Figma — no cloning the repo and running `npm run build`
* The plugin stays **open source** (`figma-plugin/` in the repo) for anyone who wants to read or build a modified version, and it remains **separate from the npm package** — `npx uspec-skills` delivers only the skills, while the plugin lives in Figma Desktop
* Because every `create-*` render skill now requires a `.md`, and the `.md` comes from `create-component-md` consuming the plugin's `_base.json`, the plugin is now part of the standard pipeline rather than an optional extra
### Read-only input guard on `create-*` skills
* Every `create-*` skill now treats the input `.md` as **read-only**. A render request like "add a Tap target section" or "show the focus order" renders that annotation into Figma — the skills never edit or append to the source `.md`
* This closes a failure mode where a skill could mistake a render request for an instruction to edit the spec file. Changing the spec itself is `create-component-md`'s job
### Scope
* **`create-motion` is unchanged.** It consumes After Effects timeline JSON and never walks a component, so it is out of scope for the Component Markdown consumer model
* Already-rendered Figma specs are unaffected — the consumer model only changes future `create-*` runs
Run `npx uspec-skills update` to pick up the skill changes (this release ships as `uspec-skills` 0.3.0), and install the [uSpec Extract plugin](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) from the Figma Community. No action needed on Figma libraries.
## uSpec V2.3
The Figma plugin now captures every placed instance's full typed `componentProperties` 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 `componentProperties` on every walked INSTANCE via the new `snapshotComponentProperties` helper in `figma-plugin/src/safe.ts`. The snapshot mirrors Figma's `InstanceNode.componentProperties` API exactly — every entry carries `{ type, value }` with `type` typed to `BOOLEAN | 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 the `extract` merge can attach it to slot-origin entries that bypass the first-guess builder. `null` for non-INSTANCE entries (FRAMEs, vectors, layout wrappers) and for slot-preferred entries (which describe a referenced component, not a placed instance — read `propertyDefinitions.slots[].preferredInstances[]` for those defaults)
* **`booleanOverrides` is 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 empty `booleanOverrides` now carry the projected booleans correctly
* The new field is documented in `figma-plugin/docs/base-json-schema.md` and 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 `getSlotPropName` helper, which prefers the authoritative `componentPropertyReferences.mainComponent` binding (per Figma's SlotNode docs) and falls back to the SLOT node's own `name` when that binding is absent — the common case in real files, where SLOTs typically only carry the `visible` binding to a separate BOOLEAN prop
* This replaces a buggy `Object.values(cpRefs)[0]` lookup in `phaseA.ts` and `code.ts` that was picking up the `visible` binding (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.warn` when 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.md` introduces three small helpers shared by the Composition bullet rules and the API "Referenced components" `####` block:
* `displayName(child)` prefers `parentSetName` over the variant-identifier `mainComponentName`. When a referenced child is a variant of a COMPONENT\_SET, Figma's `mainComponentName` is the variant identifier (`"layout=icon-only, size=small, color=default"`) — useful as a configuration but useless as a component name. `parentSetName` is the human-readable set name (`"action button"`)
* `slug(child)` derives the spec filename from `displayName(child)` instead of the raw main-component name, so multi-variant references resolve to the right `./{slug}.md`
* `slotSuffix(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.componentProperties` exclusively. One row per entry in the typed dict, with per-`type` value formatting:
* `BOOLEAN` → `true` / `false`
* `INSTANCE_SWAP` → `(instance \`\`)\`
* `TEXT` → the literal string in backticks
* `VARIANT` → the bare option, with `"Variant axis on the placed instance."` in the Notes column
* The legacy `booleanOverrides` field remains on every entry for backward compatibility with the first-guess fingerprinting, but is no longer the source of truth for the rendered table. `subCompVariantAxes` is 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.md` now documents the two new `safe.ts` exports (`snapshotComponentProperties`, `getSlotPropName`), the SLOT-binding bug fix that motivated the latter, and the Phase F′ → renderer flow for the typed `componentProperties` snapshot
* `figma-plugin/docs/base-json-schema.md` documents the new `componentProperties` field on `_childComposition.children[]`, demotes `booleanOverrides` to a backward-compat projection, and adds the field to the post-change checklist
Run `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.
## 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 a `borderWidth` + `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-md` template gains a fenced JSON block delimited by `` / `` 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 against `layoutTree` and no need to re-extract through MCP
* `schemaVersion` is pinned at `"1.0"` for V2.2; future breaking changes will bump it. `sourceHash` is a SHA-256 of the underlying `_base.json` so consumers can detect drift between the `.md` and the extraction it was rendered from
* The block is **mechanical pass-through** of `_base.json` and the structure cache — no interpretation, no synthesis. Two `create-component-md` runs against the same `_base.json` produce byte-identical render-meta
### Layer identity stamped on structure output
* `extract-structure`'s new **R6** rule populates `section._anchor` (`{ layerName, layerId }`) on every section and `row._layerName` / `row._layerId` on every group-header row, reading directly from `_base.json.variants[].layoutTree`
* Composition sections anchor to the variant root with `layerName: "__root__"`; sub-component sections anchor to the in-context INSTANCE node (NOT the canonical `subCompSetId`, which is already covered by render-meta `subComponents[]`); 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 !== true` AND `spec` is a zone descriptor, not a property family) carry the literal Figma layer name and node id. Layers present only in `revealedByVariantName[*]` (e.g., a `clear button` parked under `state=active`) emit `_layerId: null` with an explanatory `notes` entry — the row is still present, just unpinned
* The `create-component-md` orchestrator now reads these fields directly into render-meta. A legacy fallback (name-walk against `layoutTree`) covers caches produced before this release; re-running `extract-structure` is recommended to regenerate the cache with the new fields
### `borderWidth` + `borderAlign` row pair
* Whenever a `borderWidth` row is queued (gate: `strokePaintToken != null`), a sibling `borderAlign` row is queued from `dimensions.strokeAlign.display` (`inside` / `outside` / `center`). The two rows share the same gate — emit both, or neither
* The coverage matrix (`_extractionArtifacts.coverageMatrix`) accepts `borderAlign` as a first-class family alongside `borderWidth`, with identical R4/R5 detection rules
* Legacy fallback: when `dimensions.strokeAlign` is absent from a `_base.json` produced by a pre-2.3.0 plugin build, `borderAlign` emits as `"—"` with `provenance: "not-measured"` and `generalNotes` surfaces 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.visible` instead of relying on the default variant's `componentProperties` keys. 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 resulting `associatedLayerId` is canonical and downstream-consumable
* **`strokeAlign` capture (Phase E).** `extractDims()` now emits `strokeAlign` as `{ value, token: null, display }` where `value` is the raw Figma enum (`"INSIDE"` / `"OUTSIDE"` / `"CENTER"`) and `display` is the lower-cased prose form. Present on `variants[].dimensions`, `variants[].treeHierarchical[*].dimensions`, and every `subComponentVariantWalks` entry. **Not** on `variants[].revealedTree[*].dimensions` — Phase G uses a minimal `dim()` extractor focused on topology; dimensional ground truth always comes from the baseline `treeHierarchical`
* **Node ids on every walk entry.** `treeHierarchical`, `layoutTree`, `treeFlat`, `colorWalk`, `revealedTree`, `revealedColorWalk`, and Phase I's `measureHierarchical` all carry the Figma node `id` (or `nodeId` for 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
* `borderWidth` rows now require `strokeWeight.value > 0`. The extractor emits `strokeWeight: { value: 0 }` for nodes that have the property set but no paint in `node.strokes`; without this gate the agent emitted a phantom `borderWidth: 0` row even though no border is painted on the component
* The structure rendering rules now forbid Figma node ids and `TODO: confirm with Figma` stubs in `Notes` columns. Notes is engineer-facing implementation context — when a value cannot be confirmed, skip the row or surface the gap in `generalNotes` rather 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 `7d2e7f4` baseline are reverted — they made the workflow brittle without improving output. `create-structure` is back on the unified `rootOnly` / `fullTree` annotation model with cleaner output
### Housekeeping
* `maintaining.md` updated for npm's current **web-based 2FA** flow — `npm publish` now 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 `.npmrc` mirrors `packages/cli/.npmrc` and 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.md` removed (`utils/` is no longer a meaningful directory in the repo)
* `README.md` and `implementation.md` prose tightened — the canvas-measurements paragraph now documents the `rootOnly` vs `fullTree` annotation policy explicitly and the new `{ success, plannedColumns }` return semantics
Run `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.
## uSpec V2.1.4
The `create-structure` skill now accepts an authoritative `components/.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.md` adds **Step 0 — Detect Input Mode**. Mode A is description-only (today's behavior). Mode B reads `components/.md` in full and persists it as `MD_SPEC` before 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 `.md` are logged in `generalNotes` and the `.md` value wins
* Step 6 in Mode B is reduced to (1) mapping each `.md` row to extraction nodes for annotation rendering, (2) reconciling each `.md` row against the corresponding extraction value, (3) skipping the cross-section pattern recognition pass (`create-component-md` already did it)
* Every emitted row now carries a required `provenance` field: `"md"` (value came from the `.md`), `"measured"` (`.md` was 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 `.md` are provided, the `.md` wins for properties it documents and the description applies only to anything the `.md` is silent on
### Reasoning discipline (Structure)
* `references/structure/agent-structure-instruction.md` adds a **Reasoning Discipline** section that applies at every step — extraction interpretation through rendering. Five rules: (1) the `.md` is the source of truth when provided, (2) every row needs provenance, (3) no confabulation — skip rows or surface gaps in `generalNotes` rather than fill in defaults, (4) screenshots verify layout intent only, not paints/strokes/spacings/radii/tokens, (5) `strokeWeight` alone is not evidence of a border
* The Conflicts table grows a new top row covering authoritative `.md` precedence, and the existing "Figma contradicts description" row is qualified to "no `.md` provided"
* The Common Mistakes section adds matching entries: hand-rolling canvas measurements, hand-curating the annotation plan, treating `strokeWeight` as evidence of a border, citing screenshots for paint or border decisions
* The Do NOT list adds: overriding an authoritative `.md` value with anything inferred from extraction or screenshots, emitting `borderWidth` when `strokePaintToken == 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.md` is rewritten around a new `strokePaintToken` signal co-emitted by the extractor. A frame can carry `strokeWeight: 1` with `strokes: []` — no border is painted, and a phantom `borderWidth` row should never be emitted from such a node
* New emission rule: emit a `borderWidth` row only when `strokePaintToken != null`. The Inspect Reference table's Stroke width row is updated to match
* The collapsed dimensional schema description in `## Dimensional Data` clarifies that `strokeWeight` is only authoritative as evidence of a border when paired with a non-null `strokePaintToken`
### `use_figma` / `figma_execute` script escaping (architecture)
* `implementation.md` adds a new "Authoring `code` strings for `use_figma` / `figma_execute`" subsection under Figma MCP Tools. Both providers serialize the `code` argument through JSON before the Figma sandbox runs it, so `\'` inside a `'...'` JS string is a recurring source of `SyntaxError` after 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.json` now declares its registration `id: "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.json` it 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-structure` runs
Run `npx uspec-skills update` to pick up the new skill content. No action needed on Figma libraries.
## uspec-skills 0.2.8
The `packages/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 update` may **delete** stale files in your local `references/` directory that were never part of the current source tree (e.g., files like `references/_shared/mcp-adapter.md` or `references/structure/scripts/*.js` that 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
Run `npx uspec-skills update` to pick up the change.
## uSpec V2.1.3
The `create-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 `extractDimensions` and Step 4d `measureNode` recurse into every child via `extractChildren` / `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 guard `node[p] !== undefined && node[p] !== figma.mixed` ran the access *first*, so the throw fired before the comparison
* Step 4e already used the correct defensive pattern (per-access `try/catch` plus an `isContainer = 'layoutMode' in node` gate); 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 the `sg(node, prop)` accessor in `figma-plugin/src/safe.ts`
* Layout-only property groups (padding, `itemSpacing`, `counterAxisSpacing`, `layoutMode`, primary/counter axis aligns, `layoutSizing*`, `clipsContent`) are gated on `isContainer = 'layoutMode' in node` so 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.md` adds a maintainer note above the Step 4b script explaining the throw-on-leaf hazard and the `try/catch` + `isContainer` pattern, 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
Run `npx uspec-skills update` to pick up the fix. No action needed on Figma libraries.
## uSpec V2.1.2
The `create-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: CENTER` and HUG-sized children the line measured the centering offset rather than the autolayout padding
* Token-bound padding rows were unaffected — `freeText` carries the token name regardless of geometry — and gap / `itemSpacing` rows 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 `freeText` override of the autolayout value so the label still matches the table
* Implemented inline as a new `findEdgeAnchor` helper above `annotate`; no per-row configuration is required
### Documentation (`uspec-skills` 0.2.6)
* `references/structure/agent-structure-instruction.md` splits the `freeText` policy bullet into "hardcoded padding row" (anchor + fallback) vs "hardcoded gap/itemSpacing row" (default label) so the contract the agent reads matches what the SKILL implements
* `implementation.md` updates 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
Run `npx uspec-skills update` to pick up the fix. No action needed on Figma libraries.
## uspec-skills 0.2.5
The `create-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`, and `minHeight` / `maxHeight`. Other properties (corner radius, typography, color) remain table-only by design
* Token-bound rows pass the token name as `freeText` so 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`) and `figma-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 `SLOT` node inside the preview, so the slot region renders with real content instead of an empty placeholder. If `appendChild` fails (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` / `plannedColumns` contract check on the value returned by Step 11c. Measurement overlays are a canvas layer that does not appear in `figma_take_screenshot` / `get_screenshot` output, so visual screenshot review is no longer the source of truth for measurement coverage
### Documentation
* `references/structure/agent-structure-instruction.md` adds a Canvas Measurements subsection covering the allow-list, `freeText` semantics, annotation scope, and the screenshot caveat
* `implementation.md` documents the render-time slot nesting and canvas measurement architecture parallel to the existing marker positioning notes
Run `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.md` now recommends `hovered` alongside `pressed` and `focused`. The recommendation table also explicitly documents that earlier docs and many existing Figma libraries use `hover`, 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 use `Hovered` / `hovered` in 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 `stateKeywords` matcher in `figma-plugin/src/phaseF.ts` and `skills/create-color/SKILL.md` accepts **both** `hover` and `hovered` as 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.
Run `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 coordinated `uspec-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 `group` wrapper for the `overflow=scroll` variant). 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[]` with `topLevelInstanceId: "wrapper:"` and `classificationEvidence: ["layout-wrapper"]`, so layout chrome remains visible to downstream consumers
* `idx:N` in `topLevelInstanceId` now indexes into the *effective* container (post wrapper descent), not the variant root. Phase I and `treeHierarchical` are 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 `_childComposition` entry instead of N. The designer classifies once; multiplicity is recorded in three new fields:
* `placementCount` — number of sibling placements that share the entry's identity
* `placementIndices` — original positions in the effective container's children
* `placementsVary` — `true` when at least two placements differ in main component or boolean overrides, signalling a heterogeneous array
* The plugin UI surfaces a `× N` badge on grouped rows and a `varies in state` tag when `placementsVary` is true, so the designer can spot heterogeneous arrays at a glance
* Equivalence fingerprint covers `mainComponentName` (which encodes variant choice for component-set members) and `booleanOverrides` — instance-swap and text-override differences are intentionally not in the fingerprint and remain visible in `treeHierarchical`
### `create-component-md` Step 4.5 fix (uspec-skills 0.2.3)
* The post-extract review previously flagged any `_childComposition` entry without `user-selected` evidence as malformed. The new wrapper FRAME entries legitimately carry `["layout-wrapper"]` evidence, so the check is now scoped to `nodeType === "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 update` to pick up the fix
## uspec-skills 0.2.2
Fixed the first run experience so the skip option works as intended. Run `npx uspec-skills update` to pick up the fix.
## 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 init` from 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 writes `uspecs.config.json`
* `npx uspec-skills install --platform ` reinstalls or repairs skills non-interactively
* `npx uspec-skills update` re-renders skills against the current package version
* `npx uspec-skills doctor` validates your install and reports missing skills, missing references, or broken cross-references
* `init` bootstraps a fresh uSpec project into the current directory when no project root marker (`.git/`, `package.json`, or `uspecs.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 happens
* `uspec-skills install` points you at `npx uspec-skills init` when 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 legacy `uspec` shorthand 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 use `npx uspec-skills init` from their own project root
* `uspecs.config.json` now records the chosen platform and MCP provider so `firstrun` reads them from disk instead of asking again
### New skill: `create-component-md`
* Orchestrator skill that turns a plugin-produced `_base.json` into a single `components/{componentSlug}.md` file
* Runs four interpretation specialists: `extract-api` (serial, produces the shared property dictionary), then `extract-structure`, `extract-color`, and `extract-voice` in 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 →](/specs/component-md)
### 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](https://github.com/redongreen/uSpec), run `npm install && npm run build` inside `figma-plugin/`, then import the manifest in Figma Desktop. See the [install walkthrough](/specs/component-md#what-you-need)
* Output is a validated `_base.json` (Ajv schema at `figma-plugin/docs/base-json-schema.md`) that becomes the sole input for `create-component-md`
### Documentation
* New [Component Markdown spec page](/specs/component-md) covering install, usage, the four-specialist pipeline, and skill-side troubleshooting
* New **Figma Extract plugin** tab on the [Troubleshooting page](/help/troubleshooting) covering build steps, Node version requirements, the watch-mode dev loop, and common install failure modes
* [Getting Started](/getting-started) rewritten around the CLI flow with platform-specific tabs
* [Troubleshooting](/help/troubleshooting) updated with `npx uspec-skills doctor` and per-platform repair commands
### Structure skill: coverage matrix artifact
* `extract-structure` now emits a `_extractionArtifacts.coverageMatrix` artifact 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 === true` and 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 `horizontalPadding` or `itemSpacing` could be measured but not emitted
### Dual-path architecture
* `implementation.md` fully rewritten to describe both rendering paths, the plugin phases (A–I), the orchestrator workflow, the `.uspec-cache/` layout, and the `extract-*` interpretation skills
* `uspecs.config.json` gains `extractionSource: "plugin"` and `reconciliation: { 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
## 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)
* `measureChildren` now calls itself recursively instead of using a flat loop for grandchildren — deeply nested wrapper frames (e.g., icon containers inside `trailingContent`) are fully measured and surfaced as `__children` entries 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 `__children` entries 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 `enrichedTree` when 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
## 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 `buildCompositeDetail` function in the extraction script detects paint styles with 2+ visible fill layers and emits a `compositeDetail` object 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 `compositeChildren` arrays on elements — solid layers, gradient layers with per-stop detail, and image layers — rendered as nested rows with hierarchy indicators (`#hierarchy-indicator` frame toggled per child row)
* Both Strategy A (simple) and Strategy B (state-consolidated) rendering scripts support composite child rows with `showIndicator` for 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 `exhibitPlan` array 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 new `6a-ctx` and `6b-ctx` templates
* 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 a `rv()` 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`/`instAbsY` recomputed 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
## 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 `ownershipHints` array in the extraction script collects deterministic ownership cues from root properties, child overrides, text nodes, and variable collections — each hint includes `evidenceType`, `suggestedExposure`, and a `rationale`
* New Step 4c requires assembling a structured `ComponentEvidence` object before reasoning about the API — keeping raw facts separate from semantic interpretation
* `relevantVariableCollections` are 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 `ComponentEvidence` TypeScript interface as the required intermediate model between extraction and API generation
### Override promotion pass
* Step 5 now includes a mandatory override promotion pass: every `composableChildren` override 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 `isSubProperty` usage
* 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` → nested `label`, `variant`)
* Added `showCharacterCount` to the Text field canonical API
* Added `validationState` enum guidance for components with multiple validation-like states
## 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-voice` now resolves SLOT `preferredValues` to 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.md` now documents the voice skill's preferred-slot extraction and insertion flow alongside the existing SLOT support across other skills
## 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`, and `layoutTree` as 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 `slotContent` path, 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 `slotContent` after ownership resolution
* `slotContext` is the primary source for hosting-container properties such as sizing mode, padding, and alignment
* The preferred component's measured `self` values 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
## 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 `slotInsertions` parameter populates named SLOT nodes with fresh component instances: specify the slot name, a component node ID, and optional `nestedOverrides` / `textOverrides` on the inserted child
* All overrides are applied **before** `appendChild` into 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 for `textOverrides` keys
### Sub-component token ownership (Color)
* New **token ownership decision framework** in the color instruction file — evaluate each `subComponentName` entry 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 | Notes` columns 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: hug` instead 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_OVERRIDES` array 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.setCurrentPageAsync` for stable child traversal
### Slot-safe tree traversal
* `loadAllFonts` across API, color, and structure skills now uses a manual recursive collector with per-node try-catch instead of `findAll` — prevents crashes on SLOT nodes with compound IDs
* Color extraction adds `figma.setCurrentPageAsync` before traversal for stable child resolution
* `enableNestedBooleans` and `directUnhide` in the color skill wrapped with try-catch guards for slot-hosted instances
* `implementation.md` documents the **slot mutation ordering constraint**: all mutations on a child instance must happen before `appendChild` into 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
## 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 `preferredValues` to local component nodes, reads `componentPropertyReferences.visible` for boolean bindings, and surfaces `slotDefaultChildren` for 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 `slotProps` with preferred instances and `defaultChildren` including 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 `preferredValues` and generates dedicated `slotContent` sections 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 `slotVisibility` for 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`, `appendChild` into slots, and `directUnhide` — preventing "unloaded font" errors on components using non-template fonts
* **Font-family fallback** (`loadFontWithFallback`) discovers exact font style strings via `listAvailableFontsAsync` instead 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 assuming `children[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-description` header field
* Replaces the previous generic "Anatomy breakdown of..." and "Configurable properties of..." text
### Root container detection (Anatomy)
* New `childContainerIsVariant` flag 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
* `hasStrokes` on the root variant no longer triggers a separate synthetic element — strokes are described in the container note instead
### Voice rendering improvements
* Removed `artworkLabels` and the detach-and-replace-text workflow — artwork instances stay live throughout rendering
* `findStopNode` now 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.width` to match the template layout instead of computing independently
* Conditional focus stops and disabled/non-focusable states documented in merge analysis guidance
## 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 `text` instead of `container` — the frame name is preserved in `originalName` and the element carries `nodeType: '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` / `originalName` documentation in the instruction file
### Frame icon indicator (Anatomy)
* New `#frame` indicator icon for FRAME and GROUP node types, added alongside the existing `#instance`, `#text`, and `#slot` icons
* 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)
* `name` now consistently returns the designer-facing layer name across all classifications
* For `instance-unwrapped` elements, `name` is the wrapper frame's name (e.g., "Thumb") — the inner component name is available via `wrappedInstance.componentSetName`
* Previously, unwrapped instances overwrote `name` with the inner component's `componentSetName`, 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 shadow` entries are still emitted when no effect style is applied
* The `variantColorData` contract documents the new `"effect style"` property value and its semantics
### Effect and elevation token category (Color)
* Added `Effect/Elevation` row to the token-naming reference table with common style names (`low`, `medium`, `high`)
* Added `Effects` row 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 and `clipsContent = 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`/`height` plus marker margins, replacing the stale `ROOT_SIZE` parameter
* 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_SIZE` placeholder 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 `findStopNode` may fail
## 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 Figma `addMeasurement` calls) from the structure skill
* The `addMeasurement` API 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
* `rootVariantVisuals` and `traversedFrames` are 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 `isClustered` detection 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
* `selectedVariantId` is returned by extraction and reused by the rendering step, ensuring artwork matches the extraction data
* `resolveChildContainer` refactored 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` / `trailingIcon` spec 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.md` with improved reference patterns
* Updated `implementation.md` with 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 `slot` classification type in the anatomy extraction script — SLOT nodes are detected, traversed, and annotated with a dedicated `#slot` indicator 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 `slotIndex` for 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 `mainComponentSetId` so 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 `constrainedBy` metadata 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 `artworkLabels` and 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.WEB` over 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 via `tn.fontName`) for `figma-mcp` where `findAll`, `findOne`, and `getRangeAllFontNames` throw `TypeError`
* 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](https://docs.figma-console-mcp.southleft.com/) and [native Figma MCP docs](https://github.com/figma/figma-mcp) 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
The `create-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_execute` call (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
The `create-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
* `booleanDefs` extracted alongside `variantAxes` in 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_FAMILY` placeholder to the rendering template for consistent font resolution across specs
## uSpec V1.2
Major overhaul of the `create-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 `firstrun` skill handles environment setup — run `/firstrun` in Claude Code or `$firstrun` in Codex to get started
* Skills are deployed to the chosen platform on demand, keeping each environment clean
* `CLAUDE.md` and `AGENTS.md` provide 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.sh` supports `--target` flag for platform-specific skill deployment
* `uspecs.config.json` now stores the active environment alongside template keys
* `.gitignore` updated 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 `@firstrun` configuration
* Documentation site at [docs.uspec.design](https://docs.uspec.design)
# Contribute
Source: https://docs.uspec.design/help/contribute
Get help, provide feedback, or contribute to uSpec
Have questions, found a bug, or want to contribute? Here's how to get involved.
Open an issue on GitHub for questions, feedback, or feature requests.
Report issues, suggest improvements, or submit pull requests.
## Report an issue
If you encounter a bug or unexpected behavior:
1. Check the [Troubleshooting guide](/help/troubleshooting) first
2. If the issue persists, [open an issue on GitHub](https://github.com/redongreen/uSpec/issues) with:
* What you were trying to do
* What happened instead
* The JSON output (if applicable)
# Troubleshooting
Source: https://docs.uspec.design/help/troubleshooting
Solutions for common issues when creating specs
Having trouble creating a spec? Find solutions below based on where the issue occurs.
uSpec specs are generated by an LLM. Always review the output for accuracy. The agent can misinterpret component structure, assign incorrect token names, or produce incomplete specs. Treat generated specs as a strong first draft that needs a human review pass before shipping.
**Symptom**: You type a prompt but the skill doesn't run.
First, run `npx uspec-skills doctor` from your project root. It reports missing skills, missing references, or broken links and tells you exactly what to fix.
* Use the direct reference format: `@create-voice` instead of typing keywords
* Confirm your project folder is open in Cursor (the same folder where you ran `npx uspec-skills init`)
* Verify `.cursor/skills/` contains the skill folders. If empty, run `npx uspec-skills install --platform cursor`
* Restart Cursor if skills don't autocomplete
* Confirm you're running `claude` from the project root where you ran `npx uspec-skills init`
* Verify `.claude/skills/` contains the skill folders. If empty, run `npx uspec-skills install --platform claude-code`
* Try mentioning the skill by name: "Run create-voice for this component"
* Confirm you're in the project directory where you ran `npx uspec-skills init`
* Verify `.agents/skills/` contains the skill folders. If empty, run `npx uspec-skills install --platform codex`
* Try using `/skills` to list available skills, then invoke with `$skill-name`
**Symptom**: The generated spec is missing information or has incorrect values.
**Solutions**:
* Make sure you're using a high-context model — **OpenAI GPT 5.4 High** or **Opus 4.6 High** or above. OpenAI 5.4 High is more economical to use. Lower-capacity models may truncate skill instructions and produce incomplete specs.
* Start a **new agent session** for each prompt to give the model full context capacity
* Add more context to your prompt: describe all states, variants, and behaviors
* Specify states explicitly (e.g., "enabled, hovered, pressed, disabled")
* Include a screenshot for complex components
* Mention any non-obvious interactions or behaviors
**Symptom**: The agent stops generating before finishing, or the output is truncated or malformed.
**Solutions**:
* Switch to a higher-context model — uSpec skills are token-intensive
* Start a **new agent session** instead of continuing in an existing conversation — accumulated history reduces available context
* If the issue persists, try running the skill again in a fresh session with a simpler prompt first
**Symptom**: Typing `@create-` doesn't show skill suggestions.
**Solutions**:
* Confirm your project folder is open in Cursor (the folder where you ran `npx uspec-skills init`)
* Verify `.cursor/skills/` contains the skill folders. If empty, run `npx uspec-skills install --platform cursor` to repair the install
* Restart Cursor after running `npx uspec-skills init` or `npx uspec-skills install`
MCP providers update their setup and troubleshooting guides frequently. If the solutions below don't resolve your issue, check the provider's documentation for the latest instructions:
[Figma Console MCP docs](https://docs.figma-console-mcp.southleft.com/) · [Native Figma MCP docs](https://github.com/figma/figma-mcp)
**Symptom**: The agent reports it cannot access your Figma file.
**Solutions**:
* Confirm Figma Desktop is running (not the web version)
* Check that the Desktop Bridge plugin is open and active in your Figma file
* Ask your agent to "Check Figma status" to diagnose the connection
* Restart the Desktop Bridge plugin if it's unresponsive
* Verify your `FIGMA_ACCESS_TOKEN` is set correctly in your MCP configuration
For detailed setup and troubleshooting, see the [Figma Console MCP documentation](https://docs.figma-console-mcp.southleft.com/).
**Symptom**: The Desktop Bridge plugin is open but the agent can't connect.
**Solutions**:
* Close and reopen the Desktop Bridge plugin in Figma
* Make sure only one instance of Figma Desktop is running
* Verify your Figma access token is configured correctly:
Check your Cursor MCP settings or `.cursor/mcp.json`
Check `.mcp.json` at the project root
Check `.codex/config.toml`
**Symptom**: Output appears on the wrong page, node references break, or specs are corrupted when running two agents at the same time.
**Why this happens**: The Console MCP supports multiple simultaneous connections (ports 9223–9232), but Figma Desktop has a single active page. When two agents navigate to different pages, they override each other's context, causing broken references and interleaved writes.
**Solutions**:
* Run **one agent at a time** per Figma file — finish one skill before starting the next
* If you need parallel generation, use **separate Figma files** so each agent has its own page context
**Symptom**: The agent reports it cannot access your Figma file or the MCP server isn't responding.
**Solutions**:
* Confirm the MCP server is running — check your terminal or your agent's MCP panel for connection status
* Verify your `FIGMA_API_KEY` is set correctly in your MCP configuration
* Test with a simple command like *"List pages in my file"* with a Figma link
* Make sure the token has read and write scopes
For detailed setup and troubleshooting, see the [Figma MCP documentation](https://github.com/figma/figma-mcp).
**Symptom**: The agent connects but returns authentication or permission errors.
**Solutions**:
* Regenerate your personal access token at [figma.com/developers/api#access-tokens](https://www.figma.com/developers/api#access-tokens)
* Ensure the token has **read and write** scopes enabled
* Check that the token hasn't expired — Figma tokens can be set to expire
* Confirm the environment variable name matches your MCP configuration (`FIGMA_API_KEY`)
**Symptom**: The agent can connect but reports it can't find the specified file or node.
**Solutions**:
* Verify the `fileKey` in your Figma URL — it's the string between `/design/` and the file name
* Check that the `node-id` parameter is correct — convert dashes to colons (e.g., `100-200` becomes `100:200`)
* Confirm you have access to the file with the account that generated the token
**Symptom**: Specs are corrupted or incomplete when running multiple agents simultaneously.
**Why this happens**: The native Figma MCP uses the REST API, so it doesn't have the same port-sharing model as the Console MCP. However, concurrent writes to the same file can still cause conflicts.
**Solutions**:
* Run **one agent at a time** per Figma file — finish one skill before starting the next
* If you need parallel generation, use **separate Figma files** so each agent has its own context
The **uSpec Extract** Figma plugin produces the evidence for the component contract. It walks
a selected component, captures every variant and token binding, and writes a single
`_base.json` that `create-component-md` consumes. Use this tab when the plugin will not install
or does not produce a usable file.
The plugin runs entirely inside Figma Desktop's plugin sandbox. It makes no network calls and stores nothing externally. Once installed, it works offline thereafter.
### Install the plugin
Install it from the Figma Community — no local build required.
Go to [uSpec Extract](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) on the Figma Community.
Click **Open in…** (or **Try it out**) to add it to your Figma. It then appears under **Plugins → uSpec Extract** in any file.
Select a `COMPONENT` or `COMPONENT_SET`, run **Plugins → uSpec Extract**, then paste the
selected component's Figma link. The public plugin remembers the link for later runs in
the same document.
When **Plugins → uSpec Extract** opens the plugin window, the install is complete.
The plugin is open source. To run a modified build, clone [`figma-plugin/`](https://github.com/redongreen/uSpec/tree/main/figma-plugin), run `npm install && npm run build` (Node.js 18+), then import `manifest.json` via **Plugins → Development → Import plugin from manifest…**. Use `npm run build:watch` for an iterative dev loop.
### Plugin issues
**Symptom**: You installed from Community but **Plugins → uSpec Extract** is missing.
**Solutions**:
* Confirm you're signed in to the same Figma account you installed the plugin under. Community plugins are tied to the account that added them.
* Re-open the [Community page](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) and click **Open in…** again to re-add it.
* Restart Figma after installing. Some installs need a full quit (`Cmd+Q` on macOS), not just closing the window.
* Right-click the canvas and check **Plugins → Manage plugins…** to confirm it's listed.
* If you built from source instead, you'll find it under **Plugins → Development → uSpec Extract** — confirm `dist/code.js` and `dist/ui.html` exist next to the manifest, and that you're on Figma Desktop (the Development menu only appears there).
**Symptom**: The plugin shows "Select a component or component set on the canvas" even though something is selected.
**Solutions**:
* Select exactly one node. The plugin requires a single selection.
* The selection must be a `COMPONENT` or `COMPONENT_SET`. Frames, groups, and instances are not accepted. Selecting a single variant inside a component set is fine — the plugin auto-promotes it to the parent set.
* If you're working in a library file, confirm the component hasn't been detached from its master. Detached instances do not register as `COMPONENT` nodes.
* Click **Refresh** in the plugin footer if you changed the selection while the plugin window was open.
**Symptom**: The component preview appears, but **Extract & download** and **Copy JSON**
remain unavailable.
**Solutions**:
* Copy the selected component's Figma URL and paste it into the plugin footer. The public
Community plugin requires a valid file link because it cannot rely on `figma.fileKey`.
* Include the `/design/{fileKey}/...` portion of the URL. A link to a Community listing,
prototype, or unrelated web page is not valid.
* After one successful entry, reopen the plugin in the same document. The saved link should
prefill automatically.
**Symptom**: You click **Extract & download** but nothing lands in `~/Downloads/`.
**Solutions**:
* Check Figma Desktop's permission to download files. macOS may block downloads from sandboxed plugins on first run — look for a permission prompt.
* Try **Copy JSON** instead. If the clipboard copy works, the issue is download-permission related, not extraction itself. Paste the JSON into a file manually and continue.
* Open Figma's plugin developer console (**Plugins → Development → Open console**) and look for an `extract-error` message. The error reason indicates which extraction phase failed.
**Symptom**: The agent runs `uspec-skills component-md prepare` and aborts with a validation FAIL.
**Solutions**:
* Re-run the plugin and re-export. A stale file from a previous plugin version may not match the current schema.
* Confirm the plugin and the skill are on the same uSpec version. If you updated one without the other, the schema can drift. Re-install the plugin from [Community](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) to pick up the latest version (or `git pull` + `npm run build` if you run from source), and run `npx uspec-skills update` to refresh the skills.
* Run the prepare command directly to see the full diagnostic:
```bash theme={null}
npx uspec-skills component-md prepare --base ~/Downloads/your-component-_base.json --json
```
Contributors running from source can also use:
```bash theme={null}
node figma-plugin/scripts/validate-base.mjs ~/Downloads/your-component-_base.json
```
The validator names the failing field and the expected shape.
* The schema reference lives at [`figma-plugin/docs/base-json-schema.md`](https://github.com/redongreen/uSpec/blob/main/figma-plugin/docs/base-json-schema.md).
**Symptom**: The plugin's checklist marks something as **constitutive** that should be **referenced**, or vice versa.
**Solutions**:
* Flip the classification directly in the checklist before clicking **Extract & download**. Your override is recorded in `_base.json._childComposition.children[*].classificationEvidence` as `["user-selected"]`, and the orchestrator trusts user selections without re-asking.
* Non-instance children (vectors, frames, text) are locked to **decorative** and cannot be flipped. If something you expect to be configurable is showing as decorative, the underlying node is not an instance — re-create it as a component instance in Figma.
* For fully accurate classifications across runs, document the convention in your design system: what counts as constitutive vs. referenced for your library.
**Symptom**: The plugin progress indicator stalls for an unusually long time on a large component set.
**Solutions**:
* Components with more than 20 sub-component variants trigger Phase I's variant-walk cap, which slows extraction. The plugin emits a `skipped` marker when the cap is hit; check for those in the resulting `_base.json` and consider documenting oversize sub-components in their own `create-component-md` run.
* Close other open Figma files. The sandbox shares memory across files, and very large libraries can exhaust the budget.
* Restart Figma Desktop and re-run the plugin. A long Figma session sometimes accumulates state that slows plugin execution.
***
## Improving output quality
If the agent's output is incomplete or doesn't match your expectations, the issue is usually missing context rather than a technical problem.
### Output is incomplete or missing states
A render skill can only document what the `.md` records or what you describe. If states, variants, or behaviors are missing, they were usually not captured when you generated the `.md`. Fix it at the source:
* **Add context when generating the `.md`**: list all states (enabled, hovered, pressed, disabled, selected, loading) in the plugin's design-intent field or your `create-component-md` prompt, then regenerate
* **Describe behavioral modes**: fill vs. hug width, truncation rules, multi-select behavior
* **Mention invisible constraints**: tap target minimums, aspect ratios, focus order preferences
### Output seems generic or empty
If the output has the right structure but lacks detail:
* **Check the `.md` is complete**: open the component `.md` and confirm the relevant section is populated. If it's thin, regenerate it with `create-component-md` and more context
* **Check your MCP connection** (render skills only): ask your agent to verify the Figma connection (e.g., *"Check Figma status"* for Console MCP, or *"List pages in my file"* with a link for native MCP). If the connection is down, the agent can't render the frame
* **Verify the render destination**: make sure any destination node-id points to where you want the annotation, not a parent frame
### Re-prompting strategies
When the first output isn't quite right:
1. **Identify what's missing**: Is it a state? A variant? A specific part?
2. **Decide where it belongs**: if the `.md` is missing it, regenerate the `.md`; if only the render is off, re-run the render skill
3. **Be specific**: instead of "include all states," say "include enabled, disabled, and loading states"
If the output has the right structure but rendering fails, the issue is likely a connection problem, not a prompt problem. Check your MCP connection first.
***
## Component structure matters
uSpec reads your component tree programmatically. The cleaner your Figma components are structured, the more accurate the output. A well-organized component gives the agent the information it needs to produce correct specs on the first run.
* Use **auto-layout** for all layout containers
* **Name every layer** descriptively ("Leading icon", "Primary label", "Helper text")
* Use **component sets** with clear variant axis naming
* **Bind colors and dimensions** to design tokens and variables
* Keep your layer hierarchy **flat and purposeful**
* Leave default names like "Frame 427", "Group 12", or "Rectangle 89"
* Use **absolute positioning** where auto-layout would work
* **Nest elements deeply** without purpose (wrapper frames inside wrapper frames)
* Mix unrelated elements in a single **unnamed frame**
* Use **flattened vectors** for elements that should be component instances
Think of it this way: if another designer can't understand your component by reading the layer panel alone, the agent will struggle too. Layer names become table labels, auto-layout informs spacing specs, and token bindings drive color annotations.
***
uSpec is an actively developed open-source project. We're improving the skills, adding new spec types, and refining output quality continuously. If you encounter an issue or have an idea for improvement, open an issue on GitHub — contributions and feedback are welcome.
## Still stuck?
Open an issue on GitHub for questions or bug reports.
Review the setup steps to make sure everything is configured correctly.
# How It Works
Source: https://docs.uspec.design/how-it-works
Understand the uSpec pipeline: extract evidence, compile a canonical component contract and Markdown guide, then render the guide into Figma
uSpec connects your AI agent and Figma into a single pipeline. The **uSpec Extract** plugin captures
a component, `create-component-md` compiles that evidence into canonical `.json` and concise `.md`
artifacts, and the `create-*` skills render sections of the Markdown back into Figma.
## The pipeline
```mermaid theme={null}
flowchart LR
Plugin["uSpec Extract plugin (Figma Community)"] -->|"_base.json"| C["create-component-md"]
C -->|"canonical .json"| Contract["component contract"]
Contract -->|"concise .md"| R["create-* render skills"]
R -->|"annotation frames"| F["Figma"]
```
The JSON contract is the machine source of truth. Its concise Markdown view is the required input
for every `create-*` render skill—there is no path that points a render skill straight at a raw
Figma link.
Canonical JSON for automation and concise Markdown for people, LLM context, code review, and
design iteration.
Annotation frames rendered next to the component by the `create-*` skills, drawn from the `.md`. Best for design reviews, spec handoff inside Figma, and component libraries where the spec lives beside the component.
### Stage 1: compile the contract and `.md`
```mermaid theme={null}
flowchart LR
A[You] -->|"Select component"| Plugin[uSpec Extract Plugin]
Plugin -->|"_base.json"| Skill[create-component-md]
Skill -->|"Prepared evidence"| Cache[".uspec-cache/"]
Cache -->|"Validated semantics"| JSON["components/componentSlug.json"]
JSON -->|"Deterministic render"| MD["components/componentSlug.md"]
```
The plugin runs deterministic extraction inside Figma's sandbox (no network calls), producing a
`_base.json` that captures every variant, token binding, and sub-component. The public Community
build asks for the component link on first use and remembers it for that document.
`create-component-md` prepares compact evidence, interprets four domains, validates obligation
coverage, reconciles disagreements, compiles the canonical JSON, and renders the concise Markdown.
See the [Component Markdown page](/specs/component-md#how-it-works) for the full pipeline.
### Stage 2: render into Figma
```mermaid theme={null}
flowchart LR
A[You] -->|"component .md"| B[Agent Skill]
B -->|"Read .md + render-meta"| Plan[Plan annotations]
Plan -->|"Render"| C[Figma MCP]
C -->|"Documentation frame"| D[Figma Output]
```
Every `create-*` skill reads its section from the component `.md` — plus the render-meta that maps each section to Figma node ids — then renders documentation directly in Figma through the MCP. They do not re-extract the component over MCP; any live read is a small, whitelisted verification or measurement delta. The internal steps differ depending on what each skill renders. The diagrams below show what happens inside each skill.
***
## Triggering a skill
Skills are triggered by typing `@` followed by the skill name in Cursor's chat.
In Cursor's chat, type `@`. Cursor shows an autocomplete menu of available skills.
Continue typing to filter (e.g., `@create-v`) or use arrow keys to select. The skill name must match exactly: `@create-voice`, not `create voice` or `voice spec`.
After the skill name, pass the component `.md` (e.g. `./components/button.md`) and add any context the spec can't carry: which Figma node to render next to, or behaviors and edge cases.
If autocomplete doesn't show the skill, verify your project is open in Cursor and that `.cursor/skills/` is populated. If the directory is empty, run `npx uspec-skills install --platform cursor` from the project root.
Skills are triggered with `/skill-name` or by asking naturally — Claude auto-discovers skills from their description.
Type `/create-voice` to invoke directly, or just describe what you need (e.g., "create a screen reader spec"). Claude matches skills from `.claude/skills/` by their description.
Point the skill at the component `.md` and describe the states, variants, behaviors, or render destination you want documented.
Skills live in `.claude/skills/` under the project where you ran `npx uspec-skills init`. Make sure you launch `claude` from that directory so it can discover them.
Skills are triggered with `$skill-name` or matched implicitly from their description.
Type `$` to mention a skill explicitly (e.g., `$create-voice`), or describe what you need and Codex matches skills from `.agents/skills/` by their `description` frontmatter. Use `/skills` to browse available skills.
Point the skill at the component `.md` and describe the states, variants, behaviors, or render destination you want documented.
Skills live in `.agents/skills/` under the project where you ran `npx uspec-skills init`. Make sure you launch Codex from that directory so it can discover them.
***
## Inside each skill
Every render skill loads an instruction file, reads platform-specific or domain-specific reference files, reads its section from the component `.md` (plus the render-meta node ids), runs through a checklist, and renders the output via the MCP. Any live Figma read is a small, whitelisted verification or measurement delta — not a re-extraction. The reference files determine what the agent knows about each domain. (`create-component-md`, the stage-1 generator, is the exception: it reads a plugin `_base.json` rather than a `.md`.)
The `create-component-md` orchestrator is the only skill that does not render into Figma. It
consumes a plugin-produced `_base.json`, dispatches four interpretation specialists, validates
their evidence obligations, reconciles typed disagreements, compiles canonical JSON, and
renders concise Markdown.
```mermaid theme={null}
flowchart TB
Pre["Prepare evidence + obligations"] --> API["Interpret API (parent, solo)"]
API --> Dict[(api-dictionary.json)]
Dict --> FanOut["Interpret Structure, Color, and Voice in parallel"]
FanOut -->|subagent| Struct[extract-structure]
FanOut -->|subagent| Color[extract-color]
FanOut -->|subagent| Voice[extract-voice]
Struct --> Validate["Validate caches + obligation ledgers"]
Color --> Validate
Voice --> Validate
Validate --> Recon["Typed reconciliation"]
Recon -->|"typed gap + retries available"| SerialRetry["Re-dispatch one owning specialist"]
SerialRetry --> Recon
Recon --> Contract["Compile component.json"]
Contract --> Render["Render concise component.md"]
Contract --> Audit["Render audit view on request"]
```
The API specialist runs first because its property dictionary anchors the downstream specialists
on a shared vocabulary. Structure, Color, and Voice then run in parallel. Validation requires
every prepared obligation and semantic row to resolve to supported evidence. Reconciliation
re-dispatches only the specialist that owns a typed mismatch. Contract compilation and Markdown
assembly are deterministic after the semantic render plan is written.
See the [Component Markdown spec page](/specs/component-md) for install, usage, and output details.
The anatomy skill extracts child layers, element types, and property definitions, then classifies each element's role before rendering numbered markers with an attribute table directly in Figma.
```mermaid theme={null}
flowchart TB
Skill[SKILL.md] --> Instruction[agent-anatomy-instruction.md]
Skill --> MD[component .md]
MD --> Read[Read anatomy section + render-meta]
Instruction --> Classify[Map elements to markers and notes]
Read --> Classify
Classify --> Import[Import and detach template]
Import --> Composition[Render composition markers and table]
Composition --> Children[Per-child sections for eligible instances]
Children --> MCP[Figma MCP]
MCP --> Validate[Screenshot validation]
```
The skill reads child layers, element types, visibility, and property definitions (booleans, variant axes, instance swaps) from the component `.md`. The `.md` already records each element's role (optional slot, fixed sub-component, content element, structural/decorative) and semantic notes from the `create-component-md` run, so the skill maps those onto markers rather than re-classifying. Utility sub-components like Spacer and Divider are automatically skipped. Eligible nested instances get their own per-child sections with separate markers and tables, and cross-references link back from the composition table.
The property skill extracts variant axes, boolean toggles, variable modes, and child component properties, then renders visual exhibits with live instance previews directly in Figma.
```mermaid theme={null}
flowchart TB
Skill[SKILL.md] --> MD[component .md]
MD --> Props[Read properties and variant axes]
MD --> Modes[Read variable mode properties]
MD --> Children[Read child component properties]
Props --> Normalize[Normalize coupled axes and booleans]
Modes --> Normalize
Children --> Normalize
Normalize --> Import[Import and detach template]
Import --> Render[Render exhibits with instance previews]
Render --> MCP[Figma MCP]
MCP --> Validate[Screenshot validation]
```
The skill reads the API and properties sections of the `.md` to recover all variant axes, boolean toggles, and instance swap properties. Variable mode collections (shape, density) are already resolved in the `.md`. Child component properties are rendered in-context on parent instances using live instances placed via the MCP.
The API skill loads its instruction file, identifies all configurable properties (including sub-component slots), and renders property tables with configuration examples directly in Figma.
```mermaid theme={null}
flowchart TB
Skill[SKILL.md] --> Instruction[agent-api-instruction.md]
Skill --> MD[component .md]
Instruction --> Analyze[Analyze properties]
MD --> Props[Read variant properties]
MD --> Booleans[Read boolean properties]
MD --> Slots[Read sub-component slots]
Props --> Analyze
Booleans --> Analyze
Slots --> Analyze
Analyze --> Classify[Classify transient vs persistent]
Classify --> MainTable[Generate main property table]
Analyze --> SubTables[Generate sub-component tables]
MainTable --> Examples[Generate configuration examples]
SubTables --> Examples
Examples --> Checklist[Audit against checklist]
Checklist --> Render[Render in Figma via MCP]
Render --> Validate[Screenshot validation]
```
The API section of the `.md` already lists every variant property, boolean toggle, and sub-component slot. Transient states like hovered and pressed are excluded from the API — they are handled at runtime. Only persistent, configurable properties like `isDisabled` or `isSelected` become API entries.
The structure skill uses a two-tier architecture: deterministic scripts handle data extraction and rendering, while AI reasoning is focused on interpretation and planning.
```mermaid theme={null}
flowchart TB
Skill[SKILL.md] --> Instruction[agent-structure-instruction.md]
Skill --> MD[component .md]
MD --> Read["Read structure section"]
Read --> Dims[Dimensions, tokens, sub-components]
Read --> Compare[Cross-variant deltas]
Dims --> Interpret["AI interpretation"]
Compare --> Interpret
Instruction --> Interpret
Interpret --> Plan[Section plan, notes, anomaly detection]
Plan --> Import[Import and detach template]
Import --> Render["Deterministic render via MCP"]
Render --> Validate[Screenshot validation]
```
The structure section of the `.md` already carries the dimensions, token references, sub-component walks, and cross-variant deltas (measured deterministically during the `create-component-md` run). The skill's reasoning budget is spent on interpretation — building the section plan, writing design-intent notes, and detecting anomalies — rather than data gathering. Values are reported as token references when bound to a variable (e.g., `sizing-button-lg (56)`) or as plain numbers when hardcoded.
The color skill loads a single instruction file, then extracts design tokens and variable values from Figma, classifies which axes and modes affect color, chooses a rendering strategy, and renders the annotation directly in Figma.
```mermaid theme={null}
flowchart TB
Skill[SKILL.md] --> Instruction[agent-color-instruction.md]
Skill --> MD[component .md]
Instruction --> Analyze[Analyze color usage]
MD --> Tokens[Read design tokens]
MD --> Variables[Read variable values]
MD --> Styles[Read styles]
Tokens --> ClassifyAxes[Classify color-relevant axes]
Variables --> ClassifyAxes
Styles --> ClassifyAxes
ClassifyAxes --> DetectModes[Read variable mode collections]
DetectModes --> Strategy{Strategy A or B?}
Strategy -->|"6 or fewer sections"| StratA[Strategy A: one section per variant]
Strategy -->|"More than 6 sections"| StratB[Strategy B: states as columns]
Analyze --> Strategy
StratA --> Checklist[Audit against checklist]
StratB --> Checklist
Checklist --> Render[Render in Figma via MCP]
Render --> Validate[Screenshot validation]
```
The color section of the `.md` records per-element token mappings using your actual token naming conventions rather than generic names. Because `create-component-md` enables hidden boolean toggles during extraction, the `.md` already captures color bindings that only appear when optional elements are visible. The strategy decision determines the output layout: Strategy A renders one section per variant for simpler components, while Strategy B uses states as table columns for components with many variant combinations.
The screen reader skill loads four reference files, one for general instructions and one per platform, then runs a merge analysis to determine focus stops before rendering per-platform tables directly in Figma.
```mermaid theme={null}
flowchart TB
Skill[SKILL.md] --> Instruction[agent-screenreader-instruction.md]
Skill --> VO[voiceover.md]
Skill --> TB[talkback.md]
Skill --> AR[aria.md]
Instruction --> MD[component .md]
MD --> Read[Read voice section + structure]
Read --> Merge[Merge analysis]
Merge --> Focus[Identify focus stops]
VO --> Gen[Generate platform tables]
TB --> Gen
AR --> Gen
Focus --> Gen
Gen --> Checklist[Audit against checklist]
Checklist --> Render[Render in Figma via MCP]
Render --> Validate[Screenshot validation]
```
The voice section of the `.md` already records the focus order and merge analysis — which visual parts become independent focus stops and which get merged into a parent announcement. The three platform files provide the exact property names and announcement patterns for iOS, Android, and Web.
The motion skill is unique: instead of extracting data from Figma, it reads pre-computed animation data exported from After Effects. The `export-timeline.jsx` script does the heavy lifting — pairing keyframes into segments, computing cubic-bezier easing curves, and filtering out static segments. The agent reads the segments directly and renders them as a timeline visualization in Figma.
```mermaid theme={null}
flowchart TB
AE[After Effects] -->|"Run export-timeline.jsx"| JSON[JSON on clipboard]
JSON -->|Paste or file ref| Skill[SKILL.md]
Skill --> Instruction[agent-motion-instruction.md]
Skill --> MCP[Figma MCP]
Instruction --> Parse[Parse and validate JSON]
JSON --> Parse
Parse --> Layout[Compute track width and tick spacing]
Layout --> Import[Import and detach template]
Import --> Ruler[Render time ruler]
Ruler --> Timeline[Render timeline layers and bars]
Timeline --> Table[Render detail table rows]
Table --> Validate[Screenshot validation]
```
This is a two-step process: first run the export script in After Effects to get the JSON, then run the `create-motion` skill with that output. The JSON contains composition metadata (name, duration, fps, dimensions) and a flat array of layers, each with pre-computed segments containing timing, values, bar labels, and easing data. The agent computes only layout values (track width, pixels per millisecond) and passes everything else through to Figma.
***
## What the pipeline captures vs. what you provide
The uSpec Extract plugin and `create-component-md` capture structure, tokens, and styles into the `.md` automatically. But some information only exists in your head — add it in the plugin's design-intent field or in your prompt:
| The pipeline captures | You need to describe |
| ------------------------------ | ------------------------------------------- |
| Component layers and hierarchy | States not visible in the captured variants |
| Design token names and values | Behavioral modes (fill vs. hug, truncation) |
| Variant axes and properties | Focus order preferences |
| Visual dimensions and spacing | Platform-specific interaction details |
| Styles and color values | Business logic or conditional rules |
The more context you provide when generating the `.md`, the more accurate every downstream render is. A one-line prompt works, but adding states, behaviors, and edge cases produces significantly better specs.
***
## Architecture overview
```mermaid theme={null}
flowchart TB
subgraph Host["Agent Host (Cursor / Claude Code / Codex)"]
direction TB
Prompt[Your prompt]
MD[component .md]
Skill[Agent skill + reference files]
Agent[AI agent]
Prompt --> Skill
MD --> Skill
Skill --> Agent
end
subgraph Figma["Figma"]
direction TB
File[Figma file]
Output[Documentation frames]
end
subgraph MCP["Figma MCP"]
direction TB
Console["Console MCP + Desktop Bridge"]
Native["Native Figma MCP"]
end
Agent -->|"Render documentation"| MCP
Agent <-->|"Verify + small whitelisted reads"| MCP
MCP <-->|Read + write| File
File --> Output
```
The component data, tokens, and styles a render skill needs come from the `.md` — not a live MCP extraction. The MCP is the render channel back into Figma, plus the occasional small whitelisted read for verification or a measurement delta. uSpec supports two Figma MCP providers — choose the one that fits your setup:
* **Figma Console MCP** (by Southleft) connects via a Desktop Bridge plugin running inside Figma Desktop, communicating over WebSocket. It exposes 59+ tools for design creation and variable management.
* **Native Figma MCP** (by Figma) connects directly to Figma's API with read and write access. No Desktop Bridge plugin required.
Both providers let the agent render annotation frames into Figma and capture screenshots for validation. Every render skill draws through the MCP, regardless of which provider or host you use. See [Getting Started](/getting-started#2-set-up-figma-mcp) for setup instructions.
MCP providers update their capabilities and setup instructions frequently. For the latest details, see the [Figma Console MCP docs](https://docs.figma-console-mcp.southleft.com/) or the [native Figma MCP docs](https://github.com/figma/figma-mcp).
# Introduction
Source: https://docs.uspec.design/index
Generate a canonical component contract and portable implementation guide, then render the guide into Figma as annotation frames.
**uSpec starts with the uSpec Extract plugin.** The plugin captures deterministic evidence;
`create-component-md` compiles it into canonical `.json` and concise `.md` artifacts. This saves
thousands of tokens per run and captures more component detail than live extraction.
[See the Component Markdown guide →](/specs/component-md)
uSpec turns your Figma components into structured documentation from your AI agent. The **uSpec Extract** plugin captures your component, `create-component-md` compiles a canonical `.json` contract and portable `.md` implementation guide, and the `create-*` skills render that guide into Figma as annotation frames.
Works with **Cursor**, **Claude Code**, and **Codex**.
## Start here: Component Markdown
A schema-valid `.json` contract plus concise `.md` for every component. Both cover API,
structure, color, and screen-reader behavior.
## Render into Figma
Once you have a component `.md`, the `create-*` skills render annotation frames directly into your Figma file, next to the component. They read from the `.md` you generated — they no longer re-extract from a Figma link.
Numbered markers and attribute tables for every element
Properties, values, defaults, and configuration examples
Variant axes, boolean toggles, and variable mode exhibits
Design token mapping for every element and state
Dimensions, spacing, and padding across density and size variants
VoiceOver, TalkBack, and ARIA accessibility specs
Animation timeline bars and easing details from After Effects
## How it works
Every spec flows through one pipeline, with the component contract and its Markdown view at the
center:
Run the **uSpec Extract** Figma plugin on your component to produce a `_base.json` capture of
every variant, token binding, and sub-component. The public plugin asks for the component link
on first use and remembers it for that document.
Run `create-component-md` against the `_base.json`. It interprets API, Structure, Color, and
Voice evidence, validates their obligations, then writes canonical `.json` and concise `.md`
artifacts.
Point any `create-*` skill at the `.md` to render that section as annotation frames next to the component. These skills read from the `.md`; they do not re-extract from Figma.
`create-motion` is the one exception: it renders a timeline from an After Effects export and does not use the Component Markdown pipeline.
## Get started
Set up your AI agent, Figma MCP, and your template library.
Prompt format, available skills, and tips for better output.
# Anatomy
Source: https://docs.uspec.design/specs/anatomy
Generate numbered anatomy annotations with attribute tables directly in Figma
The anatomy skill documents a component's internal structure — every element gets a numbered marker and an entry in an attribute table.
`create-anatomy` now renders **from the [Component Markdown](/specs/component-md) source of truth**. Run `create-component-md` first to produce `components/.md`; this skill seeds the component's identity from the `.md`'s `render-meta` block and renders the Figma frame. It no longer re-extracts from Figma, and it fails fast if the `.md` is missing.
## What you get
Pink dots with connector lines pointing to each element in the component instance.
A 4-column table with element number, type indicator (instance or text), element name, and semantic notes describing each element's role.
The skill also generates per-child sections for nested component instances, annotating their internal elements separately. Utility sub-components like Spacer and Divider are automatically skipped.
## What you need
* A **component `.md`** produced by `create-component-md` (run it first — `create-component-md` needs a `_base.json` from the uSpec Extract plugin). Tell the skill where this `.md` lives — `components/.md` is only `create-component-md`'s default output path; the file can live anywhere. Without it this skill aborts.
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP) — used only to render the frame.
* Context about the component is captured upstream by `create-component-md`; nothing extra is needed here.
Anatomy has no dedicated body section in the `.md`. It seeds the component's identity from the `.md`'s `render-meta` block, then runs a bounded minimal child/variant walk only to position markers and confirm live layer geometry.
## How to use
Reference the skill and pass the component `.md`. Add a render destination or any extra context the spec can't carry:
```
@create-anatomy ./components/text-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
/create-anatomy ./components/text-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
$create-anatomy ./components/text-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
To place the annotation in a different file or page, add a destination link to your prompt:
`Destination: https://www.figma.com/design/xyz789/Docs?node-id=0-1`
## What it generates
| Output | Description |
| ------------------ | ---------------------------------------------------------------------------------------- |
| Component instance | Default variant rendered in the artwork area with all hidden elements made visible |
| Numbered markers | Pink dots with connector lines pointing to each element |
| Attribute table | 4-column table: number, type indicator (instance/text), element name, and semantic notes |
| Per-child sections | Nested component instances annotated with their own markers and tables |
| Cross-references | Composition table notes link to per-child sections ("See X anatomy section") |
Hidden elements are made visible in the artwork using property-aware unhide (boolean toggles are set via component properties rather than blanket visibility overrides) and labeled "(hidden)" in the table, so no structural information is lost.
In per-child sections, consecutive identical elements are collapsed into a single row with an (xN) suffix, so a row of five star icons becomes "Star (x5)" instead of five separate rows.
## How it works
The anatomy skill consumes the Component Markdown source of truth: element classification, semantic notes, and per-child section decisions were already made by `create-component-md`, so deterministic scripts render markers and tables from the `.md` while AI reasoning is limited to resolving the seeded model onto live layers.
50% Deterministic 50% AI Reasoning
```mermaid theme={null}
flowchart LR
A[You] -->|run create-component-md| M["components/<slug>.md"]
M -->|render-meta| B[create-anatomy Skill]
B -->|Render| C[Figma MCP]
C -->|Annotation frame| D[Figma Output]
```
The skill requires `components/.md` (produced by `create-component-md`) and fails fast if it is missing — it does not re-extract from Figma.
Anatomy has no dedicated body section, so the skill seeds the component's identity — child layers, element types, visibility, and property definitions (booleans, variant axes, instance swaps) — from the `.md`'s `render-meta` block, then runs a bounded minimal child/variant walk only to confirm live layer geometry.
Element roles, semantic notes, and per-child section decisions are assembled directly from the seeded model and `render-meta` — no full extraction walk.
The anatomy documentation template is imported from the library, instantiated, and detached into an editable frame.
The skill fills header fields, creates a default component instance with hidden elements made visible, positions numbered markers on each element by name-match + live bbox, and builds the attribute table. Per-child sections are created for eligible sub-components.
A screenshot is captured and checked for completeness. Issues are fixed automatically for up to 3 iterations.
The skill renders programmatically, so the output is consistent and repeatable. Running it on the same component produces identical results.
## Tips for better output
* **Use component sets**: The skill expects a component set (the dashed-border container in Figma) or a standalone component, not an instance
* **Name your layers**: Layer names become the element labels in the attribute table. Descriptive names like "Leading icon" produce better documentation than "Frame 47"
* **Hidden elements matter**: Hidden children represent toggleable boolean properties. They are included in the anatomy and labeled "(hidden)" so the full structure is documented
* **Utility sub-components are skipped**: Components like Spacer, Divider, and Separator don't get per-child sections since they have no meaningful internal structure to annotate
* **Semantic notes are automatic**: The agent classifies each element's role and writes context-aware descriptions. Notes explain whether an element is optional (and which boolean controls it), swappable, or always present
# API
Source: https://docs.uspec.design/specs/api
Generate component property documentation with configuration examples
API specs document all configurable properties for a component: values, defaults, required vs. optional, and usage examples. This gives engineers a clear reference for implementing the component.
`create-api` now renders **from the [Component Markdown](/specs/component-md) source of truth**. Run `create-component-md` first to produce `components/.md`; this skill reads its API section + `render-meta` and renders the Figma frame. It no longer re-extracts from Figma, and it fails fast if the `.md` is missing.
## What you need
* A **component `.md`** produced by `create-component-md` (run it first — `create-component-md` needs a `_base.json` from the uSpec Extract plugin). Tell the skill where this `.md` lives — `components/.md` is only `create-component-md`'s default output path; the file can live anywhere. Without it this skill aborts.
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP) — used only to render the frame.
* Context about properties, accepted values, or nested component configurations is captured upstream by `create-component-md`; nothing extra is needed here.
Mention which properties are required, what the defaults are, and any sub-components that have their own configuration (e.g., a trailing button inside a section heading).
## How to use
Reference the skill and pass the component `.md`. Add a render destination or any extra context the spec can't carry:
```
@create-api ./components/section-heading.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
/create-api ./components/section-heading.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
$create-api ./components/section-heading.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
## What it generates
The agent inspects your component's variant axes, boolean toggles, content slots, and variable modes, then renders a documentation frame in your Figma file:
| Section | What it covers |
| ---------------------- | --------------------------------------------------------------------------------- |
| Main property table | All top-level properties with values, required status, defaults, and notes |
| Sub-component tables | Separate tables for configurable nested elements (e.g., trailing content options) |
| Configuration examples | 1–4 examples showing common setups |
The agent looks at three sources in Figma to find all configurable properties:
* **Variant axes**: properties visible in variant names (size, type, state)
* **Instance properties**: boolean toggles and content options only visible when inspecting a single instance
* **Variable modes**: properties controlled at the container level (shape, density)
Transient interactive states like hovered and pressed are not included as API properties. Those are handled at runtime by the platform. Only persistent states like disabled, selected, and loading appear as properties.
## How it works
The API skill consumes the Component Markdown source of truth: property classification, required vs. optional status, descriptions, and configuration examples were already decided by `create-component-md`, so deterministic scripts render the tables and examples directly from the `.md`.
25% Deterministic 75% AI Reasoning
```mermaid theme={null}
flowchart LR
A[You] -->|run create-component-md| M["components/<slug>.md"]
M -->|API section + render-meta| B[create-api Skill]
B -->|Render| C[Figma MCP]
C -->|Annotation frame| D[Figma Output]
```
The skill requires `components/.md` (produced by `create-component-md`) and fails fast if it is missing — it does not re-extract from Figma.
The skill parses the `.md`'s API section (main property table, sub-component tables, configuration examples) plus the `render-meta` block, which carries property defs, boolean defs, variant axes, slot contents, and sub-component identities.
Property tables, sub-component tables, and configuration examples are assembled directly from the parsed `.md` and `render-meta` — no live extraction walk. The one whitelisted live read is a bounded `<=30-line` TEXT-node listing on the instance, used only to source preview text for the configuration examples.
The API documentation template is imported from the library, instantiated, and detached into an editable frame.
The skill fills header fields, builds property tables, sub-component tables, and configuration examples, resolving each preview against the instance by name-match.
A screenshot is captured and checked for completeness. Issues are fixed automatically for up to 3 iterations.
The skill renders programmatically, so the output is consistent and repeatable. Running it on the same component produces identical results.
## Tips for better output
* **Describe content slots with multiple options**: if a slot can contain different content types (icon, avatar, image, none), list them explicitly. For example: *"leading content can be an icon, avatar, or image"*
* **Note required vs. optional**: mention which properties must always be set and which have defaults
* **Mention sub-components**: if your component has configurable nested elements (e.g., a trailing button inside a section heading), describe their configuration options
* **Specify defaults**: tell the agent which values are the default configuration
* **Distinguish persistent from transient states**: mention states like `disabled`, `selected`, or `loading` that should become properties. Transient states like hovered and pressed are handled at runtime and won't appear in the API
# Color Annotation
Source: https://docs.uspec.design/specs/color
Generate design token specifications mapping UI elements to color tokens
Color annotation specs document which design tokens are used for backgrounds, text, icons, and state layers across different component states and variants.
`create-color` now renders **from the [Component Markdown](/specs/component-md) source of truth**. Run `create-component-md` first to produce `components/.md`; this skill reads its Color section + `render-meta` and renders the Figma frame. It no longer re-extracts from Figma, and it fails fast if the `.md` is missing.
## What you need
* A **component `.md`** produced by `create-component-md` (run it first — `create-component-md` needs a `_base.json` from the uSpec Extract plugin). Tell the skill where this `.md` lives — `components/.md` is only `create-component-md`'s default output path; the file can live anywhere. Without it this skill aborts.
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP) — used only to render the frame.
* Context about variants, states, or color modes is captured upstream by `create-component-md`; nothing extra is needed here.
If your component uses Figma variable modes for color variants (e.g., a "Tag color" collection with Default, Success, Warning modes), mention it in your prompt. The agent checks for these automatically, but calling them out helps.
## How to use
Reference the skill and pass the component `.md`. Add a render destination or any extra context the spec can't carry:
```
@create-color ./components/button.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
/create-color ./components/button.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
$create-color ./components/button.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
## What it generates
The agent inspects your component's fills, strokes, and variables, then maps every color-bearing element to its design token and renders the documentation directly in your Figma file.
### How the output is organized
The structure depends on your component type:
Components without interactive states (headers, cards, labels) get a single table mapping each element to its token.
Components with states (buttons, checkboxes, inputs) get a separate table per state showing how tokens change across enabled, hovered, pressed, and disabled.
Components with style or color variants (default + danger, primary + secondary) get separate variant sections, each with their own state tables.
Components where color is controlled by a Figma variable collection (tag colors, badge styles, emphasis levels) get one section per mode value.
Light and dark themes don't need separate documentation. Semantic tokens handle theme switching automatically.
## How it works
The color skill consumes the Component Markdown source of truth: token mapping, state tables, variant organization, and variable-mode sections were already decided by `create-component-md`, so deterministic scripts render directly from the `.md` while AI reasoning is limited to resolving the parsed spec onto live Figma layers.
55% Deterministic 45% AI Reasoning
```mermaid theme={null}
flowchart LR
A[You] -->|run create-component-md| M["components/<slug>.md"]
M -->|Color section + render-meta| B[create-color Skill]
B -->|Render| C[Figma MCP]
C -->|Annotation frame| D[Figma Output]
```
The skill requires `components/.md` (produced by `create-component-md`) and fails fast if it is missing — it does not re-extract from Figma.
The skill parses the `.md`'s Color section (per-element token mappings, per-state and per-variant tables, variable-mode sections) plus the `render-meta` block, which resolves sections and layers back to live Figma layer ids.
State tables, variant sections, and variable-mode sections are assembled directly from the parsed `.md` — no live extraction walk. The single whitelisted live read is `getLocalVariableCollectionsAsync()`, used only to render mode previews for variable-mode sections.
The color documentation template is imported from the library, instantiated, and detached into an editable frame.
The skill fills header fields, builds state tables, variant sections, and variable mode sections, locating each target by `render-meta` layer id with a name-match fallback on the rendered instance.
A screenshot is captured and checked for completeness. Issues are fixed automatically for up to 3 iterations.
The skill renders programmatically, so the output is consistent and repeatable. Running it on the same component produces identical results.
## Tips for better output
* **List all states**: enabled, hovered, pressed, disabled. The agent maps tokens per state
* **Mention color variants**: if your component has Default and Danger (or similar), describe both
* **Call out variable mode collections**: if color is controlled by a Figma variable collection (e.g., *"Tag color"* with Default, Success, Warning, Error modes), name the collection and its modes in your prompt. The agent checks for these automatically, but explicit mention ensures nothing is missed
* **Note sub-components**: if your component contains another component (e.g., a Button inside a Section heading), the agent references it instead of duplicating its tokens
# Component.MD
Source: https://docs.uspec.design/specs/component-md
Turn a Figma component into a canonical JSON contract and concise Markdown implementation guide
`create-component-md` produces a canonical JSON contract and a sibling Markdown implementation
guide for each component, covering API, structure, color, and screen-reader behavior. LLM tools and
automation can consume the JSON; humans can query the concise `.md`. The other uSpec skills render
sections of that specification back into Figma.
The `.md` output works with any LLM workflow: Claude in Cursor, Claude Design, GPT agents, Gemini,
local models, and anything else that reads Markdown. Use the canonical `.json` when you need a
validated machine contract.
## What it generates
Each run writes two tracked artifacts:
* `components/{componentSlug}.json` — the canonical, schema-valid machine contract
* `components/{componentSlug}.md` — the concise implementation guide rendered from that contract
Pass `--view audit` to the renderer when you need an exhaustive
`components/{componentSlug}.audit.md` diagnostic companion.
The concise Markdown contains five sections:
| Section | Content |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| Overview | Component name, variant axes summary, and composition (constitutive and referenced children) |
| API | Properties, values, defaults, required vs. optional, sub-component tables, and configuration examples |
| Structure | An Anatomy layer tree at the top, then dimensions, spacing, padding, and sub-component variant walks across every size and density |
| Color | Per-element token mapping for fills, strokes, and effects across every variant |
| Voice / Screen reader | Focus order, merge analysis, and platform tables for VoiceOver, TalkBack, and ARIA |
A Provenance block records the source identity and evidence coverage so every claim is traceable
back to the extraction without exposing pipeline internals in the human-readable body.
## What you need
This skill runs in two steps: extract, then generate. You need both pieces set up once.
The plugin produces a `_base.json` file that captures every variant, token binding, and sub-component in one pass. It is published on the Figma Community, so there is no local build.
Go to [uSpec Extract](https://www.figma.com/community/plugin/1635184425006534227/uspec-extract) on the Figma Community.
Click **Open in…** (or **Try it out**) to add it to your Figma. It then appears under **Plugins → uSpec Extract** in any file.
The plugin runs entirely inside Figma's plugin sandbox. No network calls, no account required, nothing leaves your machine.
The public Community plugin requires the selected component's Figma link because public
plugins cannot rely on the file key API. Paste it on the first run; the plugin remembers it
for later runs in the same document.
The plugin is open source. If you want to read or modify the source, it lives in [`figma-plugin/`](https://github.com/redongreen/uSpec/tree/main/figma-plugin); the [troubleshooting guide](/help/troubleshooting) covers building from source and common failure modes.
You also need the `create-component-md` skill. From your project root, run `npx uspec-skills init` and choose your agent host (Cursor, Claude Code, or Codex). The CLI installs every skill — including `create-component-md` — into the platform-specific directory. If you have not set up your agent host yet, follow [Getting Started](/getting-started). Generating the `.md` does not require Figma MCP setup or `firstrun` — those are only needed for the `create-*` skills that render the `.md` back into Figma.
## How to use
This skill uses parallel agents and runs the equivalent of four specs in one pass. We recommend running it on **Opus 4.7 High** or better. A typical run costs **50k–200k tokens** depending on component complexity. Start a fresh agent session for each run so the model has full context capacity.
In Figma:
1. Select a single `COMPONENT` or `COMPONENT_SET`. Selecting a variant auto-promotes to its component set.
2. Run **Plugins → uSpec Extract** (or **Plugins → Development → uSpec Extract** if you dev-installed).
3. Paste the selected component's Figma link into the footer.
4. Review the sub-component checklist. The plugin pre-guesses whether each child is **constitutive** (owned by this component) or **referenced** (an instance of a widely-reused component). Flip any guess you disagree with.
5. Optionally paste design intent, open questions, or constraints into the text area.
6. Click **Extract & download** to save `{componentSlug}-_base.json` to `~/Downloads/`, or **Copy JSON** to put the full payload on your clipboard.
In your agent host, point the skill at the downloaded file:
```
@create-component-md baseJsonPath=~/Downloads/text-field-_base.json
```
```
/create-component-md baseJsonPath=~/Downloads/text-field-_base.json
```
```
$create-component-md baseJsonPath=~/Downloads/text-field-_base.json
```
The agent validates the extraction, runs four interpretation passes, reconciles their outputs,
compiles the canonical contract, and writes `./components/{componentSlug}.json` plus
`./components/{componentSlug}.md`.
When the run finishes, sibling `.json` and `.md` files appear under `./components/` (for example,
`components/text-field.json` and `components/text-field.md`). Open the Markdown to verify the five
sections, then keep both files together in version control.
### Optional: pair with a Figma link
If you pass a Figma URL alongside the JSON, the agent can run a targeted measurement delta when a sub-skill flags a gap:
```
@create-component-md baseJsonPath=~/Downloads/text-field-_base.json figmaLink=https://www.figma.com/design/abc123/…
```
This is rarely needed. The plugin captures everything required for a complete spec on its own.
## How it works
The pipeline separates measured evidence, AI interpretation, and deterministic compilation. This
keeps semantic judgment where it is useful while making validation and final rendering repeatable.
Deterministic evidence Parallel interpretation Validated contract
```mermaid theme={null}
flowchart TB
Prepare["Prepare: validate, stage, slice evidence"] --> API["Interpret API + shared dictionary"]
API --> FanOut["Interpret Structure, Color, and Voice in parallel"]
FanOut --> Validate["Validate caches + evidence obligations"]
Validate --> Recon["Reconcile typed disagreements"]
Recon --> Plan["Write small semantic render plan"]
Plan --> Contract["Compile canonical component JSON"]
Contract --> Concise["Render concise Markdown"]
Contract --> Audit["Render audit Markdown on request"]
```
`component-md prepare` validates `_base.json`, stages it under
`.uspec-cache/{componentSlug}/`, and writes a manifest plus API, Structure, Color, Voice, and
renderer evidence slices. Each slice includes obligations that identify facts the specialist
must account for.
`extract-api` builds the shared property dictionary first. Structure, Color, and Voice then run
in parallel against their compact evidence slices and the same vocabulary.
`component-md validate` checks each specialist cache, its obligation ledger, source identity,
semantic row support, and output targets. The orchestrator then compares the domains for typed
disagreements and can retry only the specialist that owns a mismatch.
The parent writes a small semantic render plan containing the overview and confidence summary.
`component-md contract` combines that plan with validated caches into
`components/{componentSlug}.json`.
`component-md render` mechanically produces the concise implementation guide from the contract
and runs acceptance gates over every domain. Use `--view audit` when you need exhaustive
evidence, provenance, and target diagnostics.
Given the same extraction, validated specialist caches, and render plan, contract compilation and
Markdown rendering are deterministic. Diffs in those artifacts reflect source or interpretation
changes rather than formatting drift.
## Using the output with LLMs
The generated `.md` is self-contained for human and LLM implementation work. Hand it to any LLM
as context and ask it to:
* Implement the component in React, SwiftUI, Jetpack Compose, or your platform of choice.
* Generate unit tests that cover every documented state and variant.
* Write platform-specific accessibility code from the Voice section tables.
* Build a Storybook file with one story per variant axis value.
* Create a design-review checklist from the Known gaps block.
The spec names every property, every token, and every dimension directly, so the downstream LLM does not need to read Figma or guess at intent.
Commit the generated `.json` and `.md` together alongside the component code. When the component
changes in Figma, re-run the extractor and the skill, then diff both artifacts to see what changed.
## What the plugin captures
The extractor walks every variant and resolves every binding, which is what makes the `.md` pixel-perfect:
* **Every variant.** No default-variant sampling. Cross-variant diffs and axis classification are computed inside the plugin sandbox.
* **Variant-complete composition.** Child instances carry exact per-variant presence and placement
metadata, including children that only exist outside the default variant.
* **Distinct revealed topologies.** Every structural topology gets a populated revealed-tree
representative, so state- or variant-specific anatomy remains available downstream.
* **Library-linked variables** with name, `codeSyntax`, alias chains, and remote collection metadata.
* **Inline font properties** alongside text style IDs, so typography survives when a library style cannot be resolved.
* **Sub-components walked across their own variant axes.** A Button inside a Text Field is measured across its own size and density variants, not only the configuration the parent embeds.
* **Designer-in-the-loop classification.** You confirm or flip whether each top-level child is constitutive, referenced, or decorative before extraction runs.
See the [plugin schema reference](https://github.com/redongreen/uSpec/blob/main/figma-plugin/docs/base-json-schema.md) for the complete `_base.json` contract.
## Tips for better output
* **Use Opus 4.7 High or better.** Lower-capacity models may truncate mid-reconciliation and leave one of the four sections incomplete.
* **Start a fresh agent session for every run.** Accumulated history reduces available context. This skill uses parallel subagents and works best with a clean session.
* **Review the plugin's sub-component checklist carefully.** The downstream spec inherits your classifications. Getting constitutive vs referenced right saves reconciliation cycles.
* **Add design intent in the plugin's text area** when a component has behavior that is not visible in the static design: focus-order intent, conditional states, or platform-specific variants.
* **Run the plugin on the component set**, not a single variant. The plugin auto-promotes selected variants to their set, but starting from the set makes the axes explicit.
* **Diff the `.md` between runs.** After a design change, re-extract and re-generate. The resulting diff is a clean record of what changed semantically, not just pixel-wise.
## Troubleshooting
The accordions below cover issues with the generated `.md` itself. For plugin install or runtime issues — Figma can't find the plugin, the canvas selection is rejected, the export produces no file — see the [Figma Extract plugin troubleshooting tab](/help/troubleshooting).
The plugin output failed Ajv schema validation during the CLI prepare stage.
* Confirm the plugin version matches the skill version. If you updated one without the other, the schema can drift.
* Re-run the plugin and try again.
* Run the prepare command directly to see the full diagnostic:
```bash theme={null}
npx uspec-skills component-md prepare --base ~/Downloads/your-component-_base.json --json
```
Contributors running from source can also use:
```bash theme={null}
node figma-plugin/scripts/validate-base.mjs ~/Downloads/your-component-_base.json
```
The structure section renders `—` when the plugin could not measure a sub-component variant.
* Confirm the sub-component checklist in the plugin marks the missing child as **constitutive**. Referenced children intentionally skip deep measurement.
* If the sub-component has more than 20 variant combinations, the extractor caps the walk and emits a `skipped` marker. For very large sub-components, document them in their own `create-component-md` run and reference the resulting file.
A specialist may have hit a reconciliation budget limit.
* Check the Known gaps block at the top of the `.md`. Unresolved reconciliation items are listed there.
* Re-run on a higher-capacity model, or re-run with `reconciliation.autoRetry` set to `true` in `uspecs.config.json`.
Very complex components (many variants, many sub-components, or large property matrices) can exceed the typical range.
* Break the component into smaller units and spec them separately.
* For compound components, spec the parent and reference the children rather than re-specifying each child inline.
## Related
Install your agent host (Cursor, Claude Code, or Codex). Generating the `.md` skips MCP and template library setup.
See the uSpec pipeline and where this skill fits as the source of truth.
Install and recovery instructions for the uSpec Extract plugin.
Render VoiceOver, TalkBack, and ARIA tables directly into Figma.
# Motion
Source: https://docs.uspec.design/specs/motion
Generate motion specification annotations from After Effects timeline data directly in Figma
The motion skill documents a component's animation behavior — every animated property gets a timeline bar and an entry in a detail table showing easing, duration, and value transitions.
The motion spec currently only supports extraction from **After Effects**. Unlike other skills that work directly from a Figma link, this is a **two-step process**: first run the export script in After Effects to get the JSON data, then run the skill with that output.
**Motion is outside the Component Markdown pipeline.** The other `create-*` skills now consume `components/.md` (produced by `create-component-md`) and render from its `render-meta`. `create-motion` is the one exception: its input is an After Effects timeline export, not a Figma component walk, so there is no `_base.json`, no `extract-motion` interpreter, and no Motion section in the `.md` to consume. It stays a standalone Figma renderer driven by the AE JSON.
## What you get
Color-coded bars for each animated property, positioned on a time ruler. Blue for Bezier easing, green for Linear, and teal for Hold.
A 7-column table with element, property, from/to values, duration, delay, and easing curve for every animation segment.
Millisecond tick marks aligned to the timeline bars, scaled to the composition duration.
Component name, duration, frame rate, and dimensions at the top of the annotation.
Bar labels show value transitions (e.g., "0% -> 115%") while easing type is communicated through bar color and detailed in the table. A color legend at the bottom maps Bezier, Linear, and Hold to their bar colors.
## What you need
* **After Effects** with the composition open
* The **`export-timeline.jsx`** script (included in the `motion/` folder)
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP)
* Optionally, a **Figma destination link** to place the annotation on a specific page
## How to use
Open your composition in After Effects and run the export script:
**File > Scripts > Run Script** and select `motion/export-timeline.jsx`
The script extracts all animated properties, computes easing curves, filters out static segments, and copies the result to your clipboard as JSON.
Make sure **"Allow Scripts to Write Files and Access Network"** is enabled in After Effects preferences under Scripting & Expressions.
Reference the `create-motion` skill, provide the JSON data (pasted directly or as a file reference), and include a Figma link to the destination page:
```
@create-motion
https://www.figma.com/design/abc123/Specs?node-id=0-1
```
Or with a file reference:
```
@create-motion @motion-data.json
https://www.figma.com/design/abc123/Specs?node-id=0-1
```
```
/create-motion
https://www.figma.com/design/abc123/Specs?node-id=0-1
```
```
$create-motion
https://www.figma.com/design/abc123/Specs?node-id=0-1
```
## What it generates
| Output | Description |
| ------------------ | ------------------------------------------------------------------------------------------- |
| Composition header | Component name, "Motion Specification" label, and metadata (duration, fps, dimensions) |
| Time ruler | Tick marks at regular intervals scaled to the composition duration |
| Timeline layers | One row per animated layer, with sub-rows for each property (Scale, Opacity, etc.) |
| Timeline bars | Color-coded bars positioned on the time axis, labeled with value transitions |
| Color legend | Bezier, Linear, and Hold easing types mapped to their bar colors |
| Detail table | One row per animation segment with element, property, from, to, duration, delay, and easing |
Only layers with actual animation are included. The export script filters out segments where values don't change, so the output shows only meaningful transitions.
## How it works
The motion skill is primarily deterministic — the After Effects export script pre-computes all timing data, and rendering scripts handle layout and table generation, with AI reasoning limited to validation and error recovery.
75% Deterministic 25% AI Reasoning
```mermaid theme={null}
flowchart LR
AE[After Effects] -->|"export-timeline.jsx"| JSON[JSON data]
JSON -->|Paste or file ref| Skill[Agent Skill]
Skill -->|Render| MCP[Figma MCP]
MCP -->|Annotation frame| Figma[Figma Output]
```
The `export-timeline.jsx` script walks every layer in the active composition, pairs keyframes into segments, computes cubic-bezier easing values, formats display labels, and filters out no-change segments. The output is self-contained JSON with all display values pre-computed.
The agent validates the JSON structure: composition metadata, layer array, property segments, and required fields like `startMs`, `durationMs`, `barLabel`, and `easingType`.
Track width and tick spacing are computed from the composition duration. The time ruler and all track areas are resized to match.
The motion documentation template is imported from the library, instantiated, and detached into an editable frame.
For each animated layer, the skill clones a layer template, sets the layer name, then clones property rows with positioned and colored bars. Bar positions are computed from the pre-computed segment timing data.
One row is cloned per animation segment, filling in element name, property, from/to values, duration, delay, and easing curve.
A screenshot is captured and checked for completeness. Issues are fixed automatically for up to 3 iterations.
Unlike other skills that extract data from Figma, the motion skill reads pre-computed data from After Effects. The export script does all the heavy lifting — pairing keyframes, computing easing curves, and formatting labels. The agent reads the segments directly and only computes layout values.
## Tips for better output
* **Name your layers in After Effects**: Layer names become the element labels in the timeline and detail table. Descriptive names like "Check" or "Selected fill" produce much better documentation than "Layer 1" or "Shape Layer 3"
* **Ensure keyframes exist**: The export script only captures properties with keyframes. Static properties are excluded automatically
* **Check the composition duration**: The timeline scales to the full composition length. Trim your composition to the relevant animation range for a tighter, more readable spec
* **Re-export if validation fails**: If the agent reports missing fields, re-run `export-timeline.jsx` in After Effects. The script copies fresh JSON to your clipboard
* **One composition at a time**: The script exports the active composition. Switch compositions in After Effects before re-running the script
# Properties
Source: https://docs.uspec.design/specs/property
Generate visual property annotations with variant exhibits directly in Figma
The property skill documents every configurable property of a component — variant axes, boolean toggles, variable modes, and child component properties — each shown as a visual exhibit with live instance previews.
`create-property` now renders **from the [Component Markdown](/specs/component-md) source of truth**. Run `create-component-md` first to produce `components/.md`; this skill takes the component's property identity from the `.md`'s `render-meta` block and renders the Figma frame. It no longer re-extracts from Figma, and it fails fast if the `.md` is missing.
## What you get
One section per axis (e.g., Size, Hierarchy) with instance previews for every option.
On/off states shown side by side with defaults labeled.
Shape, density, and other variable-mode properties rendered as visual chapters.
Nested component properties shown in-context on parent instances.
## What you need
* A **component `.md`** produced by `create-component-md` (run it first — `create-component-md` needs a `_base.json` from the uSpec Extract plugin). Tell the skill where this `.md` lives — `components/.md` is only `create-component-md`'s default output path; the file can live anywhere. Without it this skill aborts.
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP) — used only to render the frame.
* Context about the component is captured upstream by `create-component-md`; nothing extra is needed here.
Properties has no dedicated body section in the `.md`. It rebuilds the property model — variant axes, boolean defs, variable modes, slot contents, and sub-component identities — directly from the `.md`'s `render-meta` block.
## How to use
Reference the skill and pass the component `.md`. Add a render destination or any extra context the spec can't carry:
```
@create-property ./components/button.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
/create-property ./components/button.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
$create-property ./components/button.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
To place the annotation in a different file or page, add a destination link to your prompt:
`Destination: https://www.figma.com/design/xyz789/Docs?node-id=0-1`
## What it generates
| Output | Description |
| ------------------------ | ------------------------------------------------------------ |
| Variant axis exhibits | One section per axis with instance previews for every option |
| Boolean toggle exhibits | On/off states shown side by side |
| Variable mode exhibits | Shape, density, and other variable-driven properties |
| Child component chapters | Nested component properties rendered on parent instances |
| Default labels | The default value for each property is labeled |
The skill rebuilds the property model from the `.md`'s `render-meta` block (`componentPropertyDefinitions`, variant axes, boolean defs, variable modes), so the output adapts to any component regardless of how many properties it has.
## How it works
The property skill is primarily deterministic — scripts rebuild the property model from `render-meta`, lay out the template, and render instances, while AI reasoning handles normalization decisions and label generation.
70% Deterministic 30% AI Reasoning
```mermaid theme={null}
flowchart LR
A[You] -->|run create-component-md| M["components/<slug>.md"]
M -->|render-meta| B[create-property Skill]
B -->|Render| C[Figma MCP]
C -->|Annotation frame| D[Figma Output]
```
The skill requires `components/.md` (produced by `create-component-md`) and fails fast if it is missing — it does not re-extract from Figma.
Properties has no dedicated body section, so the skill rebuilds the property model — `componentPropertyDefinitions`, `variantProperties`, variable modes, and child component properties — directly from the `.md`'s `render-meta` block.
Coupled axes, container-gated booleans, unified slots, and sibling booleans are consolidated from the rebuilt model to avoid redundant exhibits — no live extraction walk.
The property documentation template is imported from the library, instantiated, and detached into an editable frame.
The skill fills header fields, clones chapter sections, creates component instances for visual exhibits, and labels defaults, resolving each exhibit against the live component set by name-match.
A screenshot is captured and checked for completeness. Issues are fixed automatically for up to 3 iterations.
The skill renders programmatically, so the output is consistent and repeatable. Running it on the same component produces identical results.
## Tips for better output
* **Use component sets**: The skill expects a component set (the dashed-border container in Figma) or a standalone component, not an instance
* **Check variant coverage**: If a variant axis like "Hierarchy" doesn't have variants for every combination of other axes, the skill finds the closest available match automatically
* **Name your layers**: Descriptive layer names help the skill correctly discover and label child component properties
* **Variable modes**: If your component uses variable modes (e.g., shape or density collections), the skill detects and renders them automatically
# Screen Reader
Source: https://docs.uspec.design/specs/screen-reader
Generate accessibility specifications for VoiceOver, TalkBack, and ARIA
Screen reader specs document how assistive technologies should announce and interact with your component across iOS (VoiceOver), Android (TalkBack), and Web (ARIA).
`create-voice` now renders **from the [Component Markdown](/specs/component-md) source of truth**. Run `create-component-md` first to produce `components/.md`; this skill reads its Voice section + `render-meta` and renders the Figma frame. It no longer re-extracts from Figma, and it fails fast if the `.md` is missing.
## What you need
* A **component `.md`** produced by `create-component-md` (run it first — `create-component-md` needs a `_base.json` from the uSpec Extract plugin). Tell the skill where this `.md` lives — `components/.md` is only `create-component-md`'s default output path; the file can live anywhere. Without it this skill aborts.
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP) — used only to render the frame.
* A description of states/behaviors is captured upstream by `create-component-md`; nothing extra is needed here.
Describe all interactive parts and how they relate. For example: "The label and hint merge into the input's announcement, but the trailing clear button is a separate focus stop." This helps the agent determine focus order accurately.
## How to use
Reference the skill and pass the component `.md`. Add a render destination or any extra context the spec can't carry:
```
@create-voice ./components/search-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
/create-voice ./components/search-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
$create-voice ./components/search-field.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
## What it generates
The agent analyzes your component's visual parts, determines which are independent focus stops vs. merged into another element's announcement, and renders per-platform documentation directly in your Figma file.
### Simple vs. compound components
Components where all parts merge into a single focusable element.
**Examples**: Button, Checkbox with label, Switch, Toggle
The output documents one focus stop per state, with platform-specific properties for each.
Components with multiple independently focusable elements.
**Examples**: Text field with trailing clear button, Chip with dismiss action, Tab bar
The output includes a **focus order** section showing the traversal sequence, plus per-state documentation for each stop.
### Platform properties
Each focus stop is documented with platform-specific properties:
| Platform | Key properties |
| ---------------------- | -------------------------------------------------------------------------------------- |
| **iOS (VoiceOver)** | `accessibilityLabel`, `accessibilityTraits`, `accessibilityHint`, `accessibilityValue` |
| **Android (TalkBack)** | `contentDescription`, `role`, `stateDescription` |
| **Web (ARIA)** | `role`, `aria-label`, `aria-describedby`, `aria-expanded` |
### Merge analysis
The agent determines how visual parts combine for accessibility:
| Visual part | Typical behavior |
| ------------------------------------- | --------------------------------------------- |
| Label | Merges into the control's announcement |
| Hint text | Becomes the accessibility hint or description |
| Decorative icons | Hidden from screen readers |
| Functional icons (e.g., clear button) | Separate focus stop |
| Action buttons | Separate focus stop |
## How it works
The screen reader skill is heavily AI-driven — the agent determines merge behavior, focus order, and platform-specific properties, while deterministic scripts handle template rendering and layout.
30% Deterministic 70% AI Reasoning
```mermaid theme={null}
flowchart LR
A[You] -->|run create-component-md| M["components/<slug>.md"]
M -->|Voice section + render-meta| B[create-voice Skill]
B -->|Render| C[Figma MCP]
C -->|Annotation frame| D[Figma Output]
```
The skill requires `components/.md` (produced by `create-component-md`) and fails fast if it is missing — it does not re-extract from Figma.
The skill parses the `.md`'s Voice section (guidelines, focus order, per-state platform tables) plus the `render-meta` block and the hidden `voice-render-meta` focus-stop layer-name carry.
Sections, focus stops (by Figma layer name), variant props, boolean defs, and slot insertions are assembled directly from the parsed `.md` — no live extraction walk.
The screen reader documentation template is imported from the library, instantiated, and detached into an editable frame.
The skill fills header fields, builds focus order diagrams, state tables, and per-platform property sections, placing markers by name-match + live bbox on the rendered instance.
A screenshot is captured and checked for completeness, including that every documented focus stop resolved a marker. Issues are fixed automatically for up to 3 iterations.
The skill renders programmatically, so the output is consistent and repeatable. Running it on the same component produces identical results.
## Tips for better output
* **List all states**: enabled, disabled, selected, expanded, loading. The agent can't infer states it can't see in Figma
* **Describe interactive parts and merge behavior**: explain which elements are tappable, which are decorative, and which should merge into another element's announcement. For example: *"The label and hint merge into the input's announcement, but the trailing clear button is a separate focus stop"*
* **Mention reactive elements**: error messages, status updates, and toasts are announced as live regions, not focus stops. Call them out if they're part of your component
* **Note focus order preferences**: if the traversal order matters (e.g., input before clear button), describe it
* **Describe state-specific announcements**: if the announcement changes based on state (e.g., a switch announcing "on" vs "off"), mention it
# Structure
Source: https://docs.uspec.design/specs/structure
Generate dimensional properties documentation for spacing, padding, and density variants
Structure specs document component measurements such as heights, widths, padding, and gaps, and how those values change across variants like density, size, and shape.
`create-structure` now renders **from the [Component Markdown](/specs/component-md) source of truth**. Run `create-component-md` first to produce `components/.md`; this skill reads its Structure section + `render-meta` and renders the Figma frame. It no longer re-extracts from Figma, and it fails fast if the `.md` is missing.
## What you need
* A **component `.md`** produced by `create-component-md` (run it first — `create-component-md` needs a `_base.json` from the uSpec Extract plugin). Tell the skill where this `.md` lives — `components/.md` is only `create-component-md`'s default output path; the file can live anywhere. Without it this skill aborts.
* **Figma MCP** connected (Console MCP with Desktop Bridge, or native Figma MCP) — used only to render the frame.
* Context about density modes, size variants, or specific sub-components is captured upstream by `create-component-md`; nothing extra is needed here.
Tell the agent which variant axes affect dimensions. A button might vary by size, while a list item varies by density. The agent checks both explicit variants and variable mode collections.
## How to use
Reference the skill and pass the component `.md`. Add a render destination or any extra context the spec can't carry:
```
@create-structure ./components/list-item.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
/create-structure ./components/list-item.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
```
$create-structure ./components/list-item.md
Render next to the component at https://www.figma.com/design/abc123/Components?node-id=100:200
```
To place the annotation in a different file or page, add a destination link to your prompt:
`Destination: https://www.figma.com/design/xyz789/Docs?node-id=0-1`
## What it generates
The agent measures your component and renders a documentation frame directly in your Figma file with tables showing how values change across variants.
| Aspect | What it covers |
| ------------------------ | ------------------------------------------------------ |
| Container dimensions | Heights, widths, min/max constraints |
| Padding and spacing | Horizontal and vertical padding, gaps between elements |
| Sub-component dimensions | Sizes for icons, avatars, and other nested elements |
| Token references | Links values to design tokens when they exist |
| Composition mapping | How parent sizes map to sub-component sizes |
### How tables are organized
Each section covers a part of the component (container, leading content, labels, trailing content). Columns represent variants, either sizes or density modes, so you can see how values change across configurations.
Some dimensional properties are controlled via Figma variable modes (like density) rather than explicit variant axes. The agent checks for both automatically.
## How it works
The structure skill consumes the Component Markdown source of truth: the dimensional values, section plan, and design-intent notes were already decided by `create-component-md`, so deterministic scripts render tables and measurements from the `.md` while AI reasoning is limited to resolving the parsed spec onto live Figma layers.
60% Deterministic 40% AI Reasoning
```mermaid theme={null}
flowchart LR
A[You] -->|run create-component-md| M["components/<slug>.md"]
M -->|Structure section + render-meta| B[create-structure Skill]
B -->|Render| C[Figma MCP]
C -->|Annotation frame| D[Figma Output]
```
The skill requires `components/.md` (produced by `create-component-md`) and fails fast if it is missing — it does not re-extract from Figma.
The skill parses the `.md`'s Structure section (per-section dimension tables, token bindings, design-intent notes) plus the `render-meta` block, which resolves sections, row-groups, and boolean-gated layers back to live Figma layer ids.
Sections, rows, token references, measurement targets, and sub-component anchors are assembled directly from the parsed `.md` and `render-meta` — no live extraction walk.
The structure documentation template is imported from the library, instantiated, and detached into an editable frame.
Deterministic scripts fill tables, place preview instances, and add native Figma measurements, locating each target by `render-meta` layer id with a name-match + live bbox fallback on the rendered instance.
A screenshot is captured and checked for completeness. Issues are fixed automatically for up to 3 iterations.
Roughly 60% of the pipeline is deterministic scripts (parsing the `.md`, rendering tables, measurements) and 40% is AI reasoning (resolving the spec onto live layers, completeness checks). Output is highly consistent across runs.
## Tips for better output
* **Specify which parts to include**: container, leading content, labels, trailing content, dividers
* **Mention density or size variants**: the agent organizes columns based on these. If density is controlled via variable modes (Compact, Default, Spacious), mention the mode names
* **Describe composition relationships**: if your component is composed of multiple sub-components (e.g., Text Field = Label + Input + Hint Text), describe how parent sizes map to child sizes
* **Call out sub-components**: if a sub-component has its own spec (e.g., Avatar inside a List item), the agent cross-references it
* **Note any state-specific dimensions**: some states introduce additional properties (e.g., a focused input gaining an inner border that doesn't exist in the default state)