obsidian/wiki/claude-code/figma-code-connect-skill.md
2026-05-15 10:29:55 +01:00

203 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "Figma Code Connect — Skill Workflow (.figma.ts templates)"
aliases: [figma-code-connect-skill, figma-ts-templates, code-connect-workflow]
tags: [figma, code-connect, mcp, skill, typescript, design-to-code]
sources: [raw/Skill Code Connect Developer Docs.md]
created: 2026-05-15
updated: 2026-05-15
---
# Figma Code Connect — Skill Workflow
Step-by-step process for creating `.figma.ts` template files that map Figma components to code snippets using the Figma MCP server skill.
> Covers **template files only** (`.figma.ts` using MCP tools). Parser-based files (`.figma.tsx` with `figma.connect()` via CLI) are a separate approach.
## Prerequisites
- Figma MCP tools available (e.g. `get_code_connect_suggestions`) — verify before starting
- Component published to a Figma team library (unpublished = stop)
- Organization or Enterprise plan (not Free/Pro)
- Figma URL must include `node-id` query param
- Add `@figma/code-connect/figma-types` to `tsconfig.json`:
```json
{ "compilerOptions": { "types": ["@figma/code-connect/figma-types"] } }
```
## 6-Step Workflow
### Step 1 — Parse the Figma URL
Extract `fileKey` and `nodeId`:
| URL format | fileKey | nodeId |
|-----------|---------|--------|
| `figma.com/design/:fileKey/:name?node-id=X-Y` | `:fileKey` | `X-Y` → `X:Y` |
| `figma.com/file/:fileKey/:name?node-id=X-Y` | `:fileKey` | `X-Y` → `X:Y` |
| Branch URL with `:branchKey` | use `:branchKey` | from `node-id` param |
**Always convert hyphens to colons in nodeId**: `1234-5678` → `1234:5678`
### Step 2 — Discover Unmapped Components
Call `get_code_connect_suggestions` with `fileKey`, `nodeId`, `excludeMappingPrompt: true`.
- **"No published components found"** → tell user to publish first, stop
- **"All already connected"** → inform user, stop
- **Normal response** → extract `mainComponentNodeId` per component; use these (not the original URL node) for all subsequent steps. Repeat Steps 36 for each component.
### Step 3 — Fetch Component Properties
Call `get_context_for_code_connect` with `fileKey`, resolved `nodeId`, `clientFrameworks`, `clientLanguages`.
Property types returned:
| Type | Description |
|------|-------------|
| TEXT | Text content (labels, placeholders) |
| BOOLEAN | Toggle (show/hide, disabled) |
| VARIANT | Enum options (size, state) |
| INSTANCE_SWAP | Swappable nested instance (icon) |
| SLOT | Freeform content region |
### Step 4 — Identify the Code Component
1. Check `figma.config.json` for `paths`/`importPaths`
2. Search codebase in `src/components/`, `components/`, `lib/ui/`, `app/components/`
3. Compare props interface vs Figma properties from Step 3
4. **Confirm with user** before writing the template
### Step 5 — Create the Template File
**File location:** alongside existing `.figma.ts`/`.figma.tsx` files, named `ComponentName.figma.ts`
#### Template structure
```ts
// url=https://www.figma.com/file/{fileKey}/{fileName}?node-id={nodeId}
// source={path to code component}
// component={component name}
import figma from 'figma'
const instance = figma.selectedInstance
// property extractions...
export default {
example: figma.code`<Component ... />`,
imports: ['import { Component } from "..."'],
id: 'component-name',
metadata: { nestable: true, props: {} }
}
```
#### Property mapping methods
| Figma Type | Method | Notes |
|-----------|--------|-------|
| TEXT | `instance.getString('Name')` | Returns string |
| BOOLEAN | `instance.getBoolean('Name', { true: ..., false: ... })` | Mapping optional |
| VARIANT | `instance.getEnum('Name', { 'FigmaVal': 'codeVal' })` | Must map ALL values |
| INSTANCE_SWAP | `instance.getInstanceSwap('Name')` | Returns `InstanceHandle \| null` |
| SLOT | `instance.getSlot('Name')` | Returns `ResultSection[] \| undefined` |
| Child layer | `instance.findInstance('LayerName')` | No component property |
| Text layer | `instance.findText('LayerName').textContent` | Named text layer |
#### VARIANT exhaustive mapping (critical)
Every value from `get_context_for_code_connect` **must** appear in `getEnum`. Unmapped value → silent `undefined`:
```ts
// Correct — all 4 values mapped
const status = instance.getEnum('Status', {
'Success': 'success',
'Error': 'error',
'Warning': 'warning',
'Info': 'info',
})
```
#### Interpolation rules
| Value type | Wrapping |
|-----------|----------|
| String (`getString`, `getEnum`, `textContent`) | Quotes: `variant="${variant}"` |
| Instance snippet (`executeTemplate().example`) | Braces: `icon={${iconCode}}` |
| Slot sections (`getSlot()`) | Directly in template: `` `<X>${content}</X>` `` |
| Boolean bare prop | Conditional: `${disabled ? 'disabled' : ''}` |
#### Instance swap pattern
```ts
const icon = instance.getInstanceSwap('Icon')
let iconCode
if (icon && icon.type === 'INSTANCE') { // type check required — findInstance returns ErrorHandle on failure
iconCode = icon.executeTemplate().example
}
```
#### SelectorOptions for `findInstance`/`findText`
```ts
// Target inside a nested instance (stop at boundary by default)
instance.findInstance('child', { traverseInstances: true })
// Disambiguate duplicate layer names
instance.findInstance('child', { traverseInstances: true, path: ['ParentLayer'] })
```
### Step 6 — Validate
Read back the file and check:
- Every Figma property from Step 3 is covered
- All emitted attributes exist in the code component's `Props` interface (never invent props)
- No hardcoded children — INSTANCE_SWAP and slots use dynamic APIs
- INSTANCE_SWAP uses `getInstanceSwap()`, not `getSlot()`; SLOT uses `getSlot()`, not `getInstanceSwap()`
- `type === 'INSTANCE'` check present before every `executeTemplate()` call
## Key Takeaways
- **6 steps**: parse URL → discover unmapped → fetch properties → identify code component → write template → validate
- **VARIANT coverage is mandatory** — every enum value must be in the mapping; missing = silent `undefined`
- **Never string-concatenate `ResultSection[]`** — interpolate inside `` figma.code`...` `` tagged templates
- **`hasCodeConnect()` guard is wrong** — always call `executeTemplate()` directly after `type === 'INSTANCE'` check
- **`getSlot()` ≠ `getInstanceSwap()`** — SLOT type uses `getSlot()`, INSTANCE_SWAP uses `getInstanceSwap()`; they are not interchangeable
- **Never hardcode child content** — always resolve dynamically via `executeTemplate()`, omit if no Code Connect exists
- **`findInstance()` returns ErrorHandle (truthy) on failure**, not null — always add `type === 'INSTANCE'` guard
- **Confirm code component match with user** before writing the template (Step 4)
## Quick API Reference
### `instance.*` methods
| Method | Returns |
|--------|---------|
| `getString(prop)` | `string` |
| `getBoolean(prop, mapping?)` | `boolean \| any` |
| `getEnum(prop, mapping)` | `any` |
| `getInstanceSwap(prop)` | `InstanceHandle \| null` |
| `getSlot(prop)` | `ResultSection[] \| undefined` |
| `findInstance(name, opts?)` | `InstanceHandle \| ErrorHandle` |
| `findText(name, opts?)` | `TextHandle \| ErrorHandle` |
| `findConnectedInstance(id, opts?)` | `InstanceHandle \| ErrorHandle` |
| `findConnectedInstances(fn, opts?)` | `InstanceHandle[]` |
| `findLayers(fn, opts?)` | `(InstanceHandle \| TextHandle)[]` |
### `InstanceHandle` methods
| Method | Returns |
|--------|---------|
| `executeTemplate()` | `{ example: ResultSection[], metadata: Metadata }` |
| `hasCodeConnect()` | `boolean` (avoid as a guard — see pitfalls) |
| `codeConnectId()` | `string \| null` |
## Related Articles
- [[wiki/claude-code/figma-mcp-code-connect|figma-mcp-code-connect]] — higher-level overview: CodeConnectSnippet wrapper, CLI vs MCP mappings
- [[wiki/claude-code/figma-mcp-skills|figma-mcp-skills]] — all 8 Figma MCP skills including `figma-code-connect-components`
- [[wiki/claude-code/figma-mcp-setup|figma-mcp-setup]] — enable Figma MCP server in Claude Code
- [[wiki/claude-code/figma-skill-build-screens|figma-skill-build-screens]] — building/updating Figma screens from design system
- [[wiki/claude-code/figma-mcp-guide|figma-mcp-guide]] — Figma MCP server overview and capabilities
## Sources
- `raw/Skill Code Connect Developer Docs.md` — Figma Developer Docs, Code Connect skill reference