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
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "figma-code-agent",
3
+ "version": "1.0.0",
4
+ "description": "Figma developer expert tool for Claude Code — 19 knowledge modules and 10 invokable skills for building plugins, codegen plugins, importers, token pipelines, and design-to-code workflows.",
5
+ "bin": {
6
+ "figma-code-agent": "bin/install.js"
7
+ },
8
+ "files": [
9
+ "bin",
10
+ "skills",
11
+ "knowledge"
12
+ ],
13
+ "keywords": [
14
+ "figma",
15
+ "claude-code",
16
+ "design-to-code",
17
+ "figma-plugin",
18
+ "codegen",
19
+ "importer",
20
+ "react",
21
+ "css",
22
+ "design-tokens",
23
+ "payloadcms"
24
+ ],
25
+ "author": "aolea",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/aolea/figma-code-agent"
30
+ }
31
+ }
@@ -0,0 +1,103 @@
1
+ # Figma Agent Skills
2
+
3
+ Claude Code invokable skills for Figma development workflows.
4
+
5
+ ## Plugin Format
6
+
7
+ This agent uses the Claude Code plugin format (`.claude-plugin/plugin.json`). Skills live in `skills/{name}/SKILL.md`.
8
+
9
+ ## Available Skills
10
+
11
+ ### Tier 1: Developer Workflow (Assess → Recommend → Implement → Validate)
12
+
13
+ | Skill | Command | Description | Knowledge Modules |
14
+ |-------|---------|-------------|-------------------|
15
+ | Build Plugin | `/fca:build-plugin` | Build a Figma plugin from scratch or enhance an existing one | plugin-architecture, plugin-best-practices, figma-api-plugin |
16
+ | Build Codegen Plugin | `/fca:build-codegen-plugin` | Build a Dev Mode codegen plugin that generates code from designs | plugin-codegen, figma-api-devmode, plugin-best-practices, figma-api-plugin |
17
+ | Build Importer | `/fca:build-importer` | Build a service that fetches Figma designs into a CMS or React app | figma-api-rest, figma-api-variables, all design-to-code, css-strategy, design-tokens, payload-figma-mapping, payload-blocks |
18
+ | Build Token Pipeline | `/fca:build-token-pipeline` | Build a pipeline that syncs Figma design tokens to code | figma-api-variables, design-tokens, design-tokens-variables, figma-api-webhooks, css-strategy |
19
+
20
+ ### Tier 2: Reference / Validation (Step-by-step process)
21
+
22
+ | Skill | Command | Description | Knowledge Modules |
23
+ |-------|---------|-------------|-------------------|
24
+ | Ref: Layout | `/fca:ref-layout` | Interpret Figma Auto Layout → CSS Flexbox with correct sizing modes | layout |
25
+ | Ref: React | `/fca:ref-react` | Generate production-grade React/TSX component from Figma node data | layout, visual, typography, assets, semantic, css-strategy |
26
+ | Ref: HTML | `/fca:ref-html` | Generate semantic HTML + layered CSS from Figma node data | layout, visual, typography, assets, semantic, css-strategy, design-tokens |
27
+ | Ref: Tokens | `/fca:ref-tokens` | Extract design tokens → CSS custom properties + Tailwind config | design-tokens, design-tokens-variables, figma-api-variables, css-strategy |
28
+ | Ref: PayloadCMS Block | `/fca:ref-payload-block` | Map Figma component → PayloadCMS block config + renderer + types | payload-blocks, payload-figma-mapping, payload-visual-builder, css-strategy |
29
+
30
+ ### Tier 3: Audit
31
+
32
+ | Skill | Command | Description | Knowledge Modules |
33
+ |-------|---------|-------------|-------------------|
34
+ | Audit Plugin | `/fca:audit-plugin` | Audit Figma plugin code against production best practices | plugin-architecture, plugin-codegen, plugin-best-practices, figma-api-plugin |
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ # Recommended: install via npx
40
+ npx figma-code-agent
41
+
42
+ # Alternative: load as Claude Code plugin (for development)
43
+ claude --plugin-dir /path/to/figma-code-agent
44
+
45
+ # Manual: symlinks (requires clone)
46
+ ./install.sh
47
+ ```
48
+
49
+ ## Skill Structure
50
+
51
+ Skills use two process patterns:
52
+
53
+ ### Tier 1 Pattern: 4-Phase Process
54
+
55
+ 1. **YAML frontmatter** -- `name` and `description` for Claude Code registration
56
+ 2. **@references** -- Knowledge modules the skill depends on
57
+ 3. **Objective** -- What the skill accomplishes
58
+ 4. **Input** -- What the user provides (requirements, existing project path, description)
59
+ 5. **Process** -- 4 phases: Assess → Recommend → Implement → Validate
60
+ 6. **Output** -- What gets generated (project files, modifications, validation report)
61
+
62
+ ### Tier 2/3 Pattern: Step-by-Step Process
63
+
64
+ 1. **YAML frontmatter** -- `name` and `description` for Claude Code registration
65
+ 2. **@references** -- Knowledge modules the skill depends on
66
+ 3. **Objective** -- What the skill accomplishes
67
+ 4. **Input** -- What the user provides (Figma node data, file URL, etc.)
68
+ 5. **Process** -- Numbered step-by-step instructions for Claude
69
+ 6. **Output** -- What gets generated (React component, CSS, token config, etc.)
70
+
71
+ ## Invocation Examples
72
+
73
+ ```
74
+ # Build a Figma plugin
75
+ /fca:build-plugin I want to build a plugin that exports frames as React components
76
+
77
+ # Build a codegen plugin for Dev Mode
78
+ /fca:build-codegen-plugin Generate Tailwind + React code in the inspect panel
79
+
80
+ # Build a Figma importer
81
+ /fca:build-importer Import Figma page designs into PayloadCMS blocks
82
+
83
+ # Build a token sync pipeline
84
+ /fca:build-token-pipeline Sync Figma Variables to CSS and Tailwind on library publish
85
+
86
+ # Interpret a Figma Auto Layout frame
87
+ /fca:ref-layout <paste Figma Auto Layout JSON node data>
88
+
89
+ # Generate a React component from Figma design
90
+ /fca:ref-react <paste Figma node data or describe the component>
91
+
92
+ # Generate vanilla HTML + CSS from Figma design
93
+ /fca:ref-html <paste Figma node data>
94
+
95
+ # Extract design tokens from Figma Variables
96
+ /fca:ref-tokens <paste Figma Variables API response or style data>
97
+
98
+ # Map a Figma component to a PayloadCMS block
99
+ /fca:ref-payload-block <paste Figma component data>
100
+
101
+ # Audit a Figma plugin codebase
102
+ /fca:audit-plugin <path to Figma plugin project>
103
+ ```
@@ -0,0 +1,244 @@
1
+ ---
2
+ name: audit-plugin
3
+ description: Audit Figma plugin code against production best practices. Use this skill when the user has a Figma plugin codebase and wants a quality review covering error handling, performance, memory management, caching, async patterns, testing, and distribution readiness.
4
+ ---
5
+
6
+ @knowledge/plugin-architecture.md
7
+ @knowledge/plugin-codegen.md
8
+ @knowledge/plugin-best-practices.md
9
+ @knowledge/figma-api-plugin.md
10
+
11
+ ## Objective
12
+
13
+ Audit a Figma plugin codebase against 7 production best practice categories, plus codegen-specific checks and architectural pattern verification. Read the actual source files, identify concrete issues with code references, rate each section (pass/warn/fail), and provide actionable recommendations with fix examples. This is NOT generic advice -- every finding must reference specific code in the plugin.
14
+
15
+ ## Input
16
+
17
+ The user provides plugin source code as `$ARGUMENTS`. This may be:
18
+
19
+ - **File paths** to plugin source files (manifest, main thread code, UI code, utilities)
20
+ - **Directory path** to the plugin project root
21
+ - **Description** of the plugin's purpose and architecture, with key file contents
22
+ - **Specific concern** to focus the audit on (e.g., "check my async patterns" or "review error handling")
23
+
24
+ If file paths are provided, read all relevant source files before starting the audit. At minimum, the audit needs:
25
+ - Manifest or `package.json` with `figma-plugin` section
26
+ - Main thread entry point (typically `src/main.ts`)
27
+ - UI entry point if it exists (typically `src/ui.tsx`)
28
+
29
+ If only a subset of files is available, audit what is provided and note which sections cannot be fully evaluated.
30
+
31
+ ## Process
32
+
33
+ Read all provided source files first, then audit against each section in order. For each section, identify specific patterns (good and bad) in the code.
34
+
35
+ ### Section 1: Error Handling
36
+
37
+ Consult `knowledge/plugin-best-practices.md` Section 1.
38
+
39
+ **Check for:**
40
+
41
+ - [ ] **Structured error types** -- Does the plugin define error codes (enum/const) with machine-readable codes, human-readable messages, and optional details? Or are errors thrown as raw strings?
42
+ - [ ] **Try/catch in IPC handlers** -- Is each IPC event handler (`on<Handler>(EVENT, async () => {...})`) wrapped in a single top-level try/catch? Or are there unprotected async handlers?
43
+ - [ ] **Centralized error emission** -- Is there a single `emitError()` helper that logs to console AND emits structured error data to the UI? Or are errors handled ad-hoc in each handler?
44
+ - [ ] **User-facing error messages** -- Are error messages non-technical and actionable (e.g., "Select a frame or component")? Or do they leak stack traces or technical details to users?
45
+ - [ ] **Graceful degradation** -- When processing a tree of nodes, does the plugin skip failed nodes and continue? Or does one failure abort the entire operation?
46
+ - [ ] **UI error display** -- Does the UI handle error events with recovery hints and retry options? Or do errors silently fail or show raw error objects?
47
+ - [ ] **figma.notify usage** -- Are `figma.notify()` calls used for quick user feedback (selection errors, completion messages)?
48
+
49
+ **Rating criteria:**
50
+ - **Pass**: Structured error types, centralized emission, try/catch on all handlers, graceful degradation
51
+ - **Warn**: Try/catch present but inconsistent, no structured types, some unprotected handlers
52
+ - **Fail**: No try/catch in handlers, raw error throwing, no error propagation to UI
53
+
54
+ ### Section 2: Performance
55
+
56
+ Consult `knowledge/plugin-best-practices.md` Section 2.
57
+
58
+ **Check for:**
59
+
60
+ - [ ] **Progress reporting** -- For operations processing 100+ nodes, does the plugin report progress to the UI? Or does it appear frozen during long operations?
61
+ - [ ] **Pipeline timing** -- Are extraction and generation phases instrumented with timing logs? Or is there no visibility into where time is spent?
62
+ - [ ] **Depth limits** -- Is recursive tree traversal capped at a maximum depth (e.g., 30)? Or can deeply nested designs cause stack overflow?
63
+ - [ ] **Batch operations** -- Are child extractions parallelized with `Promise.all`? Are heavy I/O operations (exportAsync) done sequentially? Or is there unbounded parallelism on expensive operations?
64
+ - [ ] **Scoped traversal** -- Does the plugin scope searches to the selected subtree or current page? Or does it call `figma.root.findAll()` on the entire document?
65
+ - [ ] **Bundle size** -- Is the UI built with Preact (not React)? Are heavy libraries lazy-loaded? Is `--minify` enabled in the build?
66
+ - [ ] **Visible children filter** -- Does traversal filter out `visible: false` nodes early? Or are invisible nodes fully processed?
67
+
68
+ **Rating criteria:**
69
+ - **Pass**: Progress reporting, depth limits, pipeline timing, efficient traversal, optimized bundle
70
+ - **Warn**: Missing progress for long operations, no depth limit but no crashes observed, minor inefficiencies
71
+ - **Fail**: `figma.root.findAll()` without scoping, no depth limits, unbounded parallel exportAsync, React instead of Preact
72
+
73
+ ### Section 3: Memory Management
74
+
75
+ Consult `knowledge/plugin-best-practices.md` Section 3.
76
+
77
+ **Check for:**
78
+
79
+ - [ ] **JSON-serializable intermediate format** -- Does the extraction phase produce a plain data structure (ExtractedNode-like)? Or does it try to pass Figma SceneNode objects across IPC?
80
+ - [ ] **Selective property extraction** -- Are only needed properties extracted from each node? Or is every property read regardless of usage?
81
+ - [ ] **Asset deduplication** -- Are images with the same `imageHash` exported only once? Or is the same image exported multiple times?
82
+ - [ ] **Large file safeguards** -- Are there element count warnings, depth limits, and pre-flight checks before heavy operations?
83
+ - [ ] **Cache cleanup** -- Are module-level caches cleared between extraction runs and on page changes? Or do caches grow unbounded?
84
+ - [ ] **Reference nulling** -- Are large data structures nulled out when no longer needed?
85
+
86
+ **Rating criteria:**
87
+ - **Pass**: Serializable intermediate format, selective extraction, deduplication, cache cleanup
88
+ - **Warn**: Serializable format but extracts unnecessary properties, no deduplication
89
+ - **Fail**: Passing SceneNode objects across IPC, no cache cleanup, unbounded memory growth
90
+
91
+ ### Section 4: Caching
92
+
93
+ Consult `knowledge/plugin-best-practices.md` Section 4.
94
+
95
+ **Check for:**
96
+
97
+ - [ ] **Variable cache** -- Are local variable IDs loaded once and cached for the extraction run? Or is `getLocalVariablesAsync()` called repeatedly?
98
+ - [ ] **Font loading cache** -- Are already-loaded fonts tracked to avoid redundant `loadFontAsync` calls?
99
+ - [ ] **Component reference cache** -- Are component names cached to avoid repeated `getMainComponentAsync()` calls?
100
+ - [ ] **Cache invalidation** -- Are caches invalidated at appropriate times (extraction start, page change, selection change)?
101
+ - [ ] **Persistent storage** -- Are user preferences stored in `figma.clientStorage`? Is node-level metadata stored via `pluginData` where appropriate?
102
+ - [ ] **Session vs persistent separation** -- Are volatile caches (variable IDs, extracted data) kept in memory, while durable settings use clientStorage?
103
+
104
+ **Rating criteria:**
105
+ - **Pass**: Variable cache, font cache, proper invalidation, persistent settings
106
+ - **Warn**: Some caching but missing variable or font cache, manual invalidation
107
+ - **Fail**: No caching at all, repeated expensive API calls on every node
108
+
109
+ ### Section 5: Async Patterns
110
+
111
+ Consult `knowledge/plugin-best-practices.md` Section 5.
112
+
113
+ **Check for:**
114
+
115
+ - [ ] **Async node access** -- Uses `getNodeByIdAsync` (not `getNodeById`)? Null-checks results?
116
+ - [ ] **Font loading before text modification** -- Calls `loadFontAsync` before setting `characters` or font properties? Handles `figma.mixed` for multi-font text?
117
+ - [ ] **exportAsync handling** -- Processes exports sequentially for heavy operations? Uses try/catch per export?
118
+ - [ ] **Timeout handling** -- Are long-running operations wrapped with timeout logic? Is there a cancellation pattern for plugin close?
119
+ - [ ] **Sequential vs parallel** -- Are read-only child extractions parallelized while I/O operations are sequential?
120
+ - [ ] **Promise rejection handling** -- Are all async handlers wrapped in try/catch? No unhandled promise rejections?
121
+
122
+ **Rating criteria:**
123
+ - **Pass**: Async-first API usage, proper font loading, timeout handling, cancellation, correct parallel/sequential choices
124
+ - **Warn**: Async APIs used but missing null checks, no timeout handling, minor parallel/sequential issues
125
+ - **Fail**: Sync API usage (getNodeById), no font loading before text modification, unhandled rejections
126
+
127
+ ### Section 6: Testing
128
+
129
+ Consult `knowledge/plugin-best-practices.md` Section 6.
130
+
131
+ **Check for:**
132
+
133
+ - [ ] **Testable architecture** -- Is generation logic separated from Figma API calls? Can generation functions be tested with plain data input?
134
+ - [ ] **Mock data fixtures** -- Are there mock ExtractedNode fixtures for testing generation without the Figma runtime?
135
+ - [ ] **Unit tests for generation** -- Are pure generation functions (layout CSS, visual CSS, HTML rendering) unit tested?
136
+ - [ ] **Code validation** -- Does the plugin validate generated HTML/CSS output (tag matching, bracket matching, no JavaScript injection)?
137
+ - [ ] **Edge case coverage** -- Are edge cases handled: empty selection, zero-size frames, SLICE nodes, detached instances, mixed fonts, deeply nested groups?
138
+ - [ ] **Console logging strategy** -- Are logs prefixed by domain (`[Extraction]`, `[Generation]`, `[Export]`) with relevant data?
139
+
140
+ **Rating criteria:**
141
+ - **Pass**: Generation functions testable and tested, mock fixtures, validation, edge case handling, structured logging
142
+ - **Warn**: Architecture supports testing but few/no tests written, some edge cases missed
143
+ - **Fail**: Generation coupled to Figma API (untestable), no validation, crashes on common edge cases
144
+
145
+ ### Section 7: Distribution
146
+
147
+ Consult `knowledge/plugin-best-practices.md` Section 7.
148
+
149
+ **Check for:**
150
+
151
+ - [ ] **Manifest correctness** -- Is `editorType` correct (["figma"] for standard, ["dev"] for codegen)? Is `documentAccess: "dynamic-page"` set?
152
+ - [ ] **Permission minimization** -- Are only necessary permissions declared? Most plugins need zero permissions.
153
+ - [ ] **Network access scoping** -- If `networkAccess` is declared, are domains specific (not wildcard `*`)? Is reasoning provided?
154
+ - [ ] **Version management** -- Is the version in package.json following semver? Is the version reflected in the plugin name or manifest?
155
+ - [ ] **Build configuration** -- Is `--typecheck` and `--minify` enabled in the build script?
156
+ - [ ] **Publishing metadata** -- Are name, description, icon, and cover image prepared?
157
+
158
+ **Rating criteria:**
159
+ - **Pass**: Correct manifest, minimal permissions, scoped network, semver, optimized build
160
+ - **Warn**: Correct manifest but missing optimization flags, overly broad permissions
161
+ - **Fail**: Wrong editorType, missing dynamic-page, wildcard network access without justification
162
+
163
+ ### Section 8: Codegen-Specific Checks (If Applicable)
164
+
165
+ Only audit this section if the plugin is a codegen plugin (`editorType: ["dev"]`, `capabilities: ["codegen"]`).
166
+
167
+ Consult `knowledge/plugin-codegen.md`.
168
+
169
+ **Check for:**
170
+
171
+ - [ ] **3-second timeout compliance** -- Does the `generate` callback avoid network calls, heavy traversal, and unbounded operations? Is data pre-cached during `preferenceschange`?
172
+ - [ ] **Progressive complexity** -- Does the generator handle simple nodes quickly and only do heavy processing for complex nodes?
173
+ - [ ] **Language routing** -- Does the generate callback route to language-specific generators based on `event.language`?
174
+ - [ ] **CodegenResult format** -- Are results returned as an array of `{title, code, language}` with correct language constants?
175
+ - [ ] **Preferences system** -- Are user preferences (units, CSS strategy) exposed via codegen preferences?
176
+ - [ ] **Pre-caching** -- Is expensive data (component mappings, variable resolution) cached during preference changes, not during generation?
177
+
178
+ ### Section 9: Architecture Checks
179
+
180
+ Consult `knowledge/plugin-architecture.md`.
181
+
182
+ **Check for:**
183
+
184
+ - [ ] **3-stage data flow** -- Is the codebase organized into extraction (Figma API) -> generation (data transformation) -> export (output assembly)?
185
+ - [ ] **IPC type safety** -- Are IPC events defined with TypeScript types? Are event names centralized as constants (not string literals)?
186
+ - [ ] **Domain separation** -- Are extraction, generation, and export in separate directories/modules? Or is everything in one file?
187
+ - [ ] **Event correlation** -- For request/response IPC patterns, are messages correlated (e.g., via IDs or specific event types)?
188
+
189
+ ## Output
190
+
191
+ Generate an audit report with the following structure:
192
+
193
+ ### Audit Report Format
194
+
195
+ ```
196
+ # Figma Plugin Audit Report
197
+ Plugin: {plugin name}
198
+ Date: {date}
199
+ Files audited: {list of files}
200
+
201
+ ## Summary
202
+ Overall: {PASS | WARN | FAIL}
203
+ {1-2 sentence summary of the plugin's quality level}
204
+
205
+ | Section | Rating | Key Finding |
206
+ |---------|--------|-------------|
207
+ | Error Handling | {PASS/WARN/FAIL} | {one-line summary} |
208
+ | Performance | {PASS/WARN/FAIL} | {one-line summary} |
209
+ | Memory Management | {PASS/WARN/FAIL} | {one-line summary} |
210
+ | Caching | {PASS/WARN/FAIL} | {one-line summary} |
211
+ | Async Patterns | {PASS/WARN/FAIL} | {one-line summary} |
212
+ | Testing | {PASS/WARN/FAIL} | {one-line summary} |
213
+ | Distribution | {PASS/WARN/FAIL} | {one-line summary} |
214
+ | Codegen (if applicable) | {PASS/WARN/FAIL} | {one-line summary} |
215
+ | Architecture | {PASS/WARN/FAIL} | {one-line summary} |
216
+
217
+ ## Detailed Findings
218
+
219
+ ### 1. Error Handling — {RATING}
220
+
221
+ **Good:**
222
+ - {specific finding with file:line reference}
223
+
224
+ **Issues:**
225
+ - {specific finding with file:line reference}
226
+ - **Fix:** {concrete code suggestion}
227
+
228
+ ### 2. Performance — {RATING}
229
+ ... (repeat for each section)
230
+
231
+ ## Priority Fixes
232
+ 1. {highest priority fix — what and why}
233
+ 2. {second priority fix}
234
+ 3. {third priority fix}
235
+ ```
236
+
237
+ ### Report Rules
238
+
239
+ - **Every finding must reference a specific file and line/function** -- never say "you should add error handling" without pointing to where
240
+ - **Provide fix code examples** for WARN and FAIL findings -- show the corrected pattern, not just what is wrong
241
+ - **Acknowledge good patterns** -- call out what the plugin does well in each section
242
+ - **Priority fixes** should be ordered by impact: crashes > data loss > poor UX > code quality
243
+ - **Overall rating**: FAIL if any section is FAIL, WARN if any section is WARN and none are FAIL, PASS only if all sections pass
244
+ - If files are insufficient to evaluate a section, mark it as "INCOMPLETE" with a note on what files are needed
@@ -0,0 +1,279 @@
1
+ ---
2
+ name: build-codegen-plugin
3
+ description: Build a Figma Dev Mode codegen plugin that generates code from designs. Use this skill when the user wants to build a plugin that runs in Figma's Dev Mode inspect panel and generates code from selected nodes.
4
+ ---
5
+
6
+ @knowledge/plugin-codegen.md
7
+ @knowledge/figma-api-devmode.md
8
+ @knowledge/plugin-best-practices.md
9
+ @knowledge/figma-api-plugin.md
10
+
11
+ ## Objective
12
+
13
+ Help the user build a Figma codegen plugin that runs in Dev Mode's inspect panel and generates code from selected design nodes. Codegen plugins have unique constraints — a strict 3-second timeout, no network calls during generation, a built-in preferences system, and a specific `CodegenResult[]` return format. This skill handles all of these constraints and produces a working codegen plugin with language routing, pre-caching, and timeout-safe generation.
14
+
15
+ ## Input
16
+
17
+ The user provides their codegen requirements as `$ARGUMENTS`. This may be:
18
+
19
+ - Target language(s) to generate (React/TSX, Vue, HTML+CSS, Tailwind, Swift, Kotlin, custom DSL)
20
+ - A path to an existing codegen plugin to enhance
21
+ - A description of the code generation approach (property extraction vs full component generation)
22
+ - A specific codegen feature to add
23
+
24
+ If the input is a path, read the project files before proceeding. If the input is a description, proceed directly to Phase 1.
25
+
26
+ ## Process
27
+
28
+ ### Phase 1 — Assess
29
+
30
+ Determine the codegen plugin's scope and constraints.
31
+
32
+ **Language targets:**
33
+ - Which languages/frameworks should the plugin generate code for?
34
+ - Each language becomes an entry in the manifest's `codegenLanguages` array
35
+ - Each language gets a dedicated generator module
36
+
37
+ **Complexity level:**
38
+ - **Property extraction**: reads node properties and outputs simple declarations (e.g., CSS properties, style tokens)
39
+ - **Component generation**: produces full component code with structure, styles, and props (more complex, higher timeout risk)
40
+
41
+ **Plugin type:**
42
+ - **Codegen-only** (`editorType: ["dev"]`): runs exclusively in Dev Mode inspect panel. No standard plugin UI.
43
+ - **Hybrid** (`editorType: ["figma", "dev"]`): has both a standard plugin UI (for configuration, export) AND a codegen panel in Dev Mode. Use hybrid when the plugin needs operations beyond code inspection (e.g., batch export, settings UI, node manipulation).
44
+
45
+ **Preferences needed:**
46
+ - Unit system: px vs rem vs em
47
+ - CSS strategy: Tailwind utilities vs CSS Modules vs inline styles vs vanilla CSS
48
+ - Naming convention: camelCase vs kebab-case vs BEM
49
+ - Component style: functional vs class-based
50
+ - Other framework-specific options
51
+
52
+ Report the assessment to the user before proceeding.
53
+
54
+ ### Phase 2 — Recommend
55
+
56
+ Based on the assessment, recommend the architecture.
57
+
58
+ **Manifest configuration:**
59
+ ```json
60
+ {
61
+ "editorType": ["dev"],
62
+ "capabilities": ["codegen"],
63
+ "codegenLanguages": [
64
+ { "label": "React/TSX", "value": "react-tsx" },
65
+ { "label": "HTML + CSS", "value": "html-css" }
66
+ ]
67
+ }
68
+ ```
69
+ - `editorType: ["dev"]` for codegen-only; `["figma", "dev"]` for hybrid
70
+ - `capabilities: ["codegen"]` is required
71
+ - Each language in `codegenLanguages` appears as a tab in the inspect panel
72
+
73
+ **3-second timeout strategy:**
74
+ - The `generate` callback has a hard 3-second timeout — if exceeded, Figma kills the operation
75
+ - **Pre-cache during `preferenceschange`**: load variables, resolve component references, build lookup tables. This event fires when the user opens the plugin or changes preferences — no timeout pressure.
76
+ - **Keep `generate` lightweight**: only read the selected node's immediate properties, look up pre-cached data, assemble code string. No `getNodeByIdAsync`, no `exportAsync`, no network calls.
77
+ - **Progressive complexity**: handle simple nodes quickly (single properties), only do heavier processing for complex component nodes if time budget allows
78
+
79
+ **Preference system:**
80
+ - Use Figma's built-in codegen preferences panel (NOT a custom iframe UI)
81
+ - Preferences are defined in the manifest or via `figma.codegen.on('preferenceschange')`
82
+ - Preference values are available in both the `generate` and `preferenceschange` callbacks via `event.preferences`
83
+
84
+ **Language routing:**
85
+ - The `generate` callback receives `event.language` indicating which language tab the user selected
86
+ - Route to dedicated generator modules: `generateReact(node)`, `generateHTML(node)`, etc.
87
+ - Each generator module is a pure function: node data in → `CodegenResult[]` out
88
+
89
+ **Dev Resources linking (optional):**
90
+ - Link generated code to external resources (GitHub files, Storybook URLs, documentation)
91
+ - Use `figma.codegen.on('resultchange')` to update Dev Resources when code changes
92
+ - Dev Resources appear in the inspect panel alongside generated code
93
+
94
+ **Hybrid architecture (if applicable):**
95
+ - Standard UI (`src/ui.tsx`) handles configuration, batch operations, settings
96
+ - Codegen (`src/codegen.ts`) handles per-node code generation in Dev Mode
97
+ - Shared modules for generation logic used by both
98
+ - Separate entry points in manifest: `main` for standard, `codegen` for Dev Mode
99
+
100
+ Present the recommendations to the user and confirm before implementing.
101
+
102
+ ### Phase 3 — Implement
103
+
104
+ Generate the codegen plugin code.
105
+
106
+ **1. Manifest / `package.json` `figma-plugin` section:**
107
+ ```json
108
+ {
109
+ "name": "Plugin Name",
110
+ "id": "REPLACE_WITH_PLUGIN_ID",
111
+ "editorType": ["dev"],
112
+ "capabilities": ["codegen"],
113
+ "codegenLanguages": [
114
+ { "label": "React/TSX", "value": "react-tsx" }
115
+ ],
116
+ "codegenPreferences": [
117
+ {
118
+ "itemType": "select",
119
+ "propertyName": "unitSystem",
120
+ "label": "Unit System",
121
+ "options": [
122
+ { "label": "rem", "value": "rem", "isDefault": true },
123
+ { "label": "px", "value": "px" }
124
+ ]
125
+ }
126
+ ]
127
+ }
128
+ ```
129
+
130
+ **2. Main entry point (`src/main.ts`):**
131
+
132
+ ```typescript
133
+ // Pre-cached data populated during preferenceschange
134
+ let variableCache: Map<string, ResolvedVariable> = new Map();
135
+ let componentCache: Map<string, string> = new Map();
136
+
137
+ figma.codegen.on('preferenceschange', async (event) => {
138
+ // Heavy work happens here — no timeout pressure
139
+ try {
140
+ // Load and cache all local variables
141
+ const variables = await figma.variables.getLocalVariablesAsync();
142
+ variableCache.clear();
143
+ for (const variable of variables) {
144
+ variableCache.set(variable.id, resolveVariable(variable));
145
+ }
146
+
147
+ // Cache component names for instance detection
148
+ // ... additional pre-caching
149
+ } catch (error) {
150
+ console.error('[Codegen] Pre-cache failed:', error);
151
+ }
152
+ });
153
+
154
+ figma.codegen.on('generate', (event) => {
155
+ // Lightweight — must complete within 3 seconds
156
+ // No async operations, no network calls
157
+ try {
158
+ const { node, language } = event;
159
+
160
+ switch (language) {
161
+ case 'react-tsx':
162
+ return generateReact(node, event.preferences, variableCache);
163
+ case 'html-css':
164
+ return generateHTML(node, event.preferences, variableCache);
165
+ default:
166
+ return [{ title: 'Error', code: `Unknown language: ${language}`, language: 'PLAINTEXT' }];
167
+ }
168
+ } catch (error) {
169
+ return [{ title: 'Error', code: String(error), language: 'PLAINTEXT' }];
170
+ }
171
+ });
172
+ ```
173
+
174
+ **3. Language-specific generator modules:**
175
+
176
+ Each generator is a pure function:
177
+ ```typescript
178
+ // src/generators/react.ts
179
+ export function generateReact(
180
+ node: SceneNode,
181
+ preferences: Record<string, string>,
182
+ variables: Map<string, ResolvedVariable>
183
+ ): CodegenResult[] {
184
+ // Read node properties (synchronous — no async API calls)
185
+ // Look up pre-cached variable bindings
186
+ // Assemble React/TSX code string
187
+ // Return CodegenResult array
188
+
189
+ return [
190
+ {
191
+ title: 'Component.tsx',
192
+ code: componentCode,
193
+ language: 'TYPESCRIPT',
194
+ },
195
+ {
196
+ title: 'Component.module.css',
197
+ code: cssCode,
198
+ language: 'CSS',
199
+ },
200
+ ];
201
+ }
202
+ ```
203
+
204
+ **4. Preference handling:**
205
+ - Read preferences from `event.preferences` in both callbacks
206
+ - Apply preference values to generation (unit conversion, naming convention, CSS strategy)
207
+ - Provide sensible defaults for all preferences
208
+
209
+ **5. Code quality patterns:**
210
+ - Try/catch in both `generate` and `preferenceschange` callbacks
211
+ - Graceful fallback: if generation fails for a node, return a helpful error message as a `CodegenResult` (not an exception)
212
+ - Code validation: verify generated code has balanced brackets, valid syntax structure
213
+ - Progressive detail: simple nodes get simple output, complex nodes get full component generation
214
+
215
+ ### Phase 4 — Validate
216
+
217
+ Verify the codegen plugin meets Figma's constraints.
218
+
219
+ **Timeout compliance:**
220
+ - [ ] No `async` keyword or `await` in the `generate` callback
221
+ - [ ] No `getNodeByIdAsync`, `loadFontAsync`, `exportAsync` in `generate`
222
+ - [ ] No `fetch()` or network calls in `generate`
223
+ - [ ] Heavy data loading happens in `preferenceschange` (pre-caching)
224
+ - [ ] Node property reads in `generate` are synchronous and direct
225
+
226
+ **Manifest correctness:**
227
+ - [ ] `editorType` includes `"dev"`
228
+ - [ ] `capabilities` includes `"codegen"`
229
+ - [ ] `codegenLanguages` array is populated with at least one language
230
+ - [ ] Each language has `label` (display name) and `value` (event identifier)
231
+ - [ ] Preferences use valid `itemType` values (`select`, `input`, `separator`)
232
+
233
+ **Output format:**
234
+ - [ ] `generate` returns `CodegenResult[]` (array, not single object)
235
+ - [ ] Each result has `title` (string), `code` (string), `language` (Figma language constant)
236
+ - [ ] Language constants are valid: `CSS`, `HTML`, `JAVASCRIPT`, `TYPESCRIPT`, `JSON`, `PLAINTEXT`, etc.
237
+
238
+ **Pre-caching:**
239
+ - [ ] Variable resolution cached during `preferenceschange`
240
+ - [ ] Component name lookups cached
241
+ - [ ] Caches are refreshed on preference changes (not stale between sessions)
242
+
243
+ **Error handling:**
244
+ - [ ] Both `generate` and `preferenceschange` have try/catch
245
+ - [ ] Generation errors produce a readable error CodegenResult (not a crash)
246
+ - [ ] Pre-cache failures are logged but don't prevent generation from working with partial data
247
+
248
+ ## Output
249
+
250
+ Generate the appropriate files:
251
+
252
+ ### Codegen-Only Plugin Output
253
+
254
+ - **`package.json`** — with `figma-plugin` section including codegen config
255
+ - **`src/main.ts`** — Entry point with `preferenceschange` (pre-caching) and `generate` (routing) handlers
256
+ - **`src/generators/{language}.ts`** — One generator module per target language
257
+ - **`src/types.ts`** — Shared types, resolved variable interfaces, preference types
258
+ - **`tsconfig.json`** — TypeScript configuration
259
+
260
+ ### Hybrid Plugin Output (if applicable)
261
+
262
+ All of the above, plus:
263
+ - **`src/ui.tsx`** — Standard plugin UI for configuration/batch operations
264
+ - Separate entry points in manifest for standard and codegen modes
265
+
266
+ ### Output Checklist
267
+
268
+ Before returning the codegen plugin code, verify:
269
+
270
+ - [ ] Manifest has `capabilities: ["codegen"]` and correct `editorType`
271
+ - [ ] `codegenLanguages` array populated with all target languages
272
+ - [ ] 3-second timeout budget respected — `generate` callback is synchronous and lightweight
273
+ - [ ] No network calls, no async API calls inside `generate`
274
+ - [ ] Heavy data loading pre-cached in `preferenceschange` handler
275
+ - [ ] `CodegenResult[]` format correct with valid language constants
276
+ - [ ] Preferences use Figma's built-in preference system (not custom UI)
277
+ - [ ] Language routing dispatches to dedicated generator modules
278
+ - [ ] Error handling produces readable error results (not crashes)
279
+ - [ ] Pre-cached data is refreshed on preference changes