@pedroab0/skills 1.1.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.
@@ -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. |