@pedroab0/skills 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/cli.js CHANGED
@@ -72,9 +72,37 @@ ${style.bold('Examples:')}
72
72
  }
73
73
 
74
74
  // -----------------------------------------------------------------------------
75
- // Skill Discovery
75
+ // Frontmatter & Skill Discovery
76
76
  // -----------------------------------------------------------------------------
77
77
 
78
+ function parseFrontmatterField(content, field) {
79
+ const fm = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
80
+ if (!fm) return '';
81
+ const lines = fm[1].split(/\r?\n/);
82
+ const line = lines.find((l) => l.startsWith(`${field}:`));
83
+ if (!line) return '';
84
+ const raw = line.slice(field.length + 1).trim();
85
+ if (raw.startsWith("'") && raw.endsWith("'")) {
86
+ return raw.slice(1, -1).replace(/''/g, "'");
87
+ }
88
+ if (raw.startsWith('"') && raw.endsWith('"')) {
89
+ try {
90
+ return JSON.parse(raw);
91
+ } catch (_) {
92
+ return raw.slice(1, -1);
93
+ }
94
+ }
95
+ return raw;
96
+ }
97
+
98
+ function rewriteRelativeLinksForCursor(body, skill) {
99
+ return body.replace(/\]\((?!https?:|#|\/)([^)\s#]+\.md)(#[^)]*)?\)/g, (m, rel, hash = '') => {
100
+ return fs.existsSync(path.join(skill.path, rel))
101
+ ? `](../skills/${skill.name}/${rel}${hash || ''})`
102
+ : m;
103
+ });
104
+ }
105
+
78
106
  function getAvailableSkills() {
79
107
  const skills = [];
80
108
  try {
@@ -87,10 +115,7 @@ function getAvailableSkills() {
87
115
  let description = '';
88
116
  try {
89
117
  const content = fs.readFileSync(skillMdPath, 'utf8');
90
- const match = content.match(/description:\s*['"]?([^'"\n\r]+)['"]?/);
91
- if (match) {
92
- description = match[1].trim();
93
- }
118
+ description = parseFrontmatterField(content, 'description');
94
119
  } catch (_) {}
95
120
  skills.push({
96
121
  name: entry.name,
@@ -543,11 +568,14 @@ function installSkill(skill, destDir, useSymlink = false, isCursor = false) {
543
568
  fs.cpSync(skill.path, cursorSkillsDir, { recursive: true, filter: copyFilter });
544
569
 
545
570
  const rawSkillMd = fs.readFileSync(path.join(skill.path, 'SKILL.md'), 'utf8');
546
- const skillBody = rawSkillMd.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n*/, '');
571
+ const skillBody = rewriteRelativeLinksForCursor(
572
+ rawSkillMd.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n*/, ''),
573
+ skill,
574
+ );
547
575
  const ruleFile = path.join(destDir, `${skill.name}.mdc`);
548
576
  const ruleContent = `---
549
- description: ${skill.description}
550
- globs: *
577
+ description: ${JSON.stringify(skill.description)}
578
+ alwaysApply: false
551
579
  ---
552
580
 
553
581
  ${skillBody}`;
@@ -880,6 +908,8 @@ if (require.main === module) {
880
908
 
881
909
  module.exports = {
882
910
  selectPrompt,
911
+ parseFrontmatterField,
912
+ rewriteRelativeLinksForCursor,
883
913
  getAvailableSkills,
884
914
  getAgentConfigs,
885
915
  checkFigmaToken,
@@ -129,6 +129,7 @@ node figma-extractor/scripts/fetch_figma.js "<FigmaURL>" --tokens --spec tokens
129
129
  | `--spec <name>` | | **Atomic SDD mode**: Saves `./.specs/<name>.json` (add `-i` to also download preview PNG). |
130
130
  | `--image`, `--download-image` | `-i` | Download and save rendered preview image from Figma (Tier 1 call; optional). |
131
131
  | `--image-path <path>` | `-o <path>` | Custom destination path for saved preview image (e.g., `./.specs/card.png`). |
132
+ | `--force`, `--fresh` | `-f` | Ignore existing local spec/preview and re-fetch freshly from Figma. |
132
133
  | `--tokens`, `--variables` | | Export only the file's design token dictionary (colors, spacing, radii). |
133
134
  | `--shallow-instances` | | Collapse internal layers of component instances into clean props. |
134
135
  | `--include-tokens` | | Bundle complete design tokens dictionary alongside the node tree. |
@@ -137,7 +138,7 @@ node figma-extractor/scripts/fetch_figma.js "<FigmaURL>" --tokens --spec tokens
137
138
  | `--raw` | | Return full unpruned Figma API response without filtering. |
138
139
  | `--depth <number>` | | Limit node tree traversal depth (e.g., `--depth 2` for top-level layout only). |
139
140
  | `--scale <1\|2\|3\|4>` | | Multiplier for rendered image resolution (default: `2`). |
140
- | `--format <png\|svg\|jpg>` | | Image format for downloaded preview (default: `png`). |
141
+ | `--format <png\|svg\|jpg\|pdf>` | | Image format for downloaded preview (default: `png`). |
141
142
  | `--no-variables` | | Skip querying local variables to speed up extraction. |
142
143
  | `--help` | `-h` | Display command usage and available flags. |
143
144
 
@@ -0,0 +1,111 @@
1
+ # Figma Extractor Reference
2
+
3
+ ## Contents
4
+
5
+ - Token setup
6
+ - Corporate proxy and SSL
7
+ - CLI flags
8
+ - Output spec schema
9
+ - Rate-limit gate internals
10
+
11
+ ## Token setup
12
+
13
+ A Figma Personal Access Token (or OAuth token) is required. The user creates one in **Figma Settings → Personal Access Tokens**. The script reads `FIGMA_ACCESS_TOKEN` (or `FIGMA_TOKEN`) from the environment, from `.env` / `.env.local` in the working directory, from `~/.env`, and from shell profiles.
14
+
15
+ | Platform | Command for the user |
16
+ | :--- | :--- |
17
+ | macOS / Linux | `export FIGMA_ACCESS_TOKEN="figd_your_token_here"` in `~/.zshrc` or `~/.bashrc` |
18
+ | Windows (PowerShell) | `[Environment]::SetEnvironmentVariable("FIGMA_ACCESS_TOKEN", "figd_your_token_here", "User")` |
19
+ | Any (workspace) | `FIGMA_ACCESS_TOKEN=figd_your_token_here` in `.env` |
20
+
21
+ ## Corporate proxy and SSL
22
+
23
+ Behind a corporate proxy with self-signed certificates, the script fails with `FIGMA_SSL_CERTIFICATE_ERROR`. The user can disable certificate verification for Figma requests:
24
+
25
+ ```env
26
+ FIGMA_IGNORE_SSL=true
27
+ ```
28
+
29
+ ## CLI flags
30
+
31
+ ```bash
32
+ node "<skill-dir>/scripts/fetch_figma.js" <FigmaURL> [options]
33
+ node "<skill-dir>/scripts/fetch_figma.js" <fileKey> [nodeId] [options]
34
+ ```
35
+
36
+ | Flag | Shorthand | Description |
37
+ | :--- | :--- | :--- |
38
+ | `--spec <name>` | | Save `./.specs/<name>.json` (and `<name>.png` with `-i`). Reuses an existing spec with 0 API calls. |
39
+ | `--image`, `--download-image` | `-i` | Download the rendered preview image (+1 Tier 1 call). |
40
+ | `--image-path <path>`, `--output <path>` | `-o <path>` | Destination path for the preview image (implies `--image`). |
41
+ | `--force`, `--fresh` | `-f` | Ignore the existing local spec/preview and re-fetch from Figma. |
42
+ | `--tokens`, `--variables` | | Output only the design token dictionary (colors, spacing, radii). |
43
+ | `--shallow-instances` | | Collapse internal layers of component instances into props. |
44
+ | `--include-tokens` | | Include the full design token dictionary alongside the node tree. |
45
+ | `--include-ids` | | Keep internal Figma node IDs on each node. |
46
+ | `--pretty` | | Pretty-print JSON with 2-space indentation (default is compact). |
47
+ | `--raw` | | Return the full, unpruned Figma API response. Large; avoid unless debugging. |
48
+ | `--depth <number>` | | Limit node tree traversal depth (e.g. `--depth 2` for an overview). |
49
+ | `--scale <1\|2\|3\|4>` | | Preview render scale (default: `2`). |
50
+ | `--format <png\|svg\|jpg\|pdf>` | | Preview image format (default: `png`). |
51
+ | `--no-variables` | | Skip querying `/variables/local`. |
52
+ | `--help` | `-h` | Show the help message. |
53
+
54
+ ## Output spec schema
55
+
56
+ Each node keeps only properties that differ from Figma defaults. Hidden layers are dropped. Pure vector groups collapse into a single `VECTOR` node with `isSvg: true`.
57
+
58
+ | Field | Meaning |
59
+ | :--- | :--- |
60
+ | `name`, `type` | Layer name and node type (`FRAME`, `INSTANCE`, `TEXT`, `VECTOR`, ...). |
61
+ | `bounds` | `{ width, height }` render dimensions. |
62
+ | `layoutMode`, `layoutWrap`, `primaryAxisAlignItems`, `counterAxisAlignItems` | Auto-layout direction and alignment. |
63
+ | `layoutGrow`, `layoutAlign`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight` | Child sizing constraints. |
64
+ | `padding` / `paddingToken`, `itemSpacing` / `itemSpacingToken` | Spacing values and bound tokens. |
65
+ | `cornerRadius` / `cornerRadiusToken`, `cornerRadii` | Uniform or per-corner radius. |
66
+ | `fills`, `strokes`, `effects`, `opacity` | Paints (hex `color` + optional `token`), borders, shadows/blurs. |
67
+ | `characters`, `typography` | Text content and `fontFamily`, `fontSize`, `fontWeight`, `lineHeightPx`, `letterSpacing`, `textAlignHorizontal`, `textAlignVertical`. |
68
+ | `component`, `props` | Master component `name`/`variant` and normalized instance props. |
69
+ | `children` | Child nodes. |
70
+ | `image` | Present when `-i` was used: preview `path`, or `error`. |
71
+
72
+ ### Resolved design tokens
73
+
74
+ When a layer is bound to Figma variables, the semantic token name is attached next to the computed fallback value:
75
+
76
+ ```json
77
+ {
78
+ "name": "Card Container",
79
+ "type": "FRAME",
80
+ "layoutMode": "VERTICAL",
81
+ "padding": { "top": 16, "right": 16, "bottom": 16, "left": 16 },
82
+ "paddingToken": "spacing/md",
83
+ "itemSpacing": 12,
84
+ "itemSpacingToken": "spacing/sm",
85
+ "cornerRadius": 8,
86
+ "cornerRadiusToken": "radii/lg",
87
+ "fills": [{ "type": "SOLID", "color": "#1877F2", "token": "colors/brand/primary" }]
88
+ }
89
+ ```
90
+
91
+ ### Normalized component instances
92
+
93
+ Figma property hashes (`Label#12:3`) become clean props linked to the master component:
94
+
95
+ ```json
96
+ {
97
+ "name": "Submit Button",
98
+ "type": "INSTANCE",
99
+ "component": { "name": "Button", "variant": "Variant=Primary, Size=Large" },
100
+ "props": { "variant": "Primary", "size": "Large", "hasIcon": true, "label": "Confirm Order" },
101
+ "bounds": { "width": 140, "height": 44 }
102
+ }
103
+ ```
104
+
105
+ ## Rate-limit gate internals
106
+
107
+ The script protects the file quota automatically. No agent action is needed beyond the Zero-Hammer rules in `SKILL.md`.
108
+
109
+ - **Sliding window**: at most 5 requests per minute per file key (Figma throttles at roughly 10/min).
110
+ - **Pacing**: at least 2.5 s between consecutive requests.
111
+ - **Circuit breaker**: after an HTTP 429, the lockout end time is stored in `~/.figma_ratelimit.json`. Later calls to that file key fail immediately with `FIGMA_CIRCUIT_BREAKER_ACTIVE` and send no network traffic, so the lockout is not extended.
@@ -1,201 +1,77 @@
1
1
  ---
2
2
  name: figma-extractor
3
- description: 'Extract compact JSON node hierarchies, design tokens, component instance props, and automated preview images from Figma using the Figma REST API. Trigger this skill during the planning or specification phase whenever a Figma link is provided or when the user asks to inspect, extract, or sync design specifications and tokens from Figma into .specs/. This skill strictly produces specification artifacts and does not modify application code.'
3
+ description: 'Extracts Figma frames and components into compact JSON spec files (.specs/*.json) with resolved design tokens, normalized component instance props, and optional preview images, using the Figma REST API. Use when the user shares a figma.com link and wants to inspect, extract, document, or plan a design before implementation, or asks to sync Figma variables and design tokens. Produces specification artifacts only and never edits application code. For immediate one-shot code generation from a Figma link, use figma-to-code instead.'
4
4
  ---
5
5
 
6
- # Figma Extractor Skill (SDD Spec Ingest)
6
+ # Figma Extractor (SDD Spec Ingest)
7
7
 
8
- Extract design node metadata, component hierarchies, design tokens/variables, and rendered preview images directly from Figma via the Figma REST API into structured specification artifacts (`.specs/`).
8
+ Writes Figma designs to `.specs/<name>.json` (and optionally `.specs/<name>.png`) so a later implementation step can build from a fixed specification. A **spec** is the pruned Figma node tree with resolved tokens and component props.
9
9
 
10
- This skill serves as the **Specification Ingestion Layer** in a **Spec-Driven Development (SDD)** workflow. It is **Design-System Aware**, high-performance, token-efficient, and has zero external dependencies.
10
+ Requires Node.js >= 16.7. The scripts have zero dependencies (no `npm install`).
11
11
 
12
- ---
13
-
14
- ## Operational Boundary: Spec Ingestion Only
15
-
16
- * **Specification Artifacts Only**: This skill strictly outputs machine-readable design specifications (`.specs/<name>.json`) and visual references (`.specs/<name>.png`).
17
- * **Zero Application Code Changes**: Do **NOT** create, edit, or modify application source code (`.tsx`, `.vue`, `.html`, `.css`, etc.) while executing this skill.
18
- * **Hand-off to Implementation**: Once specifications are generated in `./.specs/`, present a summary of the extracted tokens, components, and layout bounds. The implementation phase is handled separately by the developer or a downstream builder skill (such as `figma-node-builder`).
19
-
20
- ---
21
-
22
- ## Strict Guardrails: No Browser Scraping / Automation
23
-
24
- > [!CAUTION]
25
- > **NEVER use browser tools (Playwright, Puppeteer, Chrome DevTools, `browser_navigate`, `read_browser_page`) on Figma URLs.**
26
- >
27
- > 1. **Figma Canvas is WebGL/Wasm**: Figma renders design canvas elements inside an HTML5 `<canvas>` via WebAssembly. There are NO inspectable HTML DOM elements for frames, layers, texts, or styles. Browser automation cannot extract Figma nodes or properties.
28
- > 2. **Never search for local browser binaries**: Do not search OS application directories (e.g., `/Applications`, `Program Files`, `/usr/bin`) or run browser automation scripts.
29
- > 3. **API Errors Are Final**: If `fetch_figma.js` returns an API error (e.g., 401 Unauthorized, 403 Forbidden, or 429 Rate Limited), **report the error directly to the user**. Guide them to check their `FIGMA_ACCESS_TOKEN`, permissions, or wait out rate limits. Do NOT attempt browser scraping fallbacks.
30
-
31
- ---
12
+ ## Boundaries
32
13
 
33
- ## Built-in Rate-Limit Gate & Circuit Breaker
14
+ - Output only `.specs/` artifacts. **Never create or edit application code** (`.tsx`, `.vue`, `.html`, `.css`, ...) while using this skill.
15
+ - **Never open Figma URLs with browser tools** (Playwright, Puppeteer, Chrome DevTools). The Figma canvas is WebGL, so there is no DOM to read. Do not search for local browser binaries.
16
+ - **API errors are final**: report them to the user. Never fall back to scraping.
34
17
 
35
- To protect your Figma file quota and prevent lockout penalties, `fetch_figma.js` enforces an automatic safety gate:
36
- * **Max 5 requests per minute** per file key (sliding window limit).
37
- * **2.5s inter-request pacing** between consecutive requests.
38
- * **Persistent Circuit Breaker**: If Figma returns HTTP 429, the script records the lockout time locally in `.figma_ratelimit.json` inside the user's home directory. All future calls to that file key are **immediately blocked with zero network traffic**, preventing Figma from extending the lockout penalty.
18
+ ## Workflow
39
19
 
40
- ### Agent Behavioral Rules (Zero-Hammer Protocol)
41
- 1. **Single-Shot Execution**: Run `fetch_figma.js` **once** per target frame or component.
42
- 2. **Never Retry on Failure**: If `fetch_figma.js` returns an error, **DO NOT retry in a loop**. Report the error directly to the user.
43
- 3. **Handling `FIGMA_CIRCUIT_BREAKER_ACTIVE`**: If the circuit breaker trips, inform the user that the file key is on cooldown, and suggest duplicating the file in Figma Drafts (Right-click $\rightarrow$ **Duplicate**) to get a fresh URL.
20
+ Copy this checklist and track your progress:
44
21
 
45
- ---
46
-
47
- ## Prerequisites
48
-
49
- A Figma Access Token (Personal Access Token or OAuth Token) is required.
50
-
51
- Configure it using either:
52
- 1. **Environment Variable**:
53
- - **macOS / Linux**: `export FIGMA_ACCESS_TOKEN="figd_your_token_here"` (or `FIGMA_TOKEN`)
54
- - **Windows (PowerShell)**: `[Environment]::SetEnvironmentVariable("FIGMA_ACCESS_TOKEN", "figd_your_token_here", "User")` or `$env:FIGMA_ACCESS_TOKEN="figd_your_token_here"` in `$PROFILE`
55
- 2. **Workspace `.env` File**:
56
- ```env
57
- FIGMA_ACCESS_TOKEN=figd_your_token_here
58
- ```
59
-
60
- ### Corporate Proxy & SSL Certificates
61
- If you are behind a corporate proxy or firewall with self-signed SSL certificates, enable SSL verification bypass:
62
- ```env
63
- FIGMA_IGNORE_SSL=true
22
+ ```
23
+ Extraction Progress:
24
+ - [ ] 1. Run the extraction (once)
25
+ - [ ] 2. Verify the result
26
+ - [ ] 3. Hand off a summary
64
27
  ```
65
28
 
66
- ---
67
-
68
- ## Tier 1 Quota Conservation: AST-Only by Default
69
-
70
- > [!IMPORTANT]
71
- > **Figma Starter plans enforce a strict limit of 20 Tier 1 requests/month.**
72
- > Both `GET /v1/files/:key/nodes` and `GET /v1/images/:key` count as Tier 1 endpoints.
73
- >
74
- > 1. **Default to AST-only extraction**: Running `--spec <name>` without `-i` consumes **only 1 Tier 1 call**. The JSON AST contains 100% of layout rules (flexbox, padding, gap), dimensions, hex colors, corner radii, and text content needed for code generation.
75
- > 2. **DO NOT pass `-i` / `--image` by default**: Only add `-i` if the user explicitly requests downloading a visual preview screenshot.
76
- > 3. **Reuse existing specs**: If `.specs/<name>.json` exists, reuse it with **0 API calls**.
77
-
78
- ---
79
-
80
- ## Agent Execution Instructions
81
-
82
- To extract a Figma frame or component as a specification artifact, run `fetch_figma.js` from this skill's `scripts/` directory:
29
+ **1. Run the extraction** (1 Tier 1 API call):
83
30
 
84
31
  ```bash
85
- # Recommended: Atomic extraction (writes ./.specs/<name>.json - 1 Tier 1 call)
86
32
  node "<skill-dir>/scripts/fetch_figma.js" "<FigmaURL>" --spec <name>
87
-
88
- # Optional: With companion preview image (writes .json and .png - 2 Tier 1 calls)
89
- node "<skill-dir>/scripts/fetch_figma.js" "<FigmaURL>" --spec <name> -i
90
33
  ```
91
34
 
92
- **Resolving `<skill-dir>` (Agent-Agnostic)**:
93
- Substitute `<skill-dir>` with the directory where this skill is installed — **never guess another agent's folder** (always keep double quotes around the script path for Windows/macOS/Linux compatibility):
94
- - **Standard Skills (`SKILL.md`)**: `<skill-dir>` is the exact parent directory of this `SKILL.md` file.
95
- - **Cursor Rule (`.cursor/rules/figma-extractor.mdc`)**: `<skill-dir>` is the sibling `.cursor/skills/figma-extractor` directory (replace `rules/figma-extractor.mdc` with `skills/figma-extractor`).
35
+ If `.specs/<name>.json` already exists, the script reuses it with 0 API calls. Pass `--force` only when the user explicitly asks to refresh the spec.
96
36
 
97
- ---
37
+ **2. Verify the result**
98
38
 
99
- ## Usage & Command Formats
39
+ - Success: stdout shows `✔ Saved Figma specification` or `✔ Reusing local Figma specification`.
40
+ - Failure: stderr contains a JSON error payload. Follow [Errors](#errors). Do not retry.
100
41
 
101
- ### 1. Atomic Spec Extraction (Recommended SDD Workflow)
42
+ **3. Hand off**: report the spec path and size, the root frame, the main component instances, and the design tokens found. Implementation is handled separately by the developer or by the `figma-node-builder` skill.
102
43
 
103
- Extract node metadata directly into `./.specs/`:
44
+ ## Common variants
104
45
 
105
- ```bash
106
- # Atomic AST extraction (1 Tier 1 call - recommended)
107
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name?node-id=4023-474" --spec card
46
+ | Need | Command suffix |
47
+ | :--- | :--- |
48
+ | Preview PNG (only if the user asks; +1 Tier 1 call) | `--spec <name> -i` |
49
+ | Design tokens dictionary only | `--tokens --spec tokens` |
50
+ | Collapse instance internals into props | `--spec <name> --shallow-instances` |
51
+ | Top-level overview of a large frame | `--spec <name> --depth 2` |
108
52
 
109
- # Optional: With rendered preview image (2 Tier 1 calls)
110
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name?node-id=4023-474" --spec card -i
53
+ All CLI flags, the output spec schema, token setup per OS, and proxy options: see [REFERENCE.md](REFERENCE.md) (located at `<skill-dir>/REFERENCE.md`).
111
54
 
112
- # Shallow instances mode (collapses internal component layers into clean props)
113
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name?node-id=4023-474" --spec card --shallow-instances
114
- ```
55
+ ## Resolving `<skill-dir>`
115
56
 
116
- ### 2. Design Tokens Dictionary Mode
57
+ Substitute `<skill-dir>` with the directory where this skill is installed. Never guess another agent's folder, and keep the double quotes around the script path (Windows/macOS/Linux):
117
58
 
118
- ```bash
119
- # Export only the file's design token dictionary (colors, spacing, radii) into ./.specs/tokens.json
120
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name" --tokens --spec tokens
121
- ```
122
-
123
- ### 3. CLI Flags Reference
124
-
125
- | Flag | Shorthand | Description |
126
- | :--- | :--- | :--- |
127
- | `--spec <name>` | | **Atomic SDD mode**: Saves `./.specs/<name>.json` (add `-i` to also download preview PNG). |
128
- | `--image`, `--download-image` | `-i` | Download and save rendered preview image from Figma (Tier 1 call; optional). |
129
- | `--image-path <path>` | `-o <path>` | Destination path for saved preview image (e.g. `./.specs/preview.png`). |
130
- | `--tokens`, `--variables` | | Output only the design token dictionary (colors, spacing, radii). |
131
- | `--shallow-instances` | | Collapse internal sub-layers of component instances into clean props. |
132
- | `--pretty` | | Pretty-print JSON with 2-space indentation (default is compact single-line JSON). |
133
- | `--include-tokens` | | Include full design tokens dictionary alongside node AST. |
134
- | `--include-ids` | | Retain internal Figma node IDs on each node in the tree. |
135
- | `--raw` | | Return full, unpruned raw Figma API AST. |
136
- | `--depth <number>` | | Limit node tree traversal depth (e.g. `--depth 2` for top-level overview). |
137
- | `--scale <1\|2\|3\|4>` | | Render resolution multiplier for preview images (default: `2`). |
138
- | `--format <png\|svg\|jpg>` | | Rendered image file format (default: `png`). |
139
- | `--no-variables` | | Skip querying `/variables/local`. |
140
- | `--help` | `-h` | Show help message. |
141
-
142
- ---
59
+ - **Standard skills (`SKILL.md`)**: the parent directory of this `SKILL.md` file.
60
+ - **Cursor rule (`.cursor/rules/figma-extractor.mdc`)**: the sibling `.cursor/skills/figma-extractor` directory.
143
61
 
144
- ## Output Spec Structure
145
-
146
- ### 1. Resolved Design Tokens
147
- When a layer uses Figma variables (design tokens), the extractor attaches semantic token names alongside computed fallback values:
148
-
149
- ```json
150
- {
151
- "name": "Card Container",
152
- "type": "FRAME",
153
- "layoutMode": "VERTICAL",
154
- "padding": { "top": 16, "right": 16, "bottom": 16, "left": 16 },
155
- "paddingToken": "spacing/md",
156
- "itemSpacing": 12,
157
- "itemSpacingToken": "spacing/sm",
158
- "cornerRadius": 8,
159
- "cornerRadiusToken": "radii/lg",
160
- "fills": [
161
- {
162
- "type": "SOLID",
163
- "color": "#1877F2",
164
- "token": "colors/brand/primary"
165
- }
166
- ]
167
- }
168
- ```
62
+ ## Quota rules (Zero-Hammer Protocol)
169
63
 
170
- ### 2. Normalized Component Instances & Props
171
- When an `INSTANCE` node is present, internal property hashes are converted into clean JavaScript props and linked to the master component name:
172
-
173
- ```json
174
- {
175
- "name": "Submit Button",
176
- "type": "INSTANCE",
177
- "component": {
178
- "name": "Button",
179
- "variant": "Variant=Primary, Size=Large"
180
- },
181
- "props": {
182
- "variant": "Primary",
183
- "size": "Large",
184
- "hasIcon": true,
185
- "label": "Confirm Order"
186
- },
187
- "bounds": { "width": 140, "height": 44 }
188
- }
189
- ```
64
+ The script enforces a local rate gate and a persistent circuit breaker, but the agent must also follow these rules:
190
65
 
191
- ---
66
+ 1. Run `fetch_figma.js` **once** per target frame or component. **Never retry in a loop.**
67
+ 2. **Do not pass `-i`** unless the user explicitly requests a preview image. The JSON spec already contains layout, dimensions, colors, radii, typography, and text.
68
+ 3. Figma Starter plans and View seats have very small monthly Tier 1 quotas, so every call matters. Prefer reusing existing specs.
192
69
 
193
- ## Error Handling & Troubleshooting
70
+ ## Errors
194
71
 
195
- - **Token Expired / Missing (`FIGMA_TOKEN_EXPIRED_OR_INVALID` / `isTokenExpiredOrInvalid`)**:
196
- - Alert the user that their Figma access token is missing, invalid, or expired.
197
- - Instruct the user to create a token in **Figma Settings → Personal Access Tokens** and configure `FIGMA_ACCESS_TOKEN` in their environment or workspace `.env` file.
198
- - **Node Not Found**:
199
- - Alert the user that the node ID could not be found in the specified file.
200
- - **Rate Limited (`FIGMA_RATE_LIMIT_EXCEEDED` / `FIGMA_CIRCUIT_BREAKER_ACTIVE`)**:
201
- - Figma REST API has per-minute and monthly rate limits on Starter plans. If quota is exhausted or circuit breaker trips, inform the user they can export the specification directly via the companion **Figma Node JSON Extractor** desktop plugin (available on [Figma Community](https://www.figma.com/community/plugin/1691244420692136789/figma-node-json-extractor)) into `./.specs/<name>.json`.
72
+ | Error code | Action |
73
+ | :--- | :--- |
74
+ | `FIGMA_ACCESS_TOKEN is not set` / `FIGMA_TOKEN_EXPIRED_OR_INVALID` | Tell the user the token is missing, invalid, or expired. They create one in **Figma Settings → Personal Access Tokens** and set `FIGMA_ACCESS_TOKEN` (setup per OS in REFERENCE.md). |
75
+ | Node not found | Report that the `node-id` does not exist in the file. |
76
+ | `FIGMA_SSL_CERTIFICATE_ERROR` | Corporate proxy or self-signed certificate: suggest `FIGMA_IGNORE_SSL=true` in `.env`. |
77
+ | `FIGMA_RATE_LIMIT_EXCEEDED` / `FIGMA_CIRCUIT_BREAKER_ACTIVE` | Report the cooldown. Suggest duplicating the file in Figma Drafts (Right-click → **Duplicate**) for a fresh URL, or exporting the selection with the companion [Figma Node JSON Extractor](https://www.figma.com/community/plugin/1691244420692136789/figma-node-json-extractor) plugin into `.specs/<name>.json`. |
@@ -1402,6 +1402,7 @@ Options:
1402
1402
  --spec <name> Atomically save ./.specs/<name>.json (add -i to also download preview PNG)
1403
1403
  --image, -i Download rendered preview image from Figma (Tier 1 call)
1404
1404
  --image-path, -o <path> Target path for saved preview image (implies --image)
1405
+ --force, -f Ignore existing local spec/preview and re-fetch from Figma
1405
1406
  --tokens, --variables Export only the design token dictionary (colors, spacing, radii)
1406
1407
  --shallow-instances Collapse internal layers of component instances into props
1407
1408
  --include-tokens Include complete tokens dictionary in node output
@@ -1,112 +1,101 @@
1
1
  ---
2
2
  name: figma-node-builder
3
- description: 'Build production-ready UI components by synthesizing extracted Figma node hierarchies (.specs/*.json) and companion preview images (.specs/*.png). Trigger this skill in Spec-Driven Development (SDD) workflows when the user asks to implement, build, or code UI components from an existing Figma spec, node AST, or specification file.'
3
+ description: 'Builds production-ready UI components from previously extracted Figma spec files (.specs/*.json) and optional preview images (.specs/*.png), reusing the host project components, design tokens, and icon library. Works offline with no Figma API calls. Use when the user asks to implement, build, or code a component or screen from an existing .specs file, or approves implementation after a figma-extractor run.'
4
4
  ---
5
5
 
6
- # Figma Node Builder Skill (SDD Implementation Layer)
6
+ # Figma Node Builder (SDD Implementation Layer)
7
7
 
8
- Build production-grade, design-system-grounded UI components directly from extracted Figma Node trees (`.specs/<name>.json`) and visual reference images (`.specs/<name>.png`).
8
+ Builds UI code from an extracted **spec** (`.specs/<name>.json`, the pruned Figma node tree with resolved tokens and component props) and its optional preview image (`.specs/<name>.png`). Works entirely offline: no Figma API calls or tokens.
9
9
 
10
- This skill serves as the **Implementation Layer** in a **Spec-Driven Development (SDD)** workflow. It works entirely offline and locally from the extracted specification contract—no Figma API calls or tokens required.
10
+ Requires Node.js >= 16.7 for the inspector script (zero dependencies, no `npm install`).
11
11
 
12
- ---
12
+ ## Workflow
13
13
 
14
- ## When to Trigger This Skill
14
+ Copy this checklist and track your progress:
15
15
 
16
- Trigger this skill whenever:
17
- * The user references an existing specification file (e.g., *"Build the component from `.specs/card.json`"*).
18
- * An extraction step by `figma-extractor` or the **Figma Node JSON Extractor** plugin has completed, and the user approves the implementation (e.g., *"Proceed"*, *"Build it"*, *"Implement the UI"*).
19
- * The user asks to turn a local Figma node AST (`.specs/<name>.json`) into React, Vue, Svelte, or HTML/CSS code.
16
+ ```
17
+ Implementation Progress:
18
+ - [ ] Phase 1: Discover the host project (stack, UI primitives, tokens, icons)
19
+ - [ ] Phase 2: Inspect the spec and map it to the codebase
20
+ - [ ] Phase 3: Build the component following the build rules
21
+ - [ ] Phase 4: Validate and fix
22
+ ```
20
23
 
21
- ---
24
+ ### Phase 1: Discover the host project
25
+
26
+ Before writing code, ground the implementation in the existing project:
27
+
28
+ 1. **Framework and styling**: check `package.json` for React, Vue, Svelte, Angular, Next.js, Tailwind CSS, styled-components, or plain CSS.
29
+ 2. **UI primitives**: inspect `components/ui/`, `src/components/`, or design system libraries (shadcn/ui, Radix, MUI) for reusable components (`Button`, `Input`, `Card`, `Badge`).
30
+ 3. **Design tokens**: inspect `tailwind.config.*`, `theme.css`, or `globals.css` for color, spacing, and radius scales.
31
+ 4. **Icons**: check `package.json` for icon packages (`lucide-react`, `@heroicons/react`, `phosphor-react`) and local icon folders (`components/icons/`, `src/assets/`, `public/`).
32
+
33
+ ### Phase 2: Inspect the spec and map it to the codebase
22
34
 
23
- ## The 4-Phase Implementation Protocol
35
+ Run the inspector instead of reading the raw JSON into context (resolve `<skill-dir>` as described below):
24
36
 
25
- ```mermaid
26
- flowchart TD
27
- A["Phase 1: Codebase Discovery<br/>(Framework & Existing Primitives)"] --> B["Phase 2: Gap Analysis<br/>(Match Tokens & Props)"]
28
- B --> C["Phase 3: Grounded Synthesis<br/>(No Hallucinated CSS)"]
29
- C --> D["Phase 4: Visual Verification<br/>(Check vs .specs/*.png)"]
37
+ ```bash
38
+ node "<skill-dir>/scripts/inspect_spec.js" .specs/<name>.json --markdown
30
39
  ```
31
40
 
32
- ### Phase 1: Codebase Discovery
33
- Before writing any code, inspect the host project to ground your implementation:
34
- 1. **Framework & Styling**: Check `package.json` for React, Vue, Svelte, Next.js, Tailwind CSS, styled-components, or plain CSS.
35
- 2. **Existing UI Primitives**: Inspect `components/ui/`, `src/components/`, or design system libraries (e.g., shadcn/ui, Radix, MUI) to identify reusable components (`Button`, `Input`, `Card`, `Badge`).
36
- 3. **Design Token System**: Inspect `tailwind.config.js`, `theme.css`, or `globals.css` to see how colors and spacing scales are configured.
37
- 4. **Icons & Assets Discovery**: Check `package.json` for installed icon packages (e.g. `lucide-react`, `@heroicons/react`, `phosphor-react`) and check if local icon folders exist (`components/icons/`, `src/assets/`, `public/`).
38
-
39
- ### Phase 2: Gap Analysis & Token Mapping
40
- Analyze the input JSON spec (`.specs/<name>.json`).
41
-
42
- > **Tip**: Instead of reading the entire raw JSON AST into your context window, run the companion **Spec Inspector CLI** from this skill's directory (`<skill-dir>` is the folder containing this `SKILL.md` file; if loaded from `.cursor/rules/figma-node-builder.mdc`, use `.cursor/skills/figma-node-builder`):
43
- > ```bash
44
- > # Compact terminal summary (always quote the script path for Windows/macOS/Linux compatibility):
45
- > node "<skill-dir>/scripts/inspect_spec.js" .specs/<name>.json
46
- >
47
- > # Output Markdown directly for your implementation plan:
48
- > node "<skill-dir>/scripts/inspect_spec.js" .specs/<name>.json --markdown
49
- > ```
50
-
51
- * **Component Instances**: For each node with `type: "INSTANCE"`, match `component.name` against existing codebase components. Extract its `props` (e.g., `{ variant: "outline", size: "lg", hasIcon: true }`).
52
- * **Design Tokens**: For every `token` property (e.g., `colors/brand/primary`, `spacing/md`, `radii/lg`), map to the project's CSS variables (`var(--color-brand-primary)`) or Tailwind classes (`bg-brand-primary`, `p-4`, `rounded-lg`).
53
- * **Gaps**: Identify any sub-components that do not exist yet in the codebase and plan to scaffold them.
54
-
55
- ### Phase 3: Grounded Code Synthesis
56
- Generate component code strictly adhering to the node specification and adapting syntax to the host project's detected stack (e.g., React, Vue, Svelte, Angular, or HTML/CSS):
57
-
58
- 1. **Reusing Existing Components (Anti-Div Soup Rule)**:
59
- - When an `INSTANCE` node matches an existing component, **import and render it directly** (example in JSX — adapt to your framework):
60
- ```tsx
61
- // Correct:
62
- <Button variant="primary" size="large" hasIcon>Confirm Order</Button>
63
-
64
- // Forbidden (do not rebuild existing primitives from raw divs):
65
- <div className="flex bg-blue-500 rounded p-2 text-white">Confirm Order</div>
66
- ```
67
- 2. **Layout & Flexbox Translation**:
68
- - `layoutMode: "HORIZONTAL"` $\rightarrow$ Flex row (`display: flex; flex-direction: row;` or `flex flex-row`).
69
- - `layoutMode: "VERTICAL"` $\rightarrow$ Flex column (`display: flex; flex-direction: column;` or `flex flex-col`).
70
- - `itemSpacing` $\rightarrow$ CSS `gap` (map to `itemSpacingToken` if available).
71
- - `padding` $\rightarrow$ CSS `padding` (map to `paddingToken` if available).
72
- - `primaryAxisAlignItems` / `counterAxisAlignItems` $\rightarrow$ `justify-*` and `items-*`.
73
- 3. **Typography & Colors**:
74
- - Never guess hex colors. If `token` is present, use the semantic token. If not, use the fallback `color` hex string.
75
- - Map font sizes, font weights, and line heights to existing design tokens or typography classes.
76
- 4. **Icon & Vector Resolution Hierarchy**:
77
- When encountering a `VECTOR` node or icon instance:
78
- - **Normalize Node Name**: Strip common prefixes (`icon/`, `ic_`, `ico-`) and clean the name (e.g., `icon/search` $\rightarrow$ `search` / `Search`).
79
- - **Step 1 (Targeted Local Assets/Components)**: Look for matching files in `components/icons/`, `src/assets/`, or `public/` (e.g., `<SearchIcon />`, `/icons/search.svg`). Avoid recursive searches outside these targeted paths.
80
- - **Step 2 (Installed Icon Library)**: If not found locally, import from the icon library detected in `package.json` (e.g., `import { Search } from 'lucide-react'`).
81
- - **Step 3 (Semantic Fallback - Never Hallucinate Raw Béziers)**: If not found, render an accessible placeholder (`<span className="w-4 h-4 inline-flex items-center justify-center text-muted-foreground" aria-hidden="true" />`) with a `TODO: Missing icon 'search'` comment. Never hallucinate raw SVG `<path d="...">` coordinates.
82
- 5. **Image Layer Handling (`fills: [{ type: "IMAGE" }]`)**:
83
- - Focus exclusively on applying the exact styling from the Figma spec: dimensions (`width`, `height`), border radius (`rounded-*`), and scale mode (`scaleMode: "FILL"` $\rightarrow$ `object-cover`, `"FIT"` $\rightarrow$ `object-contain`).
84
- - Do **NOT** attempt to resolve, fetch, or hallucinate image files or external URLs (never invent Unsplash or third-party links).
85
- - Render a standard `<img>` tag with `src=""` and a concise `TODO` comment specifying the target image:
86
- ```tsx
87
- {/* TODO: Add image source for 'User Avatar' (48x48) */}
88
- <img src="" alt="User Avatar" className="w-12 h-12 rounded-full object-cover" />
89
- ```
90
-
91
- ### Phase 4: Visual Cross-Check & Verification
92
- * **Optional Companion Image**: If the companion preview image (`.specs/<name>.png`) exists, inspect it to cross-check visual styling and icons.
93
- * **AST-Only Synthesis**: If `.specs/<name>.png` was omitted (to conserve Tier 1 API calls), rely strictly on the exact metrics, flexbox rules, hex colors, and font styles in `.specs/<name>.json`.
94
- * If a dev server or browser preview is active, verify that the rendered DOM matches the specification.
41
+ Use `--json` instead of `--markdown` for a structured summary (or `--help` / `-h` for CLI options). Then:
95
42
 
96
- ---
43
+ - **Component instances**: match each `INSTANCE` `component.name` against existing codebase components and note its `props`.
44
+ - **Design tokens**: map each `token` (`colors/brand/primary`, `spacing/md`, `radii/lg`) to the project CSS variables or Tailwind classes.
45
+ - **Gaps**: list sub-components and tokens that do not exist yet and must be created.
46
+
47
+ Read specific parts of the raw spec only when the inspector summary is not enough.
48
+
49
+ ### Phase 3: Build the component
50
+
51
+ Follow the [Build rules](#build-rules), adapting syntax to the stack detected in Phase 1.
52
+
53
+ ### Phase 4: Validate and fix
54
+
55
+ 1. Run the project's existing checks: `typecheck` or `lint` scripts from `package.json`, or `npx tsc --noEmit` when TypeScript is already installed. Never install new dependencies to do this.
56
+ 2. If checks fail in the files you created or changed, fix them and run the checks again. Repeat until they pass.
57
+ 3. Report pre-existing failures in other files instead of fixing them.
58
+ 4. If `.specs/<name>.png` exists, compare it visually with the result. If it does not exist, rely strictly on the metrics in the spec.
59
+
60
+ ## Build rules
97
61
 
98
- ## Input Spec Reference (Figma Node AST)
62
+ 1. **Reuse existing components (no div soup)**: when an `INSTANCE` matches an existing component, import and render it with the spec props. Never rebuild existing primitives from raw elements.
63
+ ```tsx
64
+ // Correct
65
+ <Button variant="primary" size="large" hasIcon>Confirm Order</Button>
66
+ // Forbidden
67
+ <div className="flex bg-blue-500 rounded p-2 text-white">Confirm Order</div>
68
+ ```
69
+ 2. **Layout**: `layoutMode: "HORIZONTAL"` → flex row; `"VERTICAL"` → flex column; `itemSpacing` → `gap`; `padding` → padding; `primaryAxisAlignItems` / `counterAxisAlignItems` → `justify-*` / `items-*`. Prefer the matching `*Token` when present.
70
+ 3. **Colors and typography**: never guess values. Use the semantic `token` when present, otherwise the exact hex `color`. Map font size, weight, and line height to existing typography tokens or classes.
71
+ 4. **Icons and vectors** (`VECTOR` nodes, `isSvg: true`, or icon instances): normalize the name by stripping `icon/`, `ic_`, `ico-` (`icon/search` → `search`), then resolve in order:
72
+ 1. Local assets or components in `components/icons/`, `src/assets/`, or `public/` only (no repo-wide searches).
73
+ 2. The icon library installed in `package.json` (e.g. `import { Search } from 'lucide-react'`).
74
+ 3. An accessible placeholder with a `TODO: Missing icon 'search'` comment. Never invent raw SVG `<path d="...">` coordinates.
75
+ 5. **Image fills** (`fills: [{ type: "IMAGE" }]`): apply only the spec styling (size, radius, `scaleMode: "FILL"` → `object-cover`, `"FIT"` → `object-contain`). Never fetch or invent image URLs:
76
+ ```tsx
77
+ {/* TODO: Add image source for 'User Avatar' (48x48) */}
78
+ <img src="" alt="User Avatar" className="w-12 h-12 rounded-full object-cover" />
79
+ ```
99
80
 
100
- The input `.specs/<name>.json` file contains a pruned AST of Figma nodes:
81
+ ## Spec field reference
101
82
 
102
- | Field | Meaning | Code Mapping |
83
+ | Field | Meaning | Code mapping |
103
84
  | :--- | :--- | :--- |
104
- | `type` | Node type (`FRAME`, `INSTANCE`, `TEXT`, `VECTOR`) | Container (`div` / `section`), Component import, Typography tag (`h1`-`p`), or Icon component/placeholder (see Icon Resolution Hierarchy). |
105
- | `layoutMode` | Auto-layout direction (`HORIZONTAL`, `VERTICAL`) | `flex flex-row` or `flex flex-col`. |
106
- | `itemSpacing` / `itemSpacingToken` | Gap between child items | `gap-*` class or `gap: Xpx`. |
107
- | `padding` / `paddingToken` | Object with `top`, `right`, `bottom`, `left` | `p-*`, `px-*`, `py-*` classes or `padding: ...`. |
108
- | `cornerRadius` / `cornerRadiusToken` | Border radius | `rounded-*` class or `border-radius: Xpx`. |
109
- | `component.name` | Master component name for an `INSTANCE` | Import name (e.g. `import { Button } from '@/components/ui/button'`). |
110
- | `props` | Normalized component variant and boolean properties | JSX/template props: `<Component {...props} />`. |
111
- | `bounds` | Render dimensions (`width`, `height`) | Sizing constraints (`w-*`, `h-*`, `max-w-*`). |
112
- | `fills` | Fill layers (`SOLID`, `IMAGE`, gradients) | Background color (`bg-*`), gradient, or styled `<img>` tag for `IMAGE` fills (see Image Layer Handling). |
85
+ | `type` | `FRAME`, `INSTANCE`, `TEXT`, `VECTOR` | Container, component import, typography tag, or icon (rule 4). |
86
+ | `layoutMode` | `HORIZONTAL` / `VERTICAL` auto-layout | `flex flex-row` / `flex flex-col`. |
87
+ | `itemSpacing` / `itemSpacingToken` | Gap between children | `gap-*` or `gap: Xpx`. |
88
+ | `padding` / `paddingToken` | `{ top, right, bottom, left }` | `p-*`, `px-*`, `py-*` or `padding`. |
89
+ | `cornerRadius` / `cornerRadiusToken` | Border radius | `rounded-*` or `border-radius`. |
90
+ | `component.name` | Master component of an `INSTANCE` | Import name (`import { Button } from '@/components/ui/button'`). |
91
+ | `props` | Normalized variant and boolean props | Component props (`<Component {...props} />`). |
92
+ | `bounds` | `{ width, height }` | Sizing (`w-*`, `h-*`, `max-w-*`). |
93
+ | `fills` | `SOLID`, `IMAGE`, gradients | Background, gradient, or `<img>` (rule 5). |
94
+ | `characters` / `typography` | Text content and font metrics | Text node with mapped typography classes. |
95
+
96
+ ## Resolving `<skill-dir>`
97
+
98
+ Substitute `<skill-dir>` with the directory where this skill is installed, keeping the double quotes around the script path (Windows/macOS/Linux):
99
+
100
+ - **Standard skills (`SKILL.md`)**: the parent directory of this `SKILL.md` file.
101
+ - **Cursor rule (`.cursor/rules/figma-node-builder.mdc`)**: the sibling `.cursor/skills/figma-node-builder` directory.
@@ -130,6 +130,7 @@ node figma-to-code/scripts/fetch_figma.js "<FigmaURL>" -i --shallow-instances
130
130
  | :--- | :--- | :--- |
131
131
  | `--image`, `--download-image` | `-i` | Download and save rendered preview image from Figma (Tier 1 call; optional). |
132
132
  | `--image-path <path>` | `-o <path>` | Custom destination path for saved preview image (e.g., `./.specs/card.png`). |
133
+ | `--force`, `--fresh` | `-f` | Ignore existing local preview image and re-fetch freshly from Figma. |
133
134
  | `--tokens`, `--variables` | | Export only the file's design token dictionary (colors, spacing, radii). |
134
135
  | `--shallow-instances` | | Collapse internal layers of component instances into clean props. |
135
136
  | `--include-tokens` | | Bundle complete design tokens dictionary alongside the node tree. |
@@ -138,7 +139,7 @@ node figma-to-code/scripts/fetch_figma.js "<FigmaURL>" -i --shallow-instances
138
139
  | `--raw` | | Return full unpruned Figma API response without filtering. |
139
140
  | `--depth <number>` | | Limit node tree traversal depth (e.g., `--depth 2` for top-level layout only). |
140
141
  | `--scale <1\|2\|3\|4>` | | Multiplier for rendered image resolution (default: `2`). |
141
- | `--format <png\|svg\|jpg>` | | Image format for downloaded preview (default: `png`). |
142
+ | `--format <png\|svg\|jpg\|pdf>` | | Image format for downloaded preview (default: `png`). |
142
143
  | `--no-variables` | | Skip querying local variables to speed up extraction. |
143
144
  | `--help` | `-h` | Display command usage and available flags. |
144
145
 
@@ -0,0 +1,110 @@
1
+ # Figma To Code Reference
2
+
3
+ ## Contents
4
+
5
+ - Token setup
6
+ - Corporate proxy and SSL
7
+ - CLI flags
8
+ - Output spec schema
9
+ - Rate-limit gate internals
10
+
11
+ ## Token setup
12
+
13
+ A Figma Personal Access Token (or OAuth token) is required. The user creates one in **Figma Settings → Personal Access Tokens**. The script reads `FIGMA_ACCESS_TOKEN` (or `FIGMA_TOKEN`) from the environment, from `.env` / `.env.local` in the working directory, from `~/.env`, and from shell profiles.
14
+
15
+ | Platform | Command for the user |
16
+ | :--- | :--- |
17
+ | macOS / Linux | `export FIGMA_ACCESS_TOKEN="figd_your_token_here"` in `~/.zshrc` or `~/.bashrc` |
18
+ | Windows (PowerShell) | `[Environment]::SetEnvironmentVariable("FIGMA_ACCESS_TOKEN", "figd_your_token_here", "User")` |
19
+ | Any (workspace) | `FIGMA_ACCESS_TOKEN=figd_your_token_here` in `.env` |
20
+
21
+ ## Corporate proxy and SSL
22
+
23
+ Behind a corporate proxy with self-signed certificates, the script fails with `FIGMA_SSL_CERTIFICATE_ERROR`. The user can disable certificate verification for Figma requests:
24
+
25
+ ```env
26
+ FIGMA_IGNORE_SSL=true
27
+ ```
28
+
29
+ ## CLI flags
30
+
31
+ ```bash
32
+ node "<skill-dir>/scripts/fetch_figma.js" <FigmaURL> [options]
33
+ node "<skill-dir>/scripts/fetch_figma.js" <fileKey> [nodeId] [options]
34
+ ```
35
+
36
+ | Flag | Shorthand | Description |
37
+ | :--- | :--- | :--- |
38
+ | `--image`, `--download-image` | `-i` | Download the rendered preview image (+1 Tier 1 call). |
39
+ | `--image-path <path>`, `--output <path>` | `-o <path>` | Destination path for the preview image (implies `--image`). |
40
+ | `--force`, `--fresh` | `-f` | Ignore an existing local preview image and re-fetch it from Figma. |
41
+ | `--tokens`, `--variables` | | Output only the design token dictionary (colors, spacing, radii). |
42
+ | `--shallow-instances` | | Collapse internal layers of component instances into props. |
43
+ | `--include-tokens` | | Include the full design token dictionary alongside the node tree. |
44
+ | `--include-ids` | | Keep internal Figma node IDs on each node. |
45
+ | `--pretty` | | Pretty-print JSON with 2-space indentation (default is compact). |
46
+ | `--raw` | | Return the full, unpruned Figma API response. Large; avoid unless debugging. |
47
+ | `--depth <number>` | | Limit node tree traversal depth (e.g. `--depth 2` for an overview). |
48
+ | `--scale <1\|2\|3\|4>` | | Preview render scale (default: `2`). |
49
+ | `--format <png\|svg\|jpg\|pdf>` | | Preview image format (default: `png`). |
50
+ | `--no-variables` | | Skip querying `/variables/local`. |
51
+ | `--help` | `-h` | Show the help message. |
52
+
53
+ ## Output spec schema
54
+
55
+ Each node keeps only properties that differ from Figma defaults. Hidden layers are dropped. Pure vector groups collapse into a single `VECTOR` node with `isSvg: true`.
56
+
57
+ | Field | Meaning |
58
+ | :--- | :--- |
59
+ | `name`, `type` | Layer name and node type (`FRAME`, `INSTANCE`, `TEXT`, `VECTOR`, ...). |
60
+ | `bounds` | `{ width, height }` render dimensions. |
61
+ | `layoutMode`, `layoutWrap`, `primaryAxisAlignItems`, `counterAxisAlignItems` | Auto-layout direction and alignment. |
62
+ | `layoutGrow`, `layoutAlign`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight` | Child sizing constraints. |
63
+ | `padding` / `paddingToken`, `itemSpacing` / `itemSpacingToken` | Spacing values and bound tokens. |
64
+ | `cornerRadius` / `cornerRadiusToken`, `cornerRadii` | Uniform or per-corner radius. |
65
+ | `fills`, `strokes`, `effects`, `opacity` | Paints (hex `color` + optional `token`), borders, shadows/blurs. |
66
+ | `characters`, `typography` | Text content and `fontFamily`, `fontSize`, `fontWeight`, `lineHeightPx`, `letterSpacing`, `textAlignHorizontal`, `textAlignVertical`. |
67
+ | `component`, `props` | Master component `name`/`variant` and normalized instance props. |
68
+ | `children` | Child nodes. |
69
+ | `image` | Present when `-i` was used: preview `path`, or `error`. |
70
+
71
+ ### Resolved design tokens
72
+
73
+ When a layer is bound to Figma variables, the semantic token name is attached next to the computed fallback value:
74
+
75
+ ```json
76
+ {
77
+ "name": "Card Container",
78
+ "type": "FRAME",
79
+ "layoutMode": "VERTICAL",
80
+ "padding": { "top": 16, "right": 16, "bottom": 16, "left": 16 },
81
+ "paddingToken": "spacing/md",
82
+ "itemSpacing": 12,
83
+ "itemSpacingToken": "spacing/sm",
84
+ "cornerRadius": 8,
85
+ "cornerRadiusToken": "radii/lg",
86
+ "fills": [{ "type": "SOLID", "color": "#1877F2", "token": "colors/brand/primary" }]
87
+ }
88
+ ```
89
+
90
+ ### Normalized component instances
91
+
92
+ Figma property hashes (`Label#12:3`) become clean props linked to the master component:
93
+
94
+ ```json
95
+ {
96
+ "name": "Submit Button",
97
+ "type": "INSTANCE",
98
+ "component": { "name": "Button", "variant": "Variant=Primary, Size=Large" },
99
+ "props": { "variant": "Primary", "size": "Large", "hasIcon": true, "label": "Confirm Order" },
100
+ "bounds": { "width": 140, "height": 44 }
101
+ }
102
+ ```
103
+
104
+ ## Rate-limit gate internals
105
+
106
+ The script protects the file quota automatically. No agent action is needed beyond the Zero-Hammer rules in `SKILL.md`.
107
+
108
+ - **Sliding window**: at most 5 requests per minute per file key (Figma throttles at roughly 10/min).
109
+ - **Pacing**: at least 2.5 s between consecutive requests.
110
+ - **Circuit breaker**: after an HTTP 429, the lockout end time is stored in `~/.figma_ratelimit.json`. Later calls to that file key fail immediately with `FIGMA_CIRCUIT_BREAKER_ACTIVE` and send no network traffic, so the lockout is not extended.
@@ -1,213 +1,82 @@
1
1
  ---
2
2
  name: figma-to-code
3
- description: 'Directly convert Figma designs into clean, production-ready UI code in a single turn using the Figma REST API. Trigger this skill whenever the user provides a Figma link and asks to generate, code, build, or implement UI components directly without an intermediate specification review.'
3
+ description: 'Converts a Figma frame or component directly into production-ready UI code in a single pass, fetching a compact design-token-aware node tree from the Figma REST API and reusing the host project components and styles. Use when the user shares a figma.com link and explicitly asks to build, code, or implement it right away, without an intermediate spec review step. Supports React, Vue, Svelte, Angular, and plain HTML/CSS.'
4
4
  ---
5
5
 
6
- # Figma To Code Skill
6
+ # Figma To Code
7
7
 
8
- Directly convert Figma designs into clean, production-ready UI components in a single turn.
8
+ Fetches a compact, design-token-aware node tree for a Figma frame and immediately builds the component in the host project, reusing its existing components and styles.
9
9
 
10
- This skill connects to the Figma REST API, extracts a compact design-system-aware AST, resolves variables into semantic design tokens, and immediately generates the target component code grounded in your project's existing design system and components.
10
+ Requires Node.js >= 16.7. The scripts have zero dependencies (no `npm install`).
11
11
 
12
- ---
13
-
14
- ## Strict Guardrails: No Browser Scraping / Automation
12
+ ## Boundaries
15
13
 
16
- > [!CAUTION]
17
- > **NEVER use browser tools (Playwright, Puppeteer, Chrome DevTools, `browser_navigate`, `read_browser_page`) on Figma URLs.**
18
- >
19
- > 1. **Figma Canvas is WebGL/Wasm**: Figma renders design canvas elements inside an HTML5 `<canvas>` via WebAssembly. There are NO inspectable HTML DOM elements for frames, layers, texts, or styles. Browser automation cannot extract Figma nodes or properties.
20
- > 2. **Never search for local browser binaries**: Do not search OS application directories (e.g., `/Applications`, `Program Files`, `/usr/bin`) or run browser automation scripts.
21
- > 3. **API Errors Are Final**: If `fetch_figma.js` returns an API error (e.g., 401 Unauthorized, 403 Forbidden, or 429 Rate Limited), **report the error directly to the user**. Guide them to check their `FIGMA_ACCESS_TOKEN`, permissions, or wait out rate limits. Do NOT attempt browser scraping fallbacks.
22
-
23
- ---
14
+ - **Never open Figma URLs with browser tools** (Playwright, Puppeteer, Chrome DevTools). The Figma canvas is WebGL, so there is no DOM to read. Do not search for local browser binaries.
15
+ - **API errors are final**: report them to the user. Never fall back to scraping.
16
+ - If the user only wants to inspect, document, or plan the design, stop and suggest the `figma-extractor` skill instead.
24
17
 
25
- ## Built-in Rate-Limit Gate & Circuit Breaker
18
+ ## Workflow
26
19
 
27
- To protect your Figma file quota and prevent lockout penalties, `fetch_figma.js` enforces an automatic safety gate:
28
- * **Max 5 requests per minute** per file key (sliding window limit).
29
- * **2.5s inter-request pacing** between consecutive requests.
30
- * **Persistent Circuit Breaker**: If Figma returns HTTP 429, the script records the lockout time locally in `.figma_ratelimit.json` inside the user's home directory. All future calls to that file key are **immediately blocked with zero network traffic**, preventing Figma from extending the lockout penalty.
31
-
32
- ### Agent Behavioral Rules (Zero-Hammer Protocol)
33
- 1. **Single-Shot Execution**: Run `fetch_figma.js` **once** per target frame or component.
34
- 2. **Never Retry on Failure**: If `fetch_figma.js` returns an error, **DO NOT retry in a loop**. Report the error directly to the user.
35
- 3. **Handling `FIGMA_CIRCUIT_BREAKER_ACTIVE`**: If the circuit breaker trips, inform the user that the file key is on cooldown, and suggest duplicating the file in Figma Drafts (Right-click $\rightarrow$ **Duplicate**) to get a fresh URL.
36
-
37
- ---
20
+ Copy this checklist and track your progress:
38
21
 
39
- ## Prerequisites
40
-
41
- A Figma Access Token (Personal Access Token or OAuth Token) is required.
42
-
43
- Configure it using either:
44
- 1. **Environment Variable**:
45
- - **macOS / Linux**: `export FIGMA_ACCESS_TOKEN="figd_your_token_here"` (or `FIGMA_TOKEN`)
46
- - **Windows (PowerShell)**: `[Environment]::SetEnvironmentVariable("FIGMA_ACCESS_TOKEN", "figd_your_token_here", "User")` or `$env:FIGMA_ACCESS_TOKEN="figd_your_token_here"` in `$PROFILE`
47
- 2. **Workspace `.env` File**:
48
- ```env
49
- FIGMA_ACCESS_TOKEN=figd_your_token_here
50
- ```
51
-
52
- ### Corporate Proxy & SSL Certificates
53
- If you are behind a corporate proxy or firewall with self-signed SSL certificates, enable SSL verification bypass:
54
- ```env
55
- FIGMA_IGNORE_SSL=true
22
+ ```
23
+ Build Progress:
24
+ - [ ] 1. Discover the host project (stack, UI primitives, tokens, icons)
25
+ - [ ] 2. Fetch the node tree (once)
26
+ - [ ] 3. Build the component following the build rules
27
+ - [ ] 4. Validate and fix
56
28
  ```
57
29
 
58
- ## Tier 1 Quota Conservation: AST-Only by Default
59
-
60
- > [!IMPORTANT]
61
- > **Figma Starter plans enforce a strict limit of 20 Tier 1 requests/month.**
62
- > Both `GET /v1/files/:key/nodes` and `GET /v1/images/:key` count as Tier 1 endpoints.
63
- >
64
- > 1. **Default to AST-only extraction**: Extracting AST without `-i` consumes **only 1 Tier 1 call**. The JSON AST contains 100% of layout rules (flexbox, padding, gap), dimensions, hex colors, corner radii, and text content needed for code generation.
65
- > 2. **DO NOT pass `-i` / `--image` by default**: Only add `-i` if the user explicitly requests downloading a visual preview screenshot.
66
-
67
- ---
68
-
69
- ## Agent Execution Instructions
30
+ **1. Discover the host project**: check `package.json` (framework, styling, icon library), reusable components in `components/ui/` or `src/components/`, and theme files (`tailwind.config.*`, `theme.css`, `globals.css`).
70
31
 
71
- To extract and build UI from a Figma URL, run `fetch_figma.js` from this skill's `scripts/` directory:
32
+ **2. Fetch the node tree** (1 Tier 1 API call; JSON is printed to stdout):
72
33
 
73
34
  ```bash
74
- # Recommended: Extract compact AST (1 Tier 1 call)
75
35
  node "<skill-dir>/scripts/fetch_figma.js" "<FigmaURL>"
76
-
77
- # Optional: With companion preview image (2 Tier 1 calls)
78
- node "<skill-dir>/scripts/fetch_figma.js" "<FigmaURL>" -i
79
36
  ```
80
37
 
81
- **Resolving `<skill-dir>` (Agent-Agnostic)**:
82
- Substitute `<skill-dir>` with the directory where this skill is installed — **never guess another agent's folder** (always keep double quotes around the script path for Windows/macOS/Linux compatibility):
83
- - **Standard Skills (`SKILL.md`)**: `<skill-dir>` is the exact parent directory of this `SKILL.md` file.
84
- - **Cursor Rule (`.cursor/rules/figma-to-code.mdc`)**: `<skill-dir>` is the sibling `.cursor/skills/figma-to-code` directory (replace `rules/figma-to-code.mdc` with `skills/figma-to-code`).
38
+ For large frames, add `--shallow-instances` (collapses instance internals into props) or `--depth 2`. All flags, the output schema, token setup per OS, and proxy options: see [REFERENCE.md](REFERENCE.md) (located at `<skill-dir>/REFERENCE.md`).
85
39
 
86
- ---
87
-
88
- ## Usage & Command Formats
40
+ **3. Build**: follow the [Build rules](#build-rules), adapting syntax to the detected stack.
89
41
 
90
- ### 1. Basic One-Shot Code Generation
42
+ **4. Validate and fix**
91
43
 
92
- ```bash
93
- # Standard extraction (1 Tier 1 call - recommended)
94
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name?node-id=4023-474"
44
+ 1. Run the project's existing checks: `typecheck` or `lint` scripts from `package.json`, or `npx tsc --noEmit` when TypeScript is already installed. Never install new dependencies to do this.
45
+ 2. If checks fail in the files you created or changed, fix them and run the checks again. Repeat until they pass.
46
+ 3. Report pre-existing failures in other files instead of fixing them.
47
+ 4. If a preview image was downloaded (`image.path` in the output), compare it visually with the result.
95
48
 
96
- # Optional: With preview image (2 Tier 1 calls)
97
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name?node-id=4023-474" -i
49
+ ## Build rules
98
50
 
99
- # Collapse internal layers of component instances into props (guides agent to reuse existing components)
100
- node "<skill-dir>/scripts/fetch_figma.js" "https://www.figma.com/design/:fileKey/:name?node-id=4023-474" --shallow-instances
101
- ```
51
+ 1. **Reuse existing components (no div soup)**: when an `INSTANCE` matches an existing component, import and render it with the spec props (`<Button variant="primary" size="large" hasIcon>Confirm Order</Button>`). Never rebuild existing primitives from raw elements.
52
+ 2. **Layout**: `layoutMode: "HORIZONTAL"` → flex row; `"VERTICAL"` → flex column; `itemSpacing` → `gap`; `padding` → padding; `primaryAxisAlignItems` / `counterAxisAlignItems` → `justify-*` / `items-*`. Prefer the matching `*Token` when present.
53
+ 3. **Colors and typography**: never guess values. Use the semantic `token` when present (mapped to the project CSS variable or Tailwind class), otherwise the exact hex `color`. Map font size, weight, and line height to existing typography tokens or classes.
54
+ 4. **Icons and vectors** (`VECTOR` nodes, `isSvg: true`, or icon instances): normalize the name by stripping `icon/`, `ic_`, `ico-` (`icon/search` → `search`), then resolve in order:
55
+ 1. Local assets or components in `components/icons/`, `src/assets/`, or `public/` only (no repo-wide searches).
56
+ 2. The icon library installed in `package.json` (e.g. `import { Search } from 'lucide-react'`).
57
+ 3. An accessible placeholder with a `TODO: Missing icon 'search'` comment. Never invent raw SVG `<path d="...">` coordinates.
58
+ 5. **Image fills** (`fills: [{ type: "IMAGE" }]`): apply only the spec styling (size, radius, `scaleMode: "FILL"` → `object-cover`, `"FIT"` → `object-contain`). Never fetch or invent image URLs. Render `<img src="" alt="...">` with a `TODO` comment naming the layer and its size.
102
59
 
103
- ### 2. CLI Flags Reference
104
-
105
- | Flag | Shorthand | Description |
106
- | :--- | :--- | :--- |
107
- | `--image`, `--download-image` | `-i` | Download and save rendered preview image from Figma (Tier 1 call; optional). |
108
- | `--image-path <path>` | `-o <path>` | Custom local file path to save preview image (implies `--image`). |
109
- | `--tokens`, `--variables` | | Output only the design token dictionary (colors, spacing, radii) for theme setup. |
110
- | `--shallow-instances` | | Collapse internal sub-layers of component instances into clean props. |
111
- | `--pretty` | | Pretty-print JSON with 2-space indentation (default is compact single-line JSON). |
112
- | `--include-tokens` | | Include full design tokens dictionary alongside node AST. |
113
- | `--include-ids` | | Retain internal Figma node IDs on each node in the tree. |
114
- | `--raw` | | Return full, unpruned raw Figma API AST. |
115
- | `--depth <number>` | | Limit node tree traversal depth (e.g. `--depth 2` for top-level overview). |
116
- | `--scale <1\|2\|3\|4>` | | Render resolution multiplier for preview images (default: `2`). |
117
- | `--format <png\|svg\|jpg>` | | Rendered image file format (default: `png`). |
118
- | `--no-variables` | | Skip querying `/variables/local`. |
119
- | `--help` | `-h` | Show help message. |
60
+ ## Resolving `<skill-dir>`
120
61
 
121
- ---
62
+ Substitute `<skill-dir>` with the directory where this skill is installed. Never guess another agent's folder, and keep the double quotes around the script path (Windows/macOS/Linux):
122
63
 
123
- ## Output Structure & Design-System Awareness
124
-
125
- ### 1. Resolved Design Tokens
126
- When a layer uses Figma variables (design tokens), the extractor attaches semantic token names alongside the computed values:
127
-
128
- ```json
129
- {
130
- "name": "Card Container",
131
- "type": "FRAME",
132
- "layoutMode": "VERTICAL",
133
- "padding": { "top": 16, "right": 16, "bottom": 16, "left": 16 },
134
- "paddingToken": "spacing/md",
135
- "itemSpacing": 12,
136
- "itemSpacingToken": "spacing/sm",
137
- "cornerRadius": 8,
138
- "cornerRadiusToken": "radii/lg",
139
- "fills": [
140
- {
141
- "type": "SOLID",
142
- "color": "#1877F2",
143
- "token": "colors/brand/primary"
144
- }
145
- ]
146
- }
147
- ```
64
+ - **Standard skills (`SKILL.md`)**: the parent directory of this `SKILL.md` file.
65
+ - **Cursor rule (`.cursor/rules/figma-to-code.mdc`)**: the sibling `.cursor/skills/figma-to-code` directory.
148
66
 
149
- ### 2. Normalized Component Instances & Props
150
- When an `INSTANCE` node is present, internal property hashes are converted into clean JavaScript props and linked to the master component name:
151
-
152
- ```json
153
- {
154
- "name": "Submit Button",
155
- "type": "INSTANCE",
156
- "component": {
157
- "name": "Button",
158
- "variant": "Variant=Primary, Size=Large"
159
- },
160
- "props": {
161
- "variant": "Primary",
162
- "size": "Large",
163
- "hasIcon": true,
164
- "label": "Confirm Order"
165
- },
166
- "bounds": { "width": 140, "height": 44 }
167
- }
168
- ```
67
+ ## Quota rules (Zero-Hammer Protocol)
169
68
 
170
- ---
69
+ The script enforces a local rate gate and a persistent circuit breaker, but the agent must also follow these rules:
171
70
 
172
- ## How to Build Components from the Extracted Data
173
-
174
- When synthesizing code from the output (always adapting syntax, attributes, and styling conventions to the project's detected stack — e.g., React, Vue, Svelte, Angular, or plain HTML/CSS):
175
-
176
- 1. **Using Existing UI Components**:
177
- - For `INSTANCE` nodes with resolved `component.name` and `props`:
178
- - Check if your codebase already has this component (e.g. `<Button />`, `<Input />`, `<Modal />`).
179
- - Directly render: `<Button variant="primary" size="large" hasIcon>Confirm Order</Button>` instead of building raw HTML divs.
180
- 2. **Applying Semantic Design Tokens**:
181
- - When a `token` is present (e.g., `colors/brand/primary`, `spacing/md`):
182
- - Map to your project's Tailwind class (`bg-brand-primary`, `p-md`, `rounded-lg`) or CSS variable (`var(--color-brand-primary)`).
183
- - Avoid hardcoding hex colors or pixel values when tokens are available.
184
- 3. **Layout & Flexbox**:
185
- - `HORIZONTAL` $\rightarrow$ `flex flex-row` (`display: flex; flex-direction: row;`).
186
- - `VERTICAL` $\rightarrow$ `flex flex-col` (`display: flex; flex-direction: column;`).
187
- - `itemSpacing` $\rightarrow$ CSS `gap`.
188
- - `primaryAxisAlignItems` & `counterAxisAlignItems` $\rightarrow$ `justify-*` and `items-*`.
189
- 4. **Icon & Vector Resolution Hierarchy**:
190
- - For `VECTOR` nodes or icon instances, normalize the name (strip prefixes `icon/`, `ic_`, `ico-`).
191
- - **Step 1 (Targeted Local Assets/Components)**: Look for matching files in `components/icons/`, `src/assets/`, or `public/` (e.g. `<SearchIcon />`, `/icons/search.svg`). Avoid unbounded repo searches.
192
- - **Step 2 (Installed Icon Library)**: If not found, import from packages in `package.json` (e.g., `lucide-react`, `@heroicons/react`).
193
- - **Step 3 (Semantic Fallback)**: If not found, render an accessible placeholder (`<span className="..." aria-hidden="true" />`) with a `TODO: Missing icon 'name'` comment. Never hallucinate raw SVG `<path d="...">` coordinates.
194
- 5. **Image Layer Handling (`fills: [{ type: "IMAGE" }]`)**:
195
- - Focus exclusively on applying the exact styling from the Figma spec: dimensions (`width`, `height`), border radius (`rounded-*`), and scale mode (`scaleMode: "FILL"` $\rightarrow$ `object-cover`, `"FIT"` $\rightarrow$ `object-contain`).
196
- - Do **NOT** attempt to resolve, fetch, or hallucinate image files or external URLs (never invent Unsplash or third-party links).
197
- - Render a standard `<img>` tag with `src=""` and a concise `TODO` comment specifying the target image layer.
198
- 6. **Visual Verification**:
199
- - Inspect the downloaded preview image (`output.image.path`) to ensure pixel-perfect fidelity.
71
+ 1. Run `fetch_figma.js` **once** per target frame or component. **Never retry in a loop.**
72
+ 2. **Do not pass `-i`** unless the user explicitly requests a preview image. The JSON already contains layout, dimensions, colors, radii, typography, and text.
73
+ 3. Figma Starter plans and View seats have very small monthly Tier 1 quotas, so every call matters.
200
74
 
201
- ---
75
+ ## Errors
202
76
 
203
- ## Error Handling & Troubleshooting
204
-
205
- - **Token Expired / Missing (`FIGMA_TOKEN_EXPIRED_OR_INVALID` / `isTokenExpiredOrInvalid`)**:
206
- - Alert the user that their Figma access token is missing, invalid, or expired.
207
- - Instruct the user to create a token in **Figma Settings $\rightarrow$ Personal Access Tokens** and configure `FIGMA_ACCESS_TOKEN` in their environment or workspace `.env` file.
208
- - **Node Not Found**:
209
- - Alert the user that the node ID could not be found in the specified file.
210
- - **Corporate Proxy / Self-Signed SSL (`FIGMA_SSL_CERTIFICATE_ERROR`)**:
211
- - Instruct the user to add `FIGMA_IGNORE_SSL=true` to `.env` or set it in their environment.
212
- - **Rate Limited (`FIGMA_RATE_LIMIT_EXCEEDED` / `FIGMA_CIRCUIT_BREAKER_ACTIVE`)**:
213
- - Figma REST API has strict per-minute and monthly rate limits. If rate limited or the circuit breaker trips, report the cooldown to the user and suggest duplicating the file in Figma Drafts to get a fresh URL.
77
+ | Error code | Action |
78
+ | :--- | :--- |
79
+ | `FIGMA_ACCESS_TOKEN is not set` / `FIGMA_TOKEN_EXPIRED_OR_INVALID` | Tell the user the token is missing, invalid, or expired. They create one in **Figma Settings → Personal Access Tokens** and set `FIGMA_ACCESS_TOKEN` (setup per OS in REFERENCE.md). |
80
+ | Node not found | Report that the `node-id` does not exist in the file. |
81
+ | `FIGMA_SSL_CERTIFICATE_ERROR` | Corporate proxy or self-signed certificate: suggest `FIGMA_IGNORE_SSL=true` in `.env`. |
82
+ | `FIGMA_RATE_LIMIT_EXCEEDED` / `FIGMA_CIRCUIT_BREAKER_ACTIVE` | Report the cooldown. Suggest duplicating the file in Figma Drafts (Right-click → **Duplicate**) for a fresh URL, or exporting the selection with the companion [Figma Node JSON Extractor](https://www.figma.com/community/plugin/1691244420692136789/figma-node-json-extractor) plugin and building from that JSON. |
@@ -1382,6 +1382,7 @@ Usage:
1382
1382
  Options:
1383
1383
  --image, -i Download rendered preview image from Figma (Tier 1 call; optional)
1384
1384
  --image-path, -o <path> Target path for saved preview image (implies --image)
1385
+ --force, -f Ignore existing local preview image and re-fetch from Figma
1385
1386
  --tokens, --variables Export only the design token dictionary (colors, spacing, radii)
1386
1387
  --shallow-instances Collapse internal layers of component instances into props
1387
1388
  --include-tokens Include complete tokens dictionary in node output
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pedroab0/skills",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Curated collection of modular, production-ready skills for AI coding agents (Claude Code, Cursor, Kiro, OpenCode, Antigravity)",
5
5
  "bin": {
6
6
  "skills": "bin/cli.js",
@@ -11,7 +11,7 @@
11
11
  "node": ">=16.7.0"
12
12
  },
13
13
  "scripts": {
14
- "test": "node figma-extractor/scripts/test_fetch_figma.js && node figma-to-code/scripts/test_fetch_figma.js && node figma-node-builder/scripts/test_inspect_spec.js && node test/test_cli.js",
14
+ "test": "node figma-extractor/scripts/test_fetch_figma.js && node figma-to-code/scripts/test_fetch_figma.js && node figma-node-builder/scripts/test_inspect_spec.js && node test/test_cli.js && node test/test_skills.js",
15
15
  "install-skills": "node ./bin/cli.js"
16
16
  },
17
17
  "repository": {