figma-code-agent 1.0.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.
Files changed (34) hide show
  1. package/README.md +133 -0
  2. package/bin/install.js +328 -0
  3. package/knowledge/README.md +62 -0
  4. package/knowledge/css-strategy.md +973 -0
  5. package/knowledge/design-to-code-assets.md +855 -0
  6. package/knowledge/design-to-code-layout.md +929 -0
  7. package/knowledge/design-to-code-semantic.md +1085 -0
  8. package/knowledge/design-to-code-typography.md +1003 -0
  9. package/knowledge/design-to-code-visual.md +1145 -0
  10. package/knowledge/design-tokens-variables.md +1261 -0
  11. package/knowledge/design-tokens.md +960 -0
  12. package/knowledge/figma-api-devmode.md +894 -0
  13. package/knowledge/figma-api-plugin.md +920 -0
  14. package/knowledge/figma-api-rest.md +742 -0
  15. package/knowledge/figma-api-variables.md +848 -0
  16. package/knowledge/figma-api-webhooks.md +876 -0
  17. package/knowledge/payload-blocks.md +1184 -0
  18. package/knowledge/payload-figma-mapping.md +1210 -0
  19. package/knowledge/payload-visual-builder.md +1004 -0
  20. package/knowledge/plugin-architecture.md +1176 -0
  21. package/knowledge/plugin-best-practices.md +1206 -0
  22. package/knowledge/plugin-codegen.md +1313 -0
  23. package/package.json +31 -0
  24. package/skills/README.md +103 -0
  25. package/skills/audit-plugin/SKILL.md +244 -0
  26. package/skills/build-codegen-plugin/SKILL.md +279 -0
  27. package/skills/build-importer/SKILL.md +320 -0
  28. package/skills/build-plugin/SKILL.md +199 -0
  29. package/skills/build-token-pipeline/SKILL.md +363 -0
  30. package/skills/ref-html/SKILL.md +290 -0
  31. package/skills/ref-layout/SKILL.md +150 -0
  32. package/skills/ref-payload-block/SKILL.md +415 -0
  33. package/skills/ref-react/SKILL.md +222 -0
  34. package/skills/ref-tokens/SKILL.md +347 -0
@@ -0,0 +1,363 @@
1
+ ---
2
+ name: build-token-pipeline
3
+ description: Build a pipeline that syncs Figma design tokens to code. Use this skill when the user needs automated or on-demand synchronization of Figma Variables into CSS Custom Properties, Tailwind config, SCSS variables, or other token formats.
4
+ ---
5
+
6
+ @knowledge/figma-api-variables.md
7
+ @knowledge/design-tokens.md
8
+ @knowledge/design-tokens-variables.md
9
+ @knowledge/figma-api-webhooks.md
10
+ @knowledge/css-strategy.md
11
+
12
+ ## Objective
13
+
14
+ Help the user build a token synchronization pipeline that reads Figma Variables (or extracts tokens from file data) and outputs production-ready CSS Custom Properties, Tailwind config, SCSS variables, or other formats. The skill covers the full pipeline: trigger mechanism (webhook, CLI, CI/CD), API access, variable resolution, alias chain following, mode classification, naming, multi-format rendering, and drift detection.
15
+
16
+ ## Input
17
+
18
+ The user provides their token pipeline requirements as `$ARGUMENTS`. This may be:
19
+
20
+ - A description of the desired sync workflow (e.g., "sync Figma Variables to CSS and Tailwind on every library publish")
21
+ - A path to an existing token pipeline to enhance
22
+ - Specific requirements (output formats, mode handling, naming conventions)
23
+ - Questions about Variables API access or Enterprise requirements
24
+
25
+ If the input is a path, read the project files before proceeding. If the input is a description, proceed directly to Phase 1.
26
+
27
+ ## Process
28
+
29
+ ### Phase 1 — Assess
30
+
31
+ Determine the pipeline's scope, trigger mechanism, and constraints.
32
+
33
+ **Sync trigger:**
34
+ - **Webhook-driven**: automatic sync on Figma library publish events. Requires a server endpoint to receive `LIBRARY_PUBLISH` webhooks. Best for continuous sync.
35
+ - **CLI command**: manual `npm run sync-tokens` or similar. Best for controlled releases.
36
+ - **CI/CD job**: runs in GitHub Actions, GitLab CI, etc. Triggered on schedule or manual dispatch. Best for teams that want PR-based token review.
37
+ - **Combination**: webhook triggers a CI job, or CLI triggers a CI job
38
+
39
+ **Output formats (can select multiple):**
40
+ - **CSS Custom Properties** — `:root` block with mode-aware overrides. The primary format.
41
+ - **Tailwind config** — `theme.extend` referencing CSS variables via `var()`. For Tailwind projects.
42
+ - **SCSS variables** — `$variable` declarations referencing CSS Custom Properties. For SCSS projects.
43
+ - **JSON** — Flat or nested token structure. For tools like Style Dictionary, Tokens Studio, or custom consumers.
44
+ - **TypeScript** — Type-safe token constants. For programmatic token access.
45
+
46
+ **Variable scope:**
47
+ - All collections and variables (full sync)
48
+ - Filtered by collection name (e.g., only "Primitives" and "Semantic")
49
+ - Filtered by variable scope (e.g., only `ALL_SCOPES` or specific scopes like `FRAME_FILL`, `TEXT_CONTENT`)
50
+
51
+ **API access:**
52
+ - **Variables API** (Enterprise plan required): `GET /v1/files/:key/variables/local` with `file_variables:read` scope. Provides structured variable collections, modes, alias chains, scopes.
53
+ - **Fallback** (any plan): file traversal + threshold-based promotion. Reads node properties, detects repeated values, promotes to tokens. Less structured but works without Enterprise.
54
+ - Assess which access level the user has and plan accordingly. Both paths should produce equivalent CSS output.
55
+
56
+ **Mode strategy:**
57
+ - How many modes does each collection have?
58
+ - What do the modes represent?
59
+ - **Theme modes** (Light/Dark, Brand A/Brand B) → `@media (prefers-color-scheme)` + `[data-theme]` selectors
60
+ - **Breakpoint modes** (Mobile/Tablet/Desktop) → `@media (min-width)` with mobile-first ascending order
61
+ - **Density modes** (Compact/Default/Comfortable) → `[data-density]` attribute selector
62
+ - Which mode is the default (base `:root`)?
63
+
64
+ Report the assessment to the user before proceeding.
65
+
66
+ ### Phase 2 — Recommend
67
+
68
+ Based on the assessment, recommend the pipeline architecture.
69
+
70
+ **Mode rendering strategy:**
71
+
72
+ For **theme modes**:
73
+ ```css
74
+ /* Base (Light mode — default) */
75
+ :root { --color-primary: hsl(220, 90%, 56%); }
76
+
77
+ /* System preference */
78
+ @media (prefers-color-scheme: dark) {
79
+ :root { --color-primary: hsl(220, 90%, 65%); }
80
+ }
81
+
82
+ /* Class-based override (progressive enhancement) */
83
+ [data-theme="dark"] { --color-primary: hsl(220, 90%, 65%); }
84
+ ```
85
+ - Render BOTH `@media (prefers-color-scheme)` AND `[data-theme]` for each non-default theme mode
86
+ - Only emit tokens whose values differ from the base mode in overrides
87
+
88
+ For **breakpoint modes**:
89
+ ```css
90
+ /* Base (Mobile — smallest, default) */
91
+ :root { --spacing-section: 1.5rem; }
92
+
93
+ @media (min-width: 768px) {
94
+ :root { --spacing-section: 2rem; }
95
+ }
96
+
97
+ @media (min-width: 1024px) {
98
+ :root { --spacing-section: 3rem; }
99
+ }
100
+ ```
101
+ - Mobile-first: smallest breakpoint is base, larger breakpoints add overrides
102
+ - Ascending `min-width` order
103
+ - Only emit changed tokens in each breakpoint
104
+
105
+ **Naming convention:**
106
+ - Preserve Figma variable path as the name basis: `color/primary/500` → `--color-primary-500`
107
+ - Slash-separated paths become hyphen-separated CSS property names
108
+ - Category prefixes maintained: `--color-*`, `--spacing-*`, `--font-*`, `--radius-*`, `--shadow-*`
109
+ - For file traversal fallback: use HSL classification for colors, base-unit detection for spacing (see `knowledge/design-tokens.md`)
110
+
111
+ **Alias chain resolution:**
112
+ - Variables can alias other variables (`VariableAlias` type)
113
+ - Chains can be multi-level: `semantic/primary` → `brand/blue-500` → `primitive/blue-500`
114
+ - Resolve to terminal value for each mode
115
+ - In CSS output, decide whether to preserve alias relationships as `var()` references or flatten to resolved values:
116
+ - **Preserve aliases** (recommended): `--color-primary: var(--color-blue-500);` — maintains semantic relationships, enables override
117
+ - **Flatten**: `--color-primary: hsl(220, 90%, 56%);` — simpler but loses relationship
118
+
119
+ **Drift detection:**
120
+ - Compare code tokens (parsed from existing CSS/JSON) against Figma source
121
+ - Report: added tokens (in Figma but not code), removed tokens (in code but not Figma), changed values
122
+ - Output as a structured diff report or GitHub PR comment
123
+
124
+ **Webhook setup** (if webhook trigger):
125
+ - Listen for `LIBRARY_PUBLISH` event type
126
+ - Verify passcode from webhook payload (`passcode` field must match configured secret)
127
+ - Debounce: if multiple publishes arrive within 30 seconds, process only the latest
128
+ - Retry handling: Figma retries failed webhook deliveries, so handlers must be idempotent
129
+
130
+ **Fallback strategy** (when Variables API unavailable):
131
+ - Traverse file nodes via REST API
132
+ - Collect repeated values across 5 domains (colors, spacing, typography, effects, breakpoints)
133
+ - Promote values used 2+ times to tokens (threshold-based promotion)
134
+ - Apply HSL color classification and spacing base-unit detection for naming
135
+ - Document the difference in output quality between Variables API and fallback paths
136
+
137
+ Present the recommendations and confirm before implementing.
138
+
139
+ ### Phase 3 — Implement
140
+
141
+ Generate the token pipeline code.
142
+
143
+ **1. Sync script (main entry point):**
144
+
145
+ ```typescript
146
+ // scripts/sync-tokens.ts (or src/tokens/sync.ts)
147
+ async function syncTokens(options: SyncOptions): Promise<SyncResult> {
148
+ // 1. Fetch variables from Figma (or fallback to file traversal)
149
+ // 2. Classify collection modes (theme vs breakpoint)
150
+ // 3. Resolve alias chains to terminal values
151
+ // 4. Assign semantic names (preserve Figma paths or apply HSL/scale naming)
152
+ // 5. Render to output formats (CSS, Tailwind, SCSS, JSON)
153
+ // 6. Run drift detection against existing token files
154
+ // 7. Write output files
155
+ // 8. Return sync report (added/changed/removed tokens)
156
+ }
157
+ ```
158
+
159
+ **2. Variable resolution module:**
160
+
161
+ ```typescript
162
+ // src/tokens/resolver.ts
163
+ function resolveVariables(
164
+ variables: Variable[],
165
+ collections: VariableCollection[]
166
+ ): ResolvedTokenMap {
167
+ // For each variable:
168
+ // - Classify the parent collection's modes
169
+ // - For each mode:
170
+ // - Follow alias chains to terminal value
171
+ // - Convert COLOR values to HSL
172
+ // - Convert FLOAT values to rem (divide by 16)
173
+ // - Determine which modes differ from the default
174
+ }
175
+ ```
176
+
177
+ - Follow alias chains: if value is `{ type: 'VARIABLE_ALIAS', id: '...' }`, look up the referenced variable and recurse
178
+ - Handle circular alias detection (guard against infinite loops)
179
+ - Classify modes using name heuristics from `knowledge/design-tokens-variables.md`
180
+
181
+ **3. Output renderers:**
182
+
183
+ **CSS renderer:**
184
+ ```typescript
185
+ // src/tokens/renderers/css.ts
186
+ function renderCSS(tokens: ResolvedTokenMap): string {
187
+ // :root block with default mode values
188
+ // Theme mode overrides: @media (prefers-color-scheme) + [data-theme]
189
+ // Breakpoint mode overrides: @media (min-width) ascending
190
+ // Only tokens that differ from base mode in overrides
191
+ // HSL format for colors, rem for spacing/typography
192
+ // Comments with original Figma variable paths
193
+ }
194
+ ```
195
+
196
+ **Tailwind renderer:**
197
+ ```typescript
198
+ // src/tokens/renderers/tailwind.ts
199
+ function renderTailwind(tokens: ResolvedTokenMap): string {
200
+ // theme.extend configuration
201
+ // All values reference var() — never hardcoded
202
+ // Colors → theme.extend.colors
203
+ // Spacing → theme.extend.spacing
204
+ // Typography → theme.extend.fontFamily, fontSize
205
+ // Effects → theme.extend.borderRadius, boxShadow
206
+ }
207
+ ```
208
+
209
+ **SCSS renderer:**
210
+ ```typescript
211
+ // src/tokens/renderers/scss.ts
212
+ function renderSCSS(tokens: ResolvedTokenMap): string {
213
+ // $variable declarations referencing var() CSS Custom Properties
214
+ // Organized by category with section comments
215
+ }
216
+ ```
217
+
218
+ **JSON renderer:**
219
+ ```typescript
220
+ // src/tokens/renderers/json.ts
221
+ function renderJSON(tokens: ResolvedTokenMap): object {
222
+ // Nested structure preserving collection/group hierarchy
223
+ // Each token: { value, type, description, modes }
224
+ // Compatible with Style Dictionary or Tokens Studio input
225
+ }
226
+ ```
227
+
228
+ **4. Webhook handler (if webhook trigger):**
229
+
230
+ ```typescript
231
+ // src/api/webhook.ts (or pages/api/figma-webhook.ts)
232
+ export async function handleWebhook(request: Request): Promise<Response> {
233
+ // 1. Verify passcode matches configured secret
234
+ // 2. Check event_type === 'LIBRARY_PUBLISH'
235
+ // 3. Debounce (skip if another sync started within 30 seconds)
236
+ // 4. Extract file_key from payload
237
+ // 5. Call syncTokens({ fileKey, ... })
238
+ // 6. Return 200 (Figma expects quick response)
239
+ }
240
+ ```
241
+
242
+ - Passcode verification: compare `request.body.passcode` against environment variable
243
+ - Idempotent: safe to process the same event multiple times
244
+ - Quick response: return 200 immediately, process sync asynchronously if needed
245
+
246
+ **5. Drift detection module:**
247
+
248
+ ```typescript
249
+ // src/tokens/drift.ts
250
+ function detectDrift(
251
+ currentTokens: ResolvedTokenMap,
252
+ existingFile: string
253
+ ): DriftReport {
254
+ // Parse existing token file (CSS, JSON, or SCSS)
255
+ // Compare against current Figma tokens
256
+ // Categorize differences: added, removed, changed (with old + new values)
257
+ // Return structured report
258
+ }
259
+ ```
260
+
261
+ **6. CI/CD integration (if CI/CD trigger):**
262
+
263
+ ```yaml
264
+ # .github/workflows/sync-tokens.yml
265
+ name: Sync Design Tokens
266
+ on:
267
+ workflow_dispatch:
268
+ schedule:
269
+ - cron: '0 9 * * 1' # Weekly Monday 9am
270
+
271
+ jobs:
272
+ sync:
273
+ runs-on: ubuntu-latest
274
+ steps:
275
+ - uses: actions/checkout@v4
276
+ - uses: actions/setup-node@v4
277
+ - run: npm ci
278
+ - run: npm run sync-tokens
279
+ env:
280
+ FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
281
+ FIGMA_FILE_KEY: ${{ vars.FIGMA_FILE_KEY }}
282
+ - uses: peter-evans/create-pull-request@v6
283
+ with:
284
+ title: 'Update design tokens from Figma'
285
+ body: 'Automated token sync from Figma Variables'
286
+ branch: tokens/auto-sync
287
+ ```
288
+
289
+ ### Phase 4 — Validate
290
+
291
+ Verify the token pipeline produces correct output.
292
+
293
+ **Variable resolution:**
294
+ - [ ] Alias chains fully resolved to terminal values (no unresolved aliases)
295
+ - [ ] Circular alias detection prevents infinite loops
296
+ - [ ] All modes for each collection are processed
297
+ - [ ] Mode classification correct (theme vs breakpoint vs unknown)
298
+ - [ ] Default mode identified correctly (Light for themes, Mobile for breakpoints)
299
+
300
+ **CSS output:**
301
+ - [ ] Theme overrides use BOTH `@media (prefers-color-scheme)` AND `[data-theme]` selectors
302
+ - [ ] Breakpoint overrides use `@media (min-width)` in ascending mobile-first order
303
+ - [ ] Only tokens with differing values appear in mode overrides
304
+ - [ ] Colors in HSL format
305
+ - [ ] Spacing and font sizes in rem units (with px comments)
306
+ - [ ] Comments show original Figma variable paths
307
+
308
+ **Tailwind output:**
309
+ - [ ] All values reference `var()` — no hardcoded values
310
+ - [ ] Token categories map to correct Tailwind theme keys
311
+ - [ ] Config is a valid `theme.extend` snippet (not a full config replacement)
312
+
313
+ **Pipeline integrity:**
314
+ - [ ] Auth scope includes `file_variables:read` (for Variables API path)
315
+ - [ ] Fallback path works when Variables API returns 403 (non-Enterprise)
316
+ - [ ] Webhook passcode verification implemented (if webhook trigger)
317
+ - [ ] Drift detection correctly identifies added/removed/changed tokens
318
+ - [ ] Output files are deterministic (same input produces same output)
319
+
320
+ ## Output
321
+
322
+ Generate the token pipeline files:
323
+
324
+ ### Core Files
325
+
326
+ - **`scripts/sync-tokens.ts`** (or `src/tokens/sync.ts`) — Main sync entry point
327
+ - **`src/tokens/resolver.ts`** — Variable resolution with alias chain following
328
+ - **`src/tokens/classifier.ts`** — Mode classification (theme vs breakpoint)
329
+ - **`src/tokens/types.ts`** — Token types, resolved token map, sync options
330
+
331
+ ### Renderer Files
332
+
333
+ - **`src/tokens/renderers/css.ts`** — CSS Custom Properties with mode overrides
334
+ - **`src/tokens/renderers/tailwind.ts`** — Tailwind theme.extend config
335
+ - **`src/tokens/renderers/scss.ts`** — SCSS variables (if requested)
336
+ - **`src/tokens/renderers/json.ts`** — JSON token structure (if requested)
337
+
338
+ ### Trigger Files (based on selected trigger)
339
+
340
+ - **`src/api/webhook.ts`** — Webhook handler (if webhook trigger)
341
+ - **`.github/workflows/sync-tokens.yml`** — GitHub Actions workflow (if CI/CD trigger)
342
+ - **`scripts/sync-tokens.ts`** — CLI script with argument parsing (if CLI trigger)
343
+
344
+ ### Supporting Files
345
+
346
+ - **`src/tokens/drift.ts`** — Drift detection module
347
+ - **Generated `tokens.css`** — Example output showing expected format
348
+
349
+ ### Output Checklist
350
+
351
+ Before returning the pipeline code, verify:
352
+
353
+ - [ ] Correct auth scope for Variables API (`file_variables:read`)
354
+ - [ ] Alias chains fully resolved with circular reference protection
355
+ - [ ] Modes classified correctly (theme vs breakpoint)
356
+ - [ ] HSL format for colors, rem units for spacing
357
+ - [ ] Theme overrides render both `@media (prefers-color-scheme)` and `[data-theme]`
358
+ - [ ] Breakpoint overrides render mobile-first ascending `@media (min-width)`
359
+ - [ ] Tailwind config uses `var()` references (no hardcoded values)
360
+ - [ ] Webhook handler verifies passcode (if webhook trigger)
361
+ - [ ] Fallback path documented and functional for non-Enterprise users
362
+ - [ ] Drift detection identifies added/removed/changed tokens
363
+ - [ ] Pipeline output is deterministic (same input → same output)
@@ -0,0 +1,290 @@
1
+ ---
2
+ name: ref-html
3
+ description: "Reference: Generate semantic HTML5 and layered CSS from Figma node data. Use this skill when the user has Figma design data and needs vanilla HTML + CSS output (no React, no JSX, no TypeScript). Ideal for static sites, email templates, prototypes, or framework-agnostic code."
4
+ ---
5
+
6
+ @knowledge/design-to-code-layout.md
7
+ @knowledge/design-to-code-visual.md
8
+ @knowledge/design-to-code-typography.md
9
+ @knowledge/design-to-code-assets.md
10
+ @knowledge/design-to-code-semantic.md
11
+ @knowledge/css-strategy.md
12
+ @knowledge/design-tokens.md
13
+
14
+ ## Objective
15
+
16
+ Generate semantic HTML5 markup and layered CSS from Figma node data. The output is framework-agnostic: a standalone `.html` file and a companion `.css` file using the three-layer CSS architecture (Tailwind utilities for layout, CSS Custom Properties for design tokens, and component-scoped classes for visual skin). No React, JSX, or TypeScript is involved.
17
+
18
+ ## Input
19
+
20
+ The user provides Figma design data as `$ARGUMENTS`. This may be:
21
+
22
+ - Raw Figma REST API JSON (node tree with children, fills, strokes, effects, text properties)
23
+ - Extracted/summarized node properties
24
+ - A description of the Figma component or page (layer names, layout, colors, typography)
25
+ - A Figma file/node URL (use the REST API knowledge to fetch data if needed)
26
+
27
+ If the input is insufficient for full generation, ask the user for what is missing. At minimum you need: component structure (parent/child hierarchy), layout mode, and visual properties for each node.
28
+
29
+ ## Process
30
+
31
+ Follow these steps in order. Each step references the relevant knowledge module for detailed mapping rules.
32
+
33
+ ### Step 1: Analyze Node Tree Structure
34
+
35
+ Identify the component boundary and internal hierarchy:
36
+
37
+ - The root node is the top-level container.
38
+ - Map each child node to its role: structural container, text element, image, icon/vector, interactive element.
39
+ - Identify repeated patterns that could use consistent class naming.
40
+ - Note variants or states that may need CSS modifier classes.
41
+
42
+ ### Step 2: Determine Semantic HTML5 Elements
43
+
44
+ Consult `knowledge/design-to-code-semantic.md`:
45
+
46
+ - Match layer names against semantic tag heuristics:
47
+ - **Structural landmarks**: `<header>`, `<nav>`, `<main>`, `<aside>`, `<section>`, `<article>`, `<footer>`
48
+ - **Headings**: `<h1>` through `<h6>` based on name and font size heuristics
49
+ - **Text**: `<p>`, `<span>`, `<blockquote>`, `<figcaption>`
50
+ - **Interactive**: `<button>`, `<a>`, `<input>`, `<form>`, `<select>`, `<label>`
51
+ - **Media**: `<img>`, `<picture>`, `<figure>`, `<svg>`
52
+ - **Lists**: `<ul>`, `<ol>`, `<li>` when repeated children are detected
53
+ - Enforce heading hierarchy: single `<h1>`, sequential levels, no headings inside buttons or links.
54
+ - Default to `<div>` only when no semantic match is found.
55
+
56
+ ### Step 3: Extract Layout Properties
57
+
58
+ Consult `knowledge/design-to-code-layout.md`:
59
+
60
+ - For Auto Layout containers: map `layoutMode`, alignment, gap, padding, wrap, constraints.
61
+ - For each child: determine sizing mode on primary and counter axes.
62
+ - **CRITICAL**: FILL on primary axis requires BOTH `flex-grow: 1` AND `flex-basis: 0`.
63
+ - FILL on counter axis with max constraint uses `width: 100%`/`height: 100%`, not `align-self: stretch`.
64
+ - Handle absolute children with `position: relative` on parent and constraint-based offsets on child.
65
+ - For GROUP/legacy frames: absolute positioning with coordinate adjustments.
66
+
67
+ ### Step 4: Extract Visual Properties
68
+
69
+ Consult `knowledge/design-to-code-visual.md`:
70
+
71
+ - **Fills**: solid colors -> `background-color`, gradients -> `background-image`, images -> handled in Step 6.
72
+ - **Strokes**: INSIDE alignment -> `box-shadow: inset 0 0 0 {width}px {color}` (NOT `border`). CENTER/OUTSIDE -> standard `border` or `outline`.
73
+ - **Effects**: drop shadows -> `box-shadow`, inner shadows -> `box-shadow: inset`, layer blur -> `filter: blur()`, background blur -> `backdrop-filter: blur()`.
74
+ - **Corner radius**: uniform -> `border-radius`, per-corner -> `border-radius: TL TR BR BL` with shorthand optimization.
75
+ - **Opacity**: node-level -> CSS `opacity`, fill-level -> embedded in color alpha. Never double-apply.
76
+ - **Gradients**: convert angle with `90 - figmaAngle` for CSS. Map gradient stops with position percentages.
77
+ - **Variable bindings**: resolve to `var(--token-name)` with pixel fallbacks for external library variables.
78
+
79
+ ### Step 5: Extract Typography
80
+
81
+ Consult `knowledge/design-to-code-typography.md`:
82
+
83
+ - Map font family, weight, size, and style.
84
+ - **Line height**: ALWAYS use unitless ratio (`lineHeightPx / fontSize`). Never use px or % for line-height.
85
+ - Letter spacing: convert from Figma percentage to CSS `em` value.
86
+ - Text decoration, text transform, text alignment.
87
+ - Handle styled segments (mixed fonts/weights/colors within one text node) as nested `<span>` elements.
88
+ - Text auto-resize modes interact with layout sizing -- resolve the interaction.
89
+
90
+ ### Step 6: Handle Assets
91
+
92
+ Consult `knowledge/design-to-code-assets.md`:
93
+
94
+ - **Vector containers** (nodes with only vector/boolean children and no Auto Layout): export as inline SVG or reference SVG file.
95
+ - **Images**: use `<img>` with descriptive `alt` text derived from layer name. Specify `srcset` at **2x minimum** for retina displays.
96
+ - **Decision tree**: If the vector is simple and needs color control -> inline SVG. If complex or decorative -> `<img src="asset.svg">`.
97
+ - Deduplicate identical images (same `imageHash`).
98
+
99
+ ### Step 7: Extract Design Tokens
100
+
101
+ Consult `knowledge/design-tokens.md`:
102
+
103
+ - Collect repeated values (colors, spacing, font sizes, radii, shadows) across the node tree.
104
+ - Values used 2+ times are promoted to CSS Custom Properties.
105
+ - Apply semantic naming: HSL hue classification for colors, grid-based scale names for spacing.
106
+ - Figma Variable bindings take priority over auto-detected tokens.
107
+ - Token extraction priority: Variables API > styles > file traversal > Plugin API.
108
+
109
+ ### Step 8: Generate Layered CSS
110
+
111
+ Consult `knowledge/css-strategy.md`:
112
+
113
+ Structure the CSS output with clear layer separation:
114
+
115
+ **Layer 1 -- Tailwind Utilities (layout bones):**
116
+ Applied as utility classes directly in the HTML `class` attribute:
117
+ - Flexbox: `flex`, `flex-row`, `flex-col`, `items-center`, `justify-between`
118
+ - Spacing: `gap-4`, `p-6`, `px-4`, `py-2`
119
+ - Sizing: `w-full`, `h-auto`, `max-w-lg`, `flex-1`
120
+ - Positioning: `relative`, `absolute`, `top-0`, `right-0`
121
+ - Responsive: `md:flex-row`, `lg:gap-8`
122
+
123
+ **Layer 2 -- CSS Custom Properties (design tokens):**
124
+ Defined in a `:root` block at the top of the CSS file:
125
+ ```css
126
+ :root {
127
+ /* Colors */
128
+ --color-primary: #2563eb;
129
+ --color-surface: #ffffff;
130
+ --color-text-primary: #111827;
131
+ --color-border: #e5e7eb;
132
+
133
+ /* Typography */
134
+ --font-heading: 'Instrument Sans', sans-serif;
135
+ --font-body: 'Inter', sans-serif;
136
+ --font-size-xl: 1.5rem;
137
+ --font-size-base: 1rem;
138
+
139
+ /* Spacing */
140
+ --spacing-sm: 0.5rem;
141
+ --spacing-md: 1rem;
142
+ --spacing-lg: 1.5rem;
143
+
144
+ /* Effects */
145
+ --radius-md: 0.5rem;
146
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
147
+ }
148
+ ```
149
+
150
+ **Layer 3 -- Component Classes (visual skin):**
151
+ BEM-named classes for component-specific visual styles:
152
+ ```css
153
+ .card {
154
+ background-color: var(--color-surface);
155
+ box-shadow: inset 0 0 0 1px var(--color-border); /* INSIDE stroke */
156
+ border-radius: var(--radius-md);
157
+ }
158
+
159
+ .card__title {
160
+ color: var(--color-text-primary);
161
+ font-family: var(--font-heading);
162
+ font-size: var(--font-size-xl);
163
+ line-height: 1.3; /* unitless: lineHeightPx / fontSize */
164
+ }
165
+ ```
166
+
167
+ ### Step 9: Generate BEM Class Names
168
+
169
+ Consult `knowledge/design-to-code-semantic.md`:
170
+
171
+ - Block name from the root component (kebab-case from Figma layer name).
172
+ - Element names with double underscore: `block__element`.
173
+ - **NEVER nest deeper than one level**: `block__element` is valid, `block__element__sub` is NOT. Flatten to `block__sub` or use a modifier.
174
+ - Modifier with double dash: `block__element--modifier`.
175
+ - Deduplicate class names within the component tree.
176
+
177
+ ### Step 10: Add ARIA and Accessibility
178
+
179
+ - `alt` attribute on every `<img>` (descriptive for content images, empty `alt=""` for decorative).
180
+ - `aria-label` on interactive elements without visible text labels.
181
+ - `role` attribute where semantic HTML alone is insufficient.
182
+ - `aria-hidden="true"` on decorative SVGs and icons.
183
+ - Keyboard-accessible interactive elements (buttons, links use native elements; custom controls get `tabindex` and key handlers).
184
+
185
+ ### Step 11: Handle Responsive Breakpoints
186
+
187
+ If the Figma data includes multiple frames for breakpoints (detected via `#mobile`/`#tablet`/`#desktop` suffix or variant properties):
188
+
189
+ - Smallest frame provides base styles (no media query).
190
+ - Larger frames contribute override styles in `@media (min-width: ...)` blocks.
191
+ - Standard breakpoints: mobile (base), tablet (`768px`), desktop (`1024px`).
192
+ - Only emit properties that differ from the base.
193
+ - Reset layout properties (`align-self: auto`, `flex-grow: 0`, `flex-shrink: 1`, `flex-basis: auto`) that exist in base but not in larger breakpoints.
194
+ - Transform fixed pixel widths in responsive overrides to `width: 100%; max-width: Npx`.
195
+
196
+ ## Output
197
+
198
+ Generate two files:
199
+
200
+ ### 1. `component-name.html`
201
+
202
+ Semantic HTML5 with Tailwind utility classes for layout and BEM classes for visual skin:
203
+
204
+ ```html
205
+ <section class="flex flex-col gap-4 p-6 card">
206
+ <h2 class="card__title">Card Heading</h2>
207
+ <p class="card__description">
208
+ Description text with <span class="card__highlight">highlighted</span> segments.
209
+ </p>
210
+ <figure class="card__media">
211
+ <img
212
+ src="hero.jpg"
213
+ srcset="hero.jpg 1x, hero@2x.jpg 2x"
214
+ alt="Product showcase"
215
+ class="w-full h-auto card__image"
216
+ >
217
+ </figure>
218
+ <button class="flex items-center justify-center card__action" type="button">
219
+ Get Started
220
+ </button>
221
+ </section>
222
+ ```
223
+
224
+ ### 2. `component-name.css`
225
+
226
+ Layered CSS with clear section comments:
227
+
228
+ ```css
229
+ /* ========================================
230
+ Design Tokens (Layer 2)
231
+ ======================================== */
232
+ :root {
233
+ --color-primary: #2563eb;
234
+ --color-surface: #ffffff;
235
+ /* ... */
236
+ }
237
+
238
+ /* ========================================
239
+ Component Styles (Layer 3)
240
+ ======================================== */
241
+ .card {
242
+ background-color: var(--color-surface);
243
+ border-radius: var(--radius-md);
244
+ }
245
+
246
+ .card__title {
247
+ color: var(--color-text-primary);
248
+ font-family: var(--font-heading);
249
+ font-size: var(--font-size-xl);
250
+ line-height: 1.3;
251
+ }
252
+
253
+ /* ========================================
254
+ Responsive Overrides
255
+ ======================================== */
256
+ @media (min-width: 768px) {
257
+ /* Only changed properties */
258
+ }
259
+
260
+ @media (min-width: 1024px) {
261
+ /* Only changed properties */
262
+ }
263
+ ```
264
+
265
+ ### Key Differences from generate-react
266
+
267
+ This skill generates **vanilla HTML + CSS**:
268
+ - No JSX syntax (uses standard HTML attributes: `class` not `className`, `for` not `htmlFor`)
269
+ - No TypeScript interfaces or prop types
270
+ - No React imports, hooks, or component functions
271
+ - No CSS Modules import (classes are global BEM names, not hashed)
272
+ - Design tokens are defined inline in the CSS file's `:root` block
273
+ - Suitable for static sites, email templates, CMS integration, or any non-React context
274
+
275
+ ### Critical Rules Checklist
276
+
277
+ Before returning the output, verify:
278
+
279
+ - [ ] INSIDE strokes use `box-shadow: inset`, not `border`
280
+ - [ ] Gradient angles use `90 - figmaAngle` conversion
281
+ - [ ] Line heights are unitless ratios (`lineHeightPx / fontSize`)
282
+ - [ ] Images reference 2x assets for retina (`srcset` or `@2x` naming)
283
+ - [ ] BEM nesting is flat: never `block__element__sub`
284
+ - [ ] FILL on primary axis has BOTH `flex-grow: 1` AND `flex-basis: 0`
285
+ - [ ] CSS has clear layer separation (tokens in `:root`, visual skin in BEM classes)
286
+ - [ ] No hardcoded color values in component classes -- use `var()` for tokens
287
+ - [ ] Semantic HTML5 tags used where layer names match heuristics
288
+ - [ ] ARIA attributes present on interactive and image elements
289
+ - [ ] Uses HTML attributes (`class`, `for`) not JSX attributes (`className`, `htmlFor`)
290
+ - [ ] Responsive overrides include layout property resets where needed