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

8.1 KiB
Raw Permalink Blame History

title aliases tags sources created updated
Figma Code Connect — Skill Workflow (.figma.ts templates)
figma-code-connect-skill
figma-ts-templates
code-connect-workflow
figma
code-connect
mcp
skill
typescript
design-to-code
raw/Skill Code Connect Developer Docs.md
2026-05-15 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:
    { "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-YX:Y
figma.com/file/:fileKey/:name?node-id=X-Y :fileKey X-YX:Y
Branch URL with :branchKey use :branchKey from node-id param

Always convert hyphens to colons in nodeId: 1234-56781234: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

// 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:

// 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

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

// 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

Sources

  • raw/Skill Code Connect Developer Docs.md — Figma Developer Docs, Code Connect skill reference