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,222 @@
1
+ ---
2
+ name: ref-react
3
+ description: "Reference: Generate a production-grade React/TSX component from Figma node data. Use this skill when the user has Figma design data (JSON node tree, REST API response, or component description) and needs a typed React component with CSS Modules, proper semantics, and accessibility."
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
+
13
+ ## Objective
14
+
15
+ Generate a complete, production-grade React/TSX component from Figma node data. The output includes a typed function component (`.tsx`) and a companion CSS Modules file (`.module.css`) using the three-layer CSS architecture: Tailwind for layout bones, CSS Custom Properties for design tokens, and CSS Modules for visual skin.
16
+
17
+ ## Input
18
+
19
+ The user provides Figma design data as `$ARGUMENTS`. This may be:
20
+
21
+ - Raw Figma REST API JSON (node tree with children, fills, strokes, effects, text properties)
22
+ - Extracted/summarized node properties
23
+ - A description of the Figma component (layer names, layout, colors, typography)
24
+ - A Figma file/node URL (use the REST API knowledge to fetch data if needed)
25
+
26
+ 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.
27
+
28
+ ## Process
29
+
30
+ Follow these steps in order. Each step references the relevant knowledge module for detailed mapping rules.
31
+
32
+ ### Step 1: Analyze Node Tree Structure
33
+
34
+ Identify the component boundary and internal hierarchy:
35
+
36
+ - The root node is the component container.
37
+ - Map each child node to its role: structural container, text element, image, icon/vector, interactive element.
38
+ - Identify repeated patterns that suggest list/map rendering.
39
+ - Note any component instances or variants that imply prop-driven rendering.
40
+
41
+ ### Step 2: Determine Semantic HTML Elements
42
+
43
+ Consult `knowledge/design-to-code-semantic.md`:
44
+
45
+ - Match layer names against semantic tag heuristics (header, nav, button, h1-h6, p, img, section, article, footer, etc.).
46
+ - Enforce heading hierarchy: single `<h1>`, sequential levels, no headings inside interactive elements.
47
+ - Detect interactive elements from names (button, link, input, form, checkbox, toggle, etc.).
48
+ - Map structural landmarks (header, nav, footer, main, aside, section).
49
+ - Default to `<div>` only when no semantic match is found.
50
+
51
+ ### Step 3: Extract Layout Properties
52
+
53
+ Consult `knowledge/design-to-code-layout.md`:
54
+
55
+ - For Auto Layout containers: map `layoutMode`, alignment, gap, padding, wrap, constraints.
56
+ - For each child: determine sizing mode on primary and counter axes.
57
+ - **CRITICAL**: FILL on primary axis requires BOTH `flex-grow: 1` AND `flex-basis: 0`.
58
+ - FILL on counter axis with max constraint uses `width: 100%`/`height: 100%`, not `align-self: stretch`.
59
+ - Handle absolute children with `position: relative` on parent and constraint-based offsets on child.
60
+ - For GROUP/legacy frames: absolute positioning with coordinate adjustments.
61
+
62
+ ### Step 4: Extract Visual Properties
63
+
64
+ Consult `knowledge/design-to-code-visual.md`:
65
+
66
+ - **Fills**: solid colors -> `background-color`, gradients -> `background-image`, images -> handled in Step 6.
67
+ - **Strokes**: INSIDE alignment -> `box-shadow: inset 0 0 0 {width}px {color}` (NOT `border`). CENTER/OUTSIDE -> standard `border` or `outline`.
68
+ - **Effects**: drop shadows -> `box-shadow`, inner shadows -> `box-shadow: inset`, layer blur -> `filter: blur()`, background blur -> `backdrop-filter: blur()`.
69
+ - **Corner radius**: uniform -> `border-radius`, per-corner -> `border-radius: TL TR BR BL` with shorthand optimization.
70
+ - **Opacity**: node-level -> CSS `opacity`, fill-level -> embedded in color alpha. Never double-apply.
71
+ - **Gradients**: convert angle with `90 - figmaAngle` for CSS. Map gradient stops with position percentages.
72
+ - **Variable bindings**: resolve to `var(--token-name)` with pixel fallbacks for external library variables.
73
+
74
+ ### Step 5: Extract Typography
75
+
76
+ Consult `knowledge/design-to-code-typography.md`:
77
+
78
+ - Map font family, weight, size, and style.
79
+ - **Line height**: ALWAYS use unitless ratio (`lineHeightPx / fontSize`). Never use px or % for line-height.
80
+ - Letter spacing: convert from Figma percentage to CSS `em` value.
81
+ - Text decoration, text transform, text alignment.
82
+ - Handle styled segments (mixed fonts/weights/colors within one text node) as `<span>` elements.
83
+ - Text auto-resize modes interact with layout sizing -- resolve the interaction.
84
+
85
+ ### Step 6: Handle Assets
86
+
87
+ Consult `knowledge/design-to-code-assets.md`:
88
+
89
+ - **Vector containers** (nodes with only vector/boolean children and no Auto Layout): export as inline SVG or `<img>` referencing an SVG file.
90
+ - **Images**: use `<img>` with `alt` text derived from layer name. Export at **2x minimum** for retina displays.
91
+ - **Decision tree**: If the vector is simple and needs color control -> inline SVG. If complex or decorative -> `<img src="asset.svg">`.
92
+ - Deduplicate identical images (same `imageHash`).
93
+
94
+ ### Step 7: Generate CSS Using Three-Layer Architecture
95
+
96
+ Consult `knowledge/css-strategy.md`:
97
+
98
+ **Layer 1 -- Tailwind (layout bones):**
99
+ Apply Tailwind utility classes directly in JSX for:
100
+ - Flexbox: `flex`, `flex-row`, `flex-col`, `items-center`, `justify-between`
101
+ - Spacing: `gap-4`, `p-6`, `px-4`, `py-2`
102
+ - Sizing: `w-full`, `h-auto`, `max-w-lg`, `flex-1`
103
+ - Positioning: `relative`, `absolute`, `top-0`, `right-0`
104
+ - Responsive: `md:flex-row`, `lg:gap-8`
105
+
106
+ **Layer 2 -- CSS Custom Properties (design tokens):**
107
+ Define in the CSS Module file or a shared `tokens.css`:
108
+ ```css
109
+ /* Token references consumed by Layer 3 */
110
+ color: var(--color-primary);
111
+ font-size: var(--font-size-lg);
112
+ border-radius: var(--radius-md);
113
+ ```
114
+
115
+ **Layer 3 -- CSS Modules (visual skin):**
116
+ Component-specific visual styles in `.module.css`:
117
+ ```css
118
+ .card {
119
+ background-color: var(--color-surface);
120
+ box-shadow: inset 0 0 0 1px var(--color-border); /* INSIDE stroke */
121
+ border-radius: var(--radius-lg);
122
+ }
123
+
124
+ .card__title {
125
+ color: var(--color-text-primary);
126
+ font-family: var(--font-heading);
127
+ font-size: var(--font-size-xl);
128
+ line-height: 1.3; /* unitless ratio */
129
+ }
130
+ ```
131
+
132
+ ### Step 8: Generate BEM Class Names
133
+
134
+ Consult `knowledge/design-to-code-semantic.md`:
135
+
136
+ - Block name from the root component (kebab-case from layer name).
137
+ - Element names with double underscore: `block__element`.
138
+ - **NEVER nest deeper than one level**: `block__element` is valid, `block__element__sub` is NOT. Flatten to `block__sub` or use a modifier.
139
+ - Modifier with double dash: `block__element--modifier`.
140
+ - Deduplicate class names within the component tree.
141
+
142
+ ### Step 9: Generate TypeScript Interfaces
143
+
144
+ Define prop interfaces for the component:
145
+
146
+ - Extract variant-driven props from Figma component properties (boolean, text, instance swap).
147
+ - Text content nodes become string props.
148
+ - Image nodes become `src`/`alt` prop pairs.
149
+ - Interactive elements get event handler props (`onClick`, `onSubmit`, etc.).
150
+ - Use descriptive names, not Figma layer names directly.
151
+
152
+ ### Step 10: Assemble React Component
153
+
154
+ Combine all outputs into a complete `.tsx` file:
155
+
156
+ ```tsx
157
+ import React from 'react';
158
+ import styles from './ComponentName.module.css';
159
+
160
+ interface ComponentNameProps {
161
+ title: string;
162
+ description?: string;
163
+ onAction?: () => void;
164
+ }
165
+
166
+ export function ComponentName({ title, description, onAction }: ComponentNameProps) {
167
+ return (
168
+ <section className={`flex flex-col gap-4 p-6 ${styles.card}`}>
169
+ <h2 className={`${styles.card__title}`}>
170
+ {title}
171
+ </h2>
172
+ {description && (
173
+ <p className={`${styles.card__description}`}>
174
+ {description}
175
+ </p>
176
+ )}
177
+ <button
178
+ className={`flex items-center justify-center ${styles.card__action}`}
179
+ onClick={onAction}
180
+ type="button"
181
+ >
182
+ Get Started
183
+ </button>
184
+ </section>
185
+ );
186
+ }
187
+ ```
188
+
189
+ ## Output
190
+
191
+ Generate two files:
192
+
193
+ ### 1. `ComponentName.tsx`
194
+
195
+ - Named export (not default export) with PascalCase component name.
196
+ - TypeScript interface for props.
197
+ - Semantic HTML elements with Tailwind layout classes + CSS Module visual classes.
198
+ - Proper ARIA attributes where needed (`aria-label`, `role`, `alt`).
199
+ - Inline SVGs for simple vectors, `<img>` for complex assets/images.
200
+
201
+ ### 2. `ComponentName.module.css`
202
+
203
+ - BEM class names with flat hierarchy.
204
+ - Visual properties only (colors, backgrounds, borders/shadows, effects, typography skin).
205
+ - CSS Custom Property references for design tokens (`var(--token-name)`).
206
+ - Responsive overrides via media queries if multi-frame breakpoints detected.
207
+ - Comments showing Figma property origin for maintainability.
208
+
209
+ ### Critical Rules Checklist
210
+
211
+ Before returning the component, verify:
212
+
213
+ - [ ] INSIDE strokes use `box-shadow: inset`, not `border`
214
+ - [ ] Gradient angles use `90 - figmaAngle` conversion
215
+ - [ ] Line heights are unitless ratios (`lineHeightPx / fontSize`)
216
+ - [ ] Images export at 2x minimum for retina
217
+ - [ ] BEM nesting is flat: never `block__element__sub`
218
+ - [ ] FILL on primary axis has BOTH `flex-grow: 1` AND `flex-basis: 0`
219
+ - [ ] Layout is in Tailwind classes; visual skin is in CSS Modules
220
+ - [ ] No hardcoded color values -- use CSS Custom Properties for anything that could be a token
221
+ - [ ] Semantic HTML tags used where layer names match heuristics
222
+ - [ ] ARIA attributes present on interactive and image elements
@@ -0,0 +1,347 @@
1
+ ---
2
+ name: ref-tokens
3
+ description: "Reference: Extract design tokens from Figma Variables, styles, or node data and generate CSS Custom Properties + Tailwind config. Use this skill when the user has Figma file data (Variables API response, style definitions, or node tree) and needs a structured token output with semantic naming, mode-aware rendering, and CSS/Tailwind integration."
4
+ ---
5
+
6
+ @knowledge/design-tokens.md
7
+ @knowledge/design-tokens-variables.md
8
+ @knowledge/figma-api-variables.md
9
+ @knowledge/css-strategy.md
10
+
11
+ ## Objective
12
+
13
+ Extract design tokens from Figma data and generate production-grade CSS Custom Properties (`:root` block with mode-aware overrides), optional SCSS variables, and a Tailwind `theme.extend` configuration snippet. The skill handles the full token pipeline: source identification, variable resolution, threshold-based promotion, semantic naming (HSL color classification, spacing scale detection), and multi-format rendering.
14
+
15
+ ## Input
16
+
17
+ The user provides Figma token source data as `$ARGUMENTS`. This may be:
18
+
19
+ - **Variables API response** -- JSON from `GET /v1/files/:key/variables/local` containing variables and collections with `valuesByMode`
20
+ - **Plugin API variable data** -- Extracted variable collections from `figma.variables.getLocalVariableCollectionsAsync()`
21
+ - **Node tree with bound variables** -- Figma REST API node data containing `boundVariables` on fills, strokes, layout properties, and text
22
+ - **Style definitions** -- Published styles from the file (colors, text styles, effects)
23
+ - **Raw node tree** -- Full node subtree for heuristic-based token extraction (file traversal fallback)
24
+ - **Plain language description** -- Description of the design system's colors, spacing, typography, etc.
25
+
26
+ If the input is insufficient, ask the user for clarification. At minimum you need either: (a) variable collections with values, or (b) a node tree with enough nodes to detect repeated values for promotion.
27
+
28
+ ## Process
29
+
30
+ Follow these steps in order. Consult the referenced knowledge modules for all mapping rules, naming conventions, and edge cases.
31
+
32
+ ### Step 1: Identify Token Source and Access Path
33
+
34
+ Determine which token extraction path to use based on the input data. Consult `knowledge/figma-api-variables.md` for access requirements and `knowledge/design-tokens-variables.md` for the source priority chain.
35
+
36
+ **Priority order:**
37
+
38
+ 1. **Variables API** (best) -- Structured, multi-mode, scoped. Requires Enterprise org full member access with `file_variables:read` scope. If the user provides Variables API JSON, use this path.
39
+ 2. **Published styles** -- Good for non-Enterprise plans. Limited to published content.
40
+ 3. **File tree traversal** -- Fallback for any plan. Heuristic-based extraction from node properties. Uses threshold promotion.
41
+ 4. **Plugin API** -- When running inside a Figma plugin context. Access via `figma.variables.getLocalVariableCollectionsAsync()`.
42
+
43
+ **If the user does not have Enterprise access**, inform them that the Variables API path is unavailable and proceed with file traversal + threshold promotion. Do NOT block on missing Variables access -- always provide a working fallback path.
44
+
45
+ ### Step 2: Extract Raw Token Values
46
+
47
+ Based on the identified source path:
48
+
49
+ **Variables API path:**
50
+ - Parse variable collections and their modes
51
+ - For each variable: read `resolvedType` (COLOR, FLOAT, STRING), `valuesByMode`, `scopes`
52
+ - Classify each collection's modes using mode name detection (see Step 3)
53
+ - Distinguish local vs remote variables using the `remote` boolean field
54
+ - Follow alias chains: if a variable's value is a `VariableAlias`, resolve to the terminal value for each mode
55
+
56
+ **File traversal path:**
57
+ - Traverse the node tree recursively
58
+ - Collect values from five domains, tracking usage count per unique value:
59
+ - **Colors**: solid fills (`fill.color`), strokes (`stroke.color`), shadow effect colors
60
+ - **Spacing**: `itemSpacing` (gap), `paddingTop/Right/Bottom/Left`, margins
61
+ - **Typography**: font families, font sizes, font weights, line heights
62
+ - **Effects**: box shadows (drop shadow, inner shadow), border radii
63
+ - **Breakpoints**: frame dimensions that suggest responsive breakpoints
64
+ - Normalize values before comparison (lowercase hex, whitespace-normalize rgba)
65
+ - Collect any `boundVariables` references found on nodes (these get priority in Step 6)
66
+
67
+ ### Step 3: Detect Modes (Variables Path Only)
68
+
69
+ Consult `knowledge/design-tokens-variables.md` Section 4 for mode detection rules.
70
+
71
+ Classify each collection's modes as one of:
72
+ - **Theme modes** -- Mode names like "Light", "Dark", "Brand A", "Brand B"
73
+ - **Breakpoint modes** -- Mode names like "Mobile", "Tablet", "Desktop", "sm", "md", "lg"
74
+ - **Unknown** -- Cannot classify; treat as theme modes by default
75
+
76
+ **Default mode selection:**
77
+ - Theme modes: "Light" is default (base `:root`)
78
+ - Breakpoint modes: smallest breakpoint (typically "Mobile") is default (mobile-first)
79
+ - Unknown: first mode in the collection is default
80
+
81
+ ### Step 4: Promote Values to Tokens
82
+
83
+ Consult `knowledge/design-tokens.md` Section 1 (Stage 2: PROMOTE).
84
+
85
+ **Threshold-based promotion (file traversal path):**
86
+ - Values used 2 or more times are promoted to CSS Custom Properties
87
+ - Single-use values remain inline in component CSS (not tokenized)
88
+ - The threshold of 2 is the default; adjust if the user specifies differently
89
+
90
+ **Variables path:**
91
+ - All Figma Variables are automatically promoted (they are explicit designer-curated tokens)
92
+ - No threshold needed -- variables are tokens by definition
93
+
94
+ **Priority when both exist:**
95
+ - Bound variable references on a property always take priority
96
+ - Auto-detected tokens fill gaps where no variable binding exists
97
+ - If a variable and an auto-detected token produce the same CSS value, the variable wins
98
+
99
+ ### Step 5: Assign Semantic Names
100
+
101
+ Consult `knowledge/design-tokens.md` Sections 3-6 for naming rules per category.
102
+
103
+ **Token naming convention:** `--{category}-{name}-{variant}`
104
+
105
+ **Colors (HSL-based classification):**
106
+ 1. Convert to HSL (Hue 0-360, Saturation 0-100, Lightness 0-100)
107
+ 2. Classify:
108
+ - Saturation < 10% --> `neutral` with lightness scale (100-900)
109
+ - Hue 0-20 or 340-360 --> `error`
110
+ - Hue 30-60 --> `warning`
111
+ - Hue 90-150 --> `success`
112
+ - Most-used saturated color --> `primary`
113
+ - Second most-used saturated --> `secondary`
114
+ - Remaining --> `accent`, `accent-2`, etc.
115
+ 3. Neutral lightness scale: `step = Math.round((1 - lightness / 100) * 8 + 1) * 100` clamped to [100, 900]
116
+ 4. Output format: HSL values for easy manipulation: `--color-primary: hsl(220, 90%, 56%)`
117
+
118
+ **If Variables API is the source**, use the variable's own path as the name base (e.g., `color/primary/500` --> `--color-primary-500`). HSL classification is only needed for file traversal path where names must be inferred.
119
+
120
+ **Spacing (4px base unit detection):**
121
+ 1. Detect the base unit from collected spacing values (typically 4px or 8px)
122
+ 2. Express each spacing value as a multiple of the base: `value / baseUnit`
123
+ 3. Name pattern: `--spacing-{multiplier}` (e.g., `--spacing-1` = 4px, `--spacing-4` = 16px)
124
+ 4. If a clear base unit cannot be detected, use pixel-based naming: `--spacing-4` = 4px, `--spacing-16` = 16px
125
+
126
+ **Typography:**
127
+ - Font families: `--font-primary`, `--font-secondary`, `--font-mono`
128
+ - Font sizes: `--text-xs`, `--text-sm`, `--text-base`, `--text-lg`, `--text-xl`, `--text-2xl`, etc. (match to nearest standard scale)
129
+ - Font weights: `--font-regular` (400), `--font-medium` (500), `--font-semibold` (600), `--font-bold` (700)
130
+
131
+ **Effects:**
132
+ - Shadows: `--shadow-sm`, `--shadow-md`, `--shadow-lg` (by blur radius / spread scale)
133
+ - Border radii: `--radius-sm`, `--radius-md`, `--radius-lg`, `--radius-full`
134
+
135
+ **Name deduplication:**
136
+ - If two tokens would get the same name, append a numeric suffix: `--color-accent`, `--color-accent-2`
137
+ - For Variables API tokens, the variable path provides unique names naturally
138
+
139
+ ### Step 6: Render CSS Custom Properties
140
+
141
+ Consult `knowledge/design-tokens-variables.md` Sections 5-7 for mode-aware rendering and `knowledge/css-strategy.md` for where tokens fit in the three-layer architecture.
142
+
143
+ **Base `:root` block (default mode values):**
144
+
145
+ ```css
146
+ /* ========================================
147
+ Design Tokens (Layer 2)
148
+ ======================================== */
149
+
150
+ :root {
151
+ /* Colors */
152
+ --color-primary: hsl(220, 90%, 56%);
153
+ --color-secondary: hsl(258, 88%, 66%);
154
+ --color-neutral-100: hsl(0, 0%, 96%);
155
+ --color-neutral-900: hsl(0, 0%, 9%);
156
+ --color-error: hsl(0, 84%, 60%);
157
+ --color-success: hsl(142, 71%, 45%);
158
+
159
+ /* Spacing (4px base) */
160
+ --spacing-1: 0.25rem; /* 4px */
161
+ --spacing-2: 0.5rem; /* 8px */
162
+ --spacing-4: 1rem; /* 16px */
163
+ --spacing-6: 1.5rem; /* 24px */
164
+ --spacing-8: 2rem; /* 32px */
165
+
166
+ /* Typography */
167
+ --font-primary: 'Inter', sans-serif;
168
+ --font-heading: 'Instrument Sans', sans-serif;
169
+ --text-sm: 0.875rem; /* 14px */
170
+ --text-base: 1rem; /* 16px */
171
+ --text-lg: 1.125rem; /* 18px */
172
+ --text-xl: 1.5rem; /* 24px */
173
+
174
+ /* Effects */
175
+ --radius-sm: 0.25rem; /* 4px */
176
+ --radius-md: 0.5rem; /* 8px */
177
+ --radius-lg: 1rem; /* 16px */
178
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
179
+ --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
180
+ }
181
+ ```
182
+
183
+ **Theme mode overrides:**
184
+
185
+ ```css
186
+ /* Dark theme */
187
+ @media (prefers-color-scheme: dark) {
188
+ :root {
189
+ --color-primary: hsl(220, 90%, 65%);
190
+ --color-neutral-100: hsl(0, 0%, 15%);
191
+ --color-neutral-900: hsl(0, 0%, 95%);
192
+ /* Only tokens that change in dark mode */
193
+ }
194
+ }
195
+
196
+ /* Class-based theme (alternative/additional) */
197
+ [data-theme="dark"] {
198
+ --color-primary: hsl(220, 90%, 65%);
199
+ --color-neutral-100: hsl(0, 0%, 15%);
200
+ --color-neutral-900: hsl(0, 0%, 95%);
201
+ }
202
+ ```
203
+
204
+ **Breakpoint mode overrides (mobile-first):**
205
+
206
+ ```css
207
+ @media (min-width: 768px) {
208
+ :root {
209
+ --spacing-4: 1.25rem; /* 20px at tablet */
210
+ --text-xl: 1.75rem; /* 28px at tablet */
211
+ }
212
+ }
213
+
214
+ @media (min-width: 1024px) {
215
+ :root {
216
+ --spacing-4: 1.5rem; /* 24px at desktop */
217
+ --text-xl: 2rem; /* 32px at desktop */
218
+ }
219
+ }
220
+ ```
221
+
222
+ **Rendering rules:**
223
+ - Only emit overrides for tokens whose values differ from the base mode
224
+ - Theme collections render as `@media (prefers-color-scheme)` AND `[data-theme]` selector (both, for progressive enhancement)
225
+ - Breakpoint collections render as `@media (min-width)` with mobile-first ordering
226
+ - Use rem units for spacing and font sizes (divide pixel value by 16)
227
+ - Use HSL for colors (enables easy lightness/saturation manipulation)
228
+ - Add comments showing the original pixel values for developer reference
229
+
230
+ ### Step 7: Render Tailwind Config Extension
231
+
232
+ Generate a `tailwind.config.ts` extension snippet that maps tokens to Tailwind utilities:
233
+
234
+ ```typescript
235
+ import type { Config } from 'tailwindcss'
236
+
237
+ export default {
238
+ theme: {
239
+ extend: {
240
+ colors: {
241
+ primary: 'var(--color-primary)',
242
+ secondary: 'var(--color-secondary)',
243
+ neutral: {
244
+ 100: 'var(--color-neutral-100)',
245
+ 900: 'var(--color-neutral-900)',
246
+ },
247
+ error: 'var(--color-error)',
248
+ success: 'var(--color-success)',
249
+ },
250
+ fontFamily: {
251
+ primary: 'var(--font-primary)',
252
+ heading: 'var(--font-heading)',
253
+ },
254
+ fontSize: {
255
+ sm: 'var(--text-sm)',
256
+ base: 'var(--text-base)',
257
+ lg: 'var(--text-lg)',
258
+ xl: 'var(--text-xl)',
259
+ },
260
+ spacing: {
261
+ 1: 'var(--spacing-1)',
262
+ 2: 'var(--spacing-2)',
263
+ 4: 'var(--spacing-4)',
264
+ 6: 'var(--spacing-6)',
265
+ 8: 'var(--spacing-8)',
266
+ },
267
+ borderRadius: {
268
+ sm: 'var(--radius-sm)',
269
+ md: 'var(--radius-md)',
270
+ lg: 'var(--radius-lg)',
271
+ },
272
+ boxShadow: {
273
+ sm: 'var(--shadow-sm)',
274
+ md: 'var(--shadow-md)',
275
+ },
276
+ },
277
+ },
278
+ } satisfies Config
279
+ ```
280
+
281
+ **Tailwind mapping rules:**
282
+ - All Tailwind values reference CSS Custom Properties via `var()` -- never hardcode values
283
+ - This ensures Tailwind utilities automatically adapt to theme/breakpoint mode changes
284
+ - Color tokens map to `theme.extend.colors` (enables `bg-primary`, `text-secondary`, etc.)
285
+ - Spacing tokens map to `theme.extend.spacing` (enables `gap-4`, `p-6`, etc.)
286
+ - Typography tokens split across `fontFamily`, `fontSize`
287
+ - Effect tokens map to `borderRadius`, `boxShadow`
288
+
289
+ ### Step 8: Render SCSS Variables (If Requested)
290
+
291
+ Only generate SCSS output if the user explicitly requests it:
292
+
293
+ ```scss
294
+ // _variables.scss — Generated from Figma design tokens
295
+
296
+ // Colors
297
+ $color-primary: var(--color-primary);
298
+ $color-secondary: var(--color-secondary);
299
+
300
+ // Spacing
301
+ $spacing-1: var(--spacing-1);
302
+ $spacing-4: var(--spacing-4);
303
+
304
+ // Typography
305
+ $font-primary: var(--font-primary);
306
+ $text-base: var(--text-base);
307
+ ```
308
+
309
+ SCSS variables reference CSS Custom Properties (not raw values) to maintain single source of truth.
310
+
311
+ ## Output
312
+
313
+ Generate two files (three if SCSS requested):
314
+
315
+ ### 1. `tokens.css`
316
+
317
+ - `:root` block with all promoted tokens organized by category (colors, spacing, typography, effects)
318
+ - Mode-aware overrides via `@media (prefers-color-scheme)`, `[data-theme]` selectors, or `@media (min-width)` for breakpoints
319
+ - Comments showing original Figma variable paths or pixel values
320
+ - HSL format for colors, rem units for spacing/typography
321
+
322
+ ### 2. `tailwind.config.ts` (extension snippet)
323
+
324
+ - `theme.extend` configuration referencing CSS Custom Properties
325
+ - All values use `var()` references to tokens defined in `tokens.css`
326
+ - Ready to merge into existing Tailwind configuration
327
+
328
+ ### 3. `_variables.scss` (only if requested)
329
+
330
+ - SCSS variable declarations referencing CSS Custom Properties
331
+
332
+ ### Output Checklist
333
+
334
+ Before returning token output, verify:
335
+
336
+ - [ ] Colors use HSL format (`hsl(h, s%, l%)`)
337
+ - [ ] Spacing values use rem units with pixel comments
338
+ - [ ] Spacing is based on consistent base unit (default 4px)
339
+ - [ ] Token names follow `--{category}-{name}-{variant}` convention
340
+ - [ ] Variables API tokens preserve original variable path in names
341
+ - [ ] File traversal tokens use HSL classification for color naming
342
+ - [ ] Mode overrides only contain tokens that differ from the base
343
+ - [ ] Theme modes render both `@media (prefers-color-scheme)` and `[data-theme]`
344
+ - [ ] Breakpoint modes render mobile-first `@media (min-width)` in ascending order
345
+ - [ ] Tailwind config references `var()` for all values (no hardcoded values)
346
+ - [ ] Fallback path is documented when Variables API is not available
347
+ - [ ] Single-use values (below threshold) are NOT promoted to tokens