Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Choose between Figma integration architectures: CLI script, webhook service, or plugin. Use when deciding how to integrate with Figma, comparing REST API vs Plugin API, or planning a Figma-connected application. Trigger with phrases like "figma architecture", "figma blueprint", "how to integrate figma", "figma plugin vs api", "figma project type".
.claude/skills/jeremylongshore-figma-architecture-variants/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 276% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 95% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 94% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 118% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 90% | 0% |
Three proven architecture patterns for Figma integrations, based on the two primary Figma APIs: the REST API (external tools) and the Plugin API (in-editor experiences).
| Architecture | API Used | Best For | Hosting | |-------------|----------|----------|---------| | CLI/Script | REST API | Design token sync, asset export | None (runs locally or in CI) | | Webhook Service | REST API | Real-time automation, Slack bots | Server/serverless | | Figma Plugin | Plugin API | In-editor tools, design linting | Runs in Figma desktop app |
Use case: Extract design tokens, export icons, sync to code
Developer runs script
│
▼
┌─────────────┐
│ CLI Script │ (Node.js)
│ - extract.ts │
└──────┬───────┘
│ GET /v1/files/:key
│ GET /v1/images/:key
▼
┌─────────────┐
│ Figma REST │
│ API │
└──────┬──────┘
│
▼
┌─────────────┐
│ Output │
│ - tokens.css│
│ - icons/ │
└─────────────┘json{ "scripts": { "figma:tokens": "tsx scripts/extract-tokens.ts", "figma:icons": "tsx scripts/export-icons.ts", "figma:sync": "npm run figma:tokens && npm run figma:icons" } }
Pros: Zero infrastructure, runs in CI, easy to debug Cons: Not real-time, manual trigger, no webhook support
Use case: Auto-sync on file save, Slack notifications, build triggers
┌─────────────┐
│ Figma Cloud │
│ FILE_UPDATE │──── Webhook V2 ────┐
│ FILE_COMMENT │ │
└──────────────┘ │
▼
┌──────────────┐
│ Your Service │
│ (Vercel/Fly) │
├──────────────┤
│ /webhooks │ ← Verify passcode
│ /health │
│ /api/tokens │
└──────┬───────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Token │ │ Slack │ │ CI │
│ Rebuild │ │ Notify │ │ Trigger │
└──────────┘ └──────────┘ └──────────┘typescript// Minimal webhook service (Express) const app = express(); app.post('/webhooks/figma', express.json(), verifyPasscode, (req, res) => { res.status(200).json({ received: true }); processEvent(req.body); // async }); app.get('/health', healthCheck); app.listen(process.env.PORT || 3000);
Pros: Real-time, event-driven, no polling waste Cons: Requires hosting, HTTPS endpoint, webhook management
Use case: Design linting, component generation, data population
┌─────────────────────────────────────────┐
│ Figma Desktop App │
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Plugin │ │ Canvas │ │
│ │ Sandbox │ │ (your design) │ │
│ │ │ │ │ │
│ │ code.ts │◄──│ figma.currentPage│ │
│ │ figma.* │──►│ figma.createRect │ │
│ │ │ │ │ │
│ ├─────────────┤ └─────────────────┘ │
│ │ UI iframe │ │
│ │ ui.html │ │
│ │ (React/HTML)│ │
│ └─────────────┘ │
└─────────────────────────────────────────┘json// manifest.json { "name": "My Design Linter", "id": "1234567890", "api": "1.0.0", "main": "dist/code.js", "ui": "dist/ui.html", "editorType": ["figma"], "permissions": ["currentuser"] }
typescript// code.ts -- Plugin API (runs in Figma sandbox) // Access the document directly -- no REST API needed const page = figma.currentPage; const frames = page.findAll(n => n.type === 'FRAME'); // Create nodes programmatically const rect = figma.createRectangle(); rect.resize(200, 100); rect.fills = [{ type: 'SOLID', color: { r: 1, g: 0.5, b: 0 } }]; page.appendChild(rect); // Read component properties const components = page.findAll(n => n.type === 'COMPONENT') as ComponentNode[]; for (const comp of components) { console.log(`${comp.name}: ${comp.width}x${comp.height}`); }
Pros: Direct document access, instant feedback, rich UI Cons: Only works in Figma desktop, no server-side processing, sandboxed
| Factor | CLI Script | Webhook Service | Figma Plugin | |--------|-----------|-----------------|--------------| | Real-time | No | Yes | Yes (in-editor) | | Infrastructure | None | Server/serverless | None | | CI/CD integration | Natural | Via webhook | Not applicable | | User interaction | No | No | Yes | | API used | REST API | REST API | Plugin API | | File modification | No (read-only) | No (read-only) | Yes (full access) | | Figma app required | No | No | Yes | | Auth | PAT | PAT + webhook passcode | None (runs in Figma) |
Many production systems combine variants:
CLI (CI) ← Scheduled token sync (daily at 9 AM)
+
Webhook Service ← Real-time notifications (Slack, rebuild triggers)
+
Figma Plugin ← In-editor design linting and data population| Issue | Cause | Solution | |-------|-------|----------| | CLI too slow | Full file fetch | Use depth=1 and /nodes | | Webhook not firing | No HTTPS | Deploy to platform with TLS | | Plugin sandbox limits | Heavy computation | Offload to REST API via fetch in UI iframe | | Wrong variant choice | Over-engineering | Start with CLI, add webhook when needed |
Pick a variant with the Step 2 decision matrix — two common calls:
LIBRARY_PUBLISH). Polling would burn the rate budget; a plugin can't run headless.Smoke-test the Variant B receiver locally before registering the webhook:
bashcurl -s -X POST localhost:3000/figma/webhook \ -H 'Content-Type: application/json' \ -d '{"event_type":"PING","passcode":"test-passcode"}' # 200 {"ok":true}
Per-variant scaffolds: references/variant-a-cli-script-simplest.md, references/variant-b-webhook-service-event-driven.md, references/variant-c-figma-plugin-in-editor.md.
For common anti-patterns, see figma-known-pitfalls.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 15,349 | 16,302 | +6% | 1 | 1 | 0% | 2,716 | 4,620 | +70% | 0 | 0 | — |
case-02 | pass→pass | 18,383 | 14,919 | -19% | 1 | 1 | 0% | 2,834 | 4,893 | +73% | 0 | 0 | — |
case-03 | fail→pass | 29,839 | 15,820 | -47% | 1 | 1 | 0% | 1,197 | 4,499 | +276% | 0 | 0 | — |
case-04 | pass→pass | 14,750 | 13,351 | -9% | 1 | 1 | 0% | 2,634 | 4,328 | +64% | 0 | 0 | — |
case-05 | pass→pass | 16,721 | 18,129 | +8% | 1 | 1 | 0% | 3,024 | 4,719 | +56% | 0 | 0 | — |
case-06 | pass→pass | 12,469 | 7,683 | -38% | 1 | 1 | 0% | 1,991 | 3,378 | +70% | 0 | 0 | — |
case-07 | fail→pass | 14,796 | 13,380 | -10% | 1 | 1 | 0% | 2,312 | 4,500 | +95% | 0 | 0 | — |
case-08 | pass→pass | 27,918 | 32,751 | +17% | 1 | 1 | 0% | 3,985 | 7,470 | +87% | 0 | 0 | — |
case-09 | fail→pass | 11,567 | 10,355 | -10% | 1 | 1 | 0% | 2,016 | 3,915 | +94% | 0 | 0 | — |
case-10 | pass→pass | 7,350 | 7,414 | +1% | 1 | 1 | 0% | 1,395 | 3,363 | +141% | 0 | 0 | — |
case-11 | pass→pass | 25,118 | 12,467 | -50% | 1 | 1 | 0% | 2,201 | 4,390 | +99% | 0 | 0 | — |
case-12 | pass→pass | 22,635 | 14,263 | -37% | 1 | 1 | 0% | 3,162 | 4,414 | +40% | 0 | 0 | — |
case-13 | fail→pass | 14,547 | 14,179 | -3% | 1 | 1 | 0% | 1,985 | 4,332 | +118% | 0 | 0 | — |
case-14 | pass→pass | 10,733 | 4,621 | -57% | 1 | 1 | 0% | 1,962 | 2,940 | +50% | 0 | 0 | — |
case-15 | pass→pass | 12,126 | 4,967 | -59% | 1 | 1 | 0% | 1,864 | 2,917 | +56% | 0 | 0 | — |
case-16 | fail→fail | 15,006 | 10,260 | -32% | 1 | 1 | 0% | 2,084 | 3,774 | +81% | 0 | 0 | — |
case-17 | pass→pass | 10,440 | 8,339 | -20% | 1 | 1 | 0% | 1,577 | 3,544 | +125% | 0 | 0 | — |
case-18 | pass→pass | 12,393 | 7,612 | -39% | 1 | 1 | 0% | 1,792 | 3,379 | +89% | 0 | 0 | — |
case-19 | fail→pass | 10,337 | 7,512 | -27% | 1 | 1 | 0% | 1,714 | 3,260 | +90% | 0 | 0 | — |
case-20 | fail→pass | 16,188 | 18,649 | +15% | 1 | 1 | 0% | 2,716 | 5,053 | +86% | 0 | 0 | — |
case-21 | fail→fail | 11,188 | 9,171 | -18% | 1 | 1 | 0% | 1,534 | 3,542 | +131% | 0 | 0 | — |
case-22 | pass→pass | 13,072 | 15,408 | +18% | 1 | 1 | 0% | 2,483 | 4,379 | +76% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +27 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.