redongreen/uspec/create-property

Claude Code and agent skill by redongreen/uspec

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Generate a visual property annotation in Figma showing each configurable property axis with component instance previews. Use when the user mentions "property", "properties", "property annotation", "create property", or wants to document a component's configurable properties visually.

Install

npx vskill@latest install redongreen/uspec/create-property

SKILL.md

Create Property Annotation

Generate a visual property annotation directly in Figma — one exhibit per variant axis and boolean toggle, each showing the available options as component instances with a summary table.

Execution contract (read first).

  • This file is instructions to RUN, not a document to edit. Invoking the skill = render the property annotation into Figma from the input .md.
  • Never edit this SKILL.md or any other skill file in response, even if one is open or focused in the editor. Modify a skill only when the user explicitly asks to change the skill itself.
  • The input component .md is a READ-ONLY source of truth. Never edit, append to, or "add a section" to it. The only artifact this skill produces is the Figma annotation. When the user asks to "create/add a section," "show," or "include" something, render it in the Figma annotation, never as an edit to the .md.
  • Never call AskQuestion, request confirmation, or pause for input (including before Figma writes, the expected output). On ambiguity, pick the most defensible option and continue.
  • Only two legal stops: (a) Step 0 fail-fast when no .md resolves; (b) one-line abort if the Figma MCP connection is dead.

MCP Adapter

Read uspecs.config.json → mcpProvider. Follow the matching column for every MCP call in this skill.

Operationfigma-consolefigma-mcp
Verify connectionfigma_get_statusSkip — implicit. If first use_figma call fails, guide user to check MCP setup.
Navigate to filefigma_navigate with URLExtract fileKey from URL (figma.com/design/:fileKey/...). No navigate needed.
Take screenshotfigma_take_screenshotget_screenshot with fileKey + nodeId
Execute Plugin JSfigma_execute with codeuse_figma with fileKey, code, description. Core logic is identical — see font loading note below for the one API difference (getRangeAllFontNames → tn.fontName).
Search componentsfigma_search_componentssearch_design_system with query + fileKey + includeComponents: true
Get file/component datafigma_get_file_data / figma_get_componentget_metadata or get_design_context with fileKey + nodeId
Get variables (file-wide)figma_get_variablesuse_figma script: return await figma.variables.getLocalVariableCollectionsAsync();
Get token valuesfigma_get_token_valuesuse_figma script reading variable values per mode/collection
Get stylesfigma_get_stylessearch_design_system with includeStyles: true, or use_figma: return figma.getLocalPaintStyles();
Get selectionfigma_get_selectionuse_figma script: return figma.currentPage.selection.map(n => ({id: n.id, name: n.name, type: n.type}));

`figma-mcp` requires `fileKey` on every call. Extract it once from the user's Figma URL at the start of the workflow. For branch URLs (figma.com/design/:fileKey/branch/:branchKey/:fileName), use :branchKey as the fileKey.

`figma-mcp` page context: use_figma resets figma.currentPage to the first page on every call. When a script accesses a node from a previous step via getNodeByIdAsync(ID), the page content may not be loaded — findAll, findOne, and characters will fail with TypeError until the page is activated. Insert this page-loading block at the start of every script that references a previously-created node:

javascript
const pages = figma.root.children;
const targetPage = pages.find(p => p.name === '__PAGE_NAME__');
if (targetPage) await figma.setCurrentPageAsync(targetPage);

Replace __PAGE_NAME__ with the actual page name (determined during Step 7 when the template is placed). This loads the page content so child nodes are accessible.

`figma-mcp` font loading: getRangeAllFontNames is not available in the use_figma sandbox and will throw TypeError. Replace it with tn.fontName (returns { family, style } for single-font text, or figma.mixed for mixed-font text). findAll and findOne work normally after setCurrentPageAsync — they do not need replacement.

Replace the font-collection loop in every script from:

javascript
const fonts = tn.getRangeAllFontNames(0, tn.characters.length);
for (const f of fonts) {
const key = f.family + '|' + f.style;
if (!fontSet.has(key)) { fontSet.add(key); fontsToLoad.push(f); }
}

to:

javascript
try {
const fn = tn.fontName;
if (fn && fn !== figma.mixed && fn.family) {
const key = fn.family + '|' + fn.style;
if (!fontSet.has(key)) { fontSet.add(key); fontsToLoad.push(fn); }
}
} catch {}

And add .catch(() => {}) to the batch load: await Promise.all(fontsToLoad.map(f => figma.loadFontAsync(f).catch(() => {})));

Inputs Expected

  • Component `.md` spec (required, user-provided path) — the source-of-truth component spec produced by {{skill:create-component-md}}. The user tells you where this `.md` lives — use the exact path they provide; the .md may live anywhere. This skill rebuilds its property model from the .md's render-meta block; it does NOT re-extract the property surface from Figma. fileKey, nodeId, and compSetNodeId come from render-meta, never from a Figma link.
  • Figma link (optional) — placement hint only (which page/frame to drop the rendered annotation on, including a cross-file destination) and the target for the two whitelisted minimal live reads in Steps 4a/4b. Never the source of the property contract.

Asymmetry from the other consumers. Unlike the Structure / Color / Voice consumers, the .md has no dedicated "Property" body section to copy. So create-property takes identity only from render-meta (which lets it skip extraction) and still authors its own property model, normalization, and exhibit plans with light in-memory reasoning. It does not parse a Property section body — there isn't one.

There is no screenshot-only path and no component-link extraction path. Without the component .md there is nothing to build from — see Step 0's fail-fast contract.

Workflow

Copy this checklist and update as you progress:

Task Progress:
- [ ] Step 0: Require the component `.md`; parse render-meta. FAIL FAST if missing.
- [ ] Step 1: Read instruction file (only as needed for normalization / exhibit-planning reasoning — NOT for re-extraction)
- [ ] Step 2: Verify MCP connection
- [ ] Step 3: Read template key from uspecs.config.json
- [ ] Step 4: Rebuild the property model from render-meta (variant axes, booleans, slots, instance-swaps, constitutive sub-components) — NO extraction
- [ ] Step 4a: WHITELISTED LIVE READ #2 — bounded variant-gated-boolean scan for requiredVariantOverrides
- [ ] Step 4b: WHITELISTED LIVE READ #1 — variable-collection lookup for the 6c variable-mode exhibit
- [ ] Step 4d: Normalize child properties IN MEMORY (coupled / unified slot / sibling boolean grouping) — no Figma reads
- [ ] Step 4e: Exhibit planning + context axis + briefDescription IN MEMORY — no Figma reads
- [ ] Step 5: Re-read instruction file (Pre-Render Validation Checklist, Common Mistakes, Do NOT) and audit
- [ ] Step 6: Navigate to destination (if different file)
- [ ] Step 7: Import and detach the Property template
- [ ] Step 8: Fill header fields
- [ ] Step 9: Build property exhibits with component instances
- [ ] Step 10: Visual validation
- [ ] Step 11: Completion link (reports sourceHash from render-meta)
Step 0: Require the component .md and parse render-meta (fail fast)

This skill is a consumer of the `.md` source of truth. It does not re-extract the property surface from Figma — extract-api/create-component-md already captured the component's variant axes, booleans, slots, instance-swaps, and constitutive sub-components into the .md's render-meta block. Your job is to rebuild the property model from render-meta and author the exhibits.

Asymmetry from the other consumers. The .md has NO dedicated "Property" body section to parse. So this skill gets identity only from render-meta (to skip extraction) and still authors its own property model + exhibit plans with light in-memory reasoning. There is no Property section body — render-meta is the only thing you read from the .md.

  1. Resolve the `.md` path. Use the exact path the user gave, else an attached or open .md in context. The .md may live anywhere; do NOT invent or guess a path. If neither resolves to an existing file, abort per item 2. Never pause to ask the user which file to use.
  2. Require the file. If no file exists at the resolved .md path, abort immediately with this exact single-line diagnostic and stop — do NOT fall back to extraction:

> This skill requires the component's Markdown .md spec (produced by create-component-md). Provide the path to it. (create-component-md needs a _base.json from the uSpec Extract plugin.)

  1. Parse the `render-meta` block (the fenced JSON between <!-- render-meta:start v=1 --> and <!-- render-meta:end -->; schema in references/component-md/agent-component-md-instruction.md § RENDER_META_JSON). Capture:
  • component = { componentName, compSetNodeId, isComponentSet }.
  • variantAxes — { <axisName>: [<option>, …] }.
  • variantAxesDefaults — { <axisName>: <default> }.
  • booleanDefs[] — { key, default, associatedLayerName, associatedLayerId }. Each key is the raw component-property key setProperties expects.
  • propertyDefs — keyed by raw key; each { type, default?, values?, preferredComponentKey?, associatedLayerName?, associatedLayerId? }. type ∈ VARIANT | BOOLEAN | INSTANCE_SWAP | SLOT | TEXT | NUMBER.
  • slotContents[] — { slotName, slotNodeType, preferredComponents: [{ componentKey, componentName, componentId, componentSetId, isComponentSet, variantAxes, booleanDefs }] }.
  • subComponents[] — { name, mainComponentName, subCompSetId, subCompVariantAxes, subCompVariantAxesDefaults, booleanOverrides }.
  • fileKey, nodeId — for template placement and the Step 11 completion link.
  • sourceHash — record it; the Step 11 completion footer reports it so downstream readers can detect drift between this render and the _base.json that produced the .md.
  1. Rebuild the property model in memory — see Step 4. No Figma reads.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/redongreen/uspec/create-property/badge)](https://verified-skill.com/skills/redongreen/uspec/create-property)

Something wrong with this skill or its page? Tell us.