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.
- package/README.md +133 -0
- package/bin/install.js +328 -0
- package/knowledge/README.md +62 -0
- package/knowledge/css-strategy.md +973 -0
- package/knowledge/design-to-code-assets.md +855 -0
- package/knowledge/design-to-code-layout.md +929 -0
- package/knowledge/design-to-code-semantic.md +1085 -0
- package/knowledge/design-to-code-typography.md +1003 -0
- package/knowledge/design-to-code-visual.md +1145 -0
- package/knowledge/design-tokens-variables.md +1261 -0
- package/knowledge/design-tokens.md +960 -0
- package/knowledge/figma-api-devmode.md +894 -0
- package/knowledge/figma-api-plugin.md +920 -0
- package/knowledge/figma-api-rest.md +742 -0
- package/knowledge/figma-api-variables.md +848 -0
- package/knowledge/figma-api-webhooks.md +876 -0
- package/knowledge/payload-blocks.md +1184 -0
- package/knowledge/payload-figma-mapping.md +1210 -0
- package/knowledge/payload-visual-builder.md +1004 -0
- package/knowledge/plugin-architecture.md +1176 -0
- package/knowledge/plugin-best-practices.md +1206 -0
- package/knowledge/plugin-codegen.md +1313 -0
- package/package.json +31 -0
- package/skills/README.md +103 -0
- package/skills/audit-plugin/SKILL.md +244 -0
- package/skills/build-codegen-plugin/SKILL.md +279 -0
- package/skills/build-importer/SKILL.md +320 -0
- package/skills/build-plugin/SKILL.md +199 -0
- package/skills/build-token-pipeline/SKILL.md +363 -0
- package/skills/ref-html/SKILL.md +290 -0
- package/skills/ref-layout/SKILL.md +150 -0
- package/skills/ref-payload-block/SKILL.md +415 -0
- package/skills/ref-react/SKILL.md +222 -0
- 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
|
+
}
|
package/skills/README.md
ADDED
|
@@ -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
|