All skills
figma avatar

/figma-code-connect

@ef474d1 official
by figmafigma/mcp-server-guide2k stars
194

Creates and maintains Figma Code Connect template files that map Figma components to code snippets. Use when the user mentions Code Connect, Figma component mapping, design-to-code translation, or asks to create/update .figma.ts or .figma.js files.

Use this Skill: https://skilld.dev/gh/figma/mcp-server-guide/figma-code-connect

This session only. Nothing lands on disk.

referencesapi.md

≈5.8k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Code Connect Template API Reference

Overview

Code Connect uses template files (.figma.js) to connect your code components to Figma designs. This API reference covers the complete template system for creating these mappings.

Quick Start

A minimal Code Connect template:

// url=https://www.figma.com/file/abc123/MyFile?node-id=123-456
// source=src/components/Button.tsx
// component=Button
const figma = require('figma')
const instance = figma.selectedInstance

const label = instance.getString('Label')

export default {
  example: figma.code`<Button label="${label}" />`,
  imports: ['import { Button } from "./Button"'],
  id: 'button'
}

Table of Contents

  1. Project Configuration
  2. Template File Structure
  3. Core API Reference
  4. Working with Properties
  5. Working with Nested Components
  6. Publishing and Management
  7. Type Reference

Project Configuration

figma.config.json

Place this file in your project root to configure Code Connect.

Required Configuration
{
  "codeConnect": {
    "include": ["**/*.figma.js"],
    "label": "React",
    "language": "tsx"
  }
}
Configuration Options
Option Type Description
include string[] Globs for where to find Code Connect files (relative to config file)
exclude string[] Globs for files to exclude (e.g., ["test/**", "build/**"])
label string Label shown in Figma Dev Mode for your snippets
language string Language for syntax highlighting (see supported languages below)
documentUrlSubstitutions object URL substitutions for multiple Figma files
Supported Languages

jsx, tsx, typescript, javascript, swift, kotlin, html, css, json, python, go, rust, bash, xml, dart, ruby, cpp, sql, graphql, plaintext

URL Substitutions Example
{
  "codeConnect": {
    "documentUrlSubstitutions": {
      "<PROD_FILE>": "https://figma.com/design/abc123/Production",
      "<TEST_FILE>": "https://figma.com/design/xyz789/Testing"
    }
  }
}

Use placeholders in templates:

// url=<PROD_FILE>?node-id=123-456
// source=<path to code component>
// component=<component name>

Template File Structure

File Naming

Templates must use the .figma.js extension:

  • Button.figma.js
  • Card.figma.js
  • MyComponent.figma.js

Required Metadata Comments

Every template starts with metadata comments:

// url=https://www.figma.com/file/abc123/MyFile?node-id=123-456
// source=src/components/Button.tsx
// component=Button

Getting the URL: In Figma, right-click component → "Copy link to selection"

Export Structure

export default {
  example: ResultSection[],      // Required: The code snippet
  id: string,                    // Required: Unique identifier
  imports?: string[],            // Optional: Import statements
  metadata?: {                   // Optional: Display settings
    nestable?: boolean,          // Show inline (true) or as pill (false)
    props?: Record<string, any>  // Data for parent templates
  }
}

Complete Example

// url=https://www.figma.com/file/abc123/MyFile?node-id=123-456
// source=src/Button.tsx
// component=Button

const figma = require('figma')
const instance = figma.selectedInstance

// Extract properties from Figma
const label = instance.getString('Label')
const variant = instance.getEnum('Variant', {
  Primary: 'primary',
  Secondary: 'secondary'
})
const disabled = instance.getBoolean('Disabled')
const icon = instance.findInstance('Icon')

export default {
  example: figma.code`
    <Button
      variant="${variant}"
      ${disabled ? 'disabled' : ''}
      ${icon ? figma.code`icon={${icon.executeTemplate().example}}` : ''}
    >
      ${label}
    </Button>
  `,
  imports: ['import { Button } from "./Button"'],
  id: 'button',
  metadata: {
    nestable: true
  }
}

Core API Reference

figma Object

Import with: const figma = require('figma')

figma.selectedInstance: InstanceHandle

The currently selected Figma component instance. This is your main entry point for accessing component data.

Tagged Template Literals

Use these to wrap your code snippets for proper syntax highlighting:

Template Use For
figma.code Generic code (fallback)
figma.tsx React/TypeScript JSX
figma.jsx React JavaScript
figma.html HTML markup
figma.swift Swift code
figma.kotlin Kotlin code

Example:

const example = figma.tsx`<MyComponent prop="${value}" />`

Important: Never use string concatenation on template results. Always wrap in figma.code:

// Wrong
const snippet = iconSnippet + buttonSnippet

// Correct
const snippet = figma.code`${iconSnippet}${buttonSnippet}`
figma.helpers

Helper utilities for rendering code patterns:

React Helpers:

figma.helpers.react.renderProp('propName', value)
figma.helpers.react.renderChildren(children)
figma.helpers.react.jsxElement('<Icon />')
figma.properties

Access child components by type:

const buttons = figma.properties.children(['Button'])
const icons = figma.properties.children(['Icon', 'Avatar'])

Working with Properties

Reading Component Properties

getString(propName: string): string

Gets a text property value from the Figma component.

const label = instance.getString('Label')
const placeholder = instance.getString('Placeholder Text')
getBoolean(propName: string, mapping?: object): boolean | any

Gets a boolean property with optional value mapping.

// Simple boolean
const isDisabled = instance.getBoolean('Disabled')

// Map to custom values
const hasIcon = instance.getBoolean('Has Icon', {
  true: figma.code`<Icon />`,
  false: null
})
getEnum(propName: string, mapping: object): any

Maps Figma variant values to code values.

const size = instance.getEnum('Size', {
  Small: 'sm',
  Medium: 'md',
  Large: 'lg'
})

const variant = instance.getEnum('Variant', {
  Primary: 'primary',
  Secondary: 'secondary',
  Tertiary: 'tertiary'
})
getInstanceSwap(propName: string): InstanceHandle

Gets a swapped instance from an instance swap property.

const icon = instance.getInstanceSwap('Icon')
if (icon) {
  const iconCode = icon.executeTemplate().example
}
getSlot(propName: string): ResultSection[] | undefined

Reads a Figma component property whose type is SLOT (not INSTANCE_SWAP). Returns a ResultSection[] containing a slot section (type: 'SLOT'). Returns undefined if the property is missing or invalid. Do not call executeTemplate() on this value — unlike getInstanceSwap(), it is not an InstanceHandle.

const content = instance.getSlot('Content')

export default {
  example: figma.code`<Card>${content}</Card>`
}
getPropertyValue(propName: string): string | boolean

Gets the raw property value without mapping.

const rawValue = instance.getPropertyValue('Some Property')

Property Patterns

Conditional Properties
const showIcon = instance.getBoolean('Has Icon')
const icon = showIcon ? instance.findInstance('Icon') : null

export default {
  example: figma.code`
    <Button ${icon ? figma.code`icon={${icon.executeTemplate().example}}` : ''}>
      Click me
    </Button>
  `
}
Combining Properties
const variant = instance.getEnum('Variant', { Primary: 'primary', Secondary: 'secondary' })
const size = instance.getEnum('Size', { Small: 'sm', Large: 'lg' })
const disabled = instance.getBoolean('Disabled')

export default {
  example: figma.code`
    <Button
      variant="${variant}"
      size="${size}"
      ${disabled ? 'disabled' : ''}
    />
  `
}

Working with Nested Components

Finding Child Layers

findInstance(layerName: string, opts?: SelectorOptions): InstanceHandle | ErrorHandle

Finds a child component instance by layer name.

const icon = instance.findInstance('Icon')
const avatar = instance.findInstance('Avatar')

With selector options:

// Find by exact path
const icon = instance.findInstance('Icon', {
  path: ['Header', 'IconSlot']
})

// Search through nested instances
const deepIcon = instance.findInstance('Icon', {
  traverseInstances: true
})
findText(layerName: string, opts?: SelectorOptions): TextHandle | ErrorHandle

Finds a text layer by name.

const heading = instance.findText('Heading')
const body = instance.findText('Body Text')

// Access text content
const headingText = heading.textContent
findConnectedInstance(codeConnectId: string, opts?: SelectorOptions): InstanceHandle | ErrorHandle

Finds a child by its Code Connect ID.

Note: Returns ErrorHandle (not null) when no match is found. Check result.type === 'INSTANCE' before calling hasCodeConnect().

// Find component with specific Code Connect ID
const button = instance.findConnectedInstance('primary-button')
findConnectedInstances(selector: (node: InstanceHandle) => boolean, opts?: SelectorOptions): InstanceHandle[]

Finds all child instances matching a selector function.

// Find all buttons
const buttons = instance.findConnectedInstances(node => {
  return node.codeConnectId() === 'button'
})

// Find all instances with certain property
const primaryButtons = instance.findConnectedInstances(node => {
  return node.getPropertyValue('Variant') === 'Primary'
})
findLayers(selector: (node: InstanceHandle | TextHandle) => boolean, opts?: SelectorOptions): (InstanceHandle | TextHandle)[]

Finds all layers (instances and text) matching a selector.

// Find all layers with specific names
const layers = instance.findLayers(node => {
  return node.name === 'Icon' || node.name === 'Label'
})

Executing Nested Templates

executeTemplate(): { example: ResultSection[], metadata: Metadata }

Renders a nested instance and returns its code and metadata.

const icon = instance.findInstance('Icon')

if (icon && icon.type === 'INSTANCE' && icon.hasCodeConnect()) {
  const result = icon.executeTemplate()
  const iconCode = result.example
  const iconProps = result.metadata.props
}

Instance Information

hasCodeConnect(): boolean

Checks if an instance has Code Connect configured.

const icon = instance.findInstance('Icon')

if (icon && icon.type === 'INSTANCE' && icon.hasCodeConnect()) {
  const iconCode = icon.executeTemplate().example
} else {
  // Fallback when no Code Connect
  const iconCode = figma.code`<Icon />`
}
codeConnectId(): string | null

Returns the Code Connect ID of the instance.

const id = instance.codeConnectId()
// Returns the 'id' from the template's export

Nested Component Patterns

Simple Nested Component
const figma = require('figma')
const instance = figma.selectedInstance

const label = instance.getString('Label')
const icon = instance.findInstance('Icon')

export default {
  example: figma.code`
    <Button
      label="${label}"
      ${icon ? figma.code`icon={${icon.executeTemplate().example}}` : ''}
    />
  `,
  id: 'button-with-icon'
}
Multiple Nested Components
const buttons = instance.findConnectedInstances(node => {
  return node.codeConnectId() === 'button'
})

const buttonElements = buttons.map(btn => btn.executeTemplate().example)

export default {
  example: figma.code`
    <ButtonGroup>
      ${buttonElements.join('\n')}
    </ButtonGroup>
  `
}
Nested with Metadata
// Child component
export default {
  example: figma.code`<Icon name="${name}" />`,
  id: 'icon',
  metadata: {
    nestable: true,
    props: { iconName: name }
  }
}

// Parent component
const icon = instance.findConnectedInstance('icon')
if (icon) {
  const result = icon.executeTemplate()
  const iconName = result.metadata.props.iconName
  // Use iconName in parent logic
}
Children Pattern
const children = figma.properties.children(['Card', 'Button'])

export default {
  example: figma.code`
    <Container>
      ${children.map(child => child.executeTemplate().example).join('\n')}
    </Container>
  `,
  id: 'container'
}

Publishing and Management

Installation

npm install --global @figma/code-connect@latest

Publishing Code Connect Files

Publish all templates to make them visible in Figma Dev Mode:

npx figma connect publish --token=YOUR_ACCESS_TOKEN

Using environment variable:

export FIGMA_ACCESS_TOKEN=your_token_here
npx figma connect publish

With custom config:

npx figma connect publish --config path/to/figma.config.json

Unpublishing

Unpublish all files in config:

npx figma connect unpublish

Unpublish specific component:

npx figma connect unpublish --node=https://figma.com/file/abc/File?node-id=123-456 --label=React

Migration from Old Format

Convert existing Code Connect files to template format:

npx figma connect migrate --outDir ./templates

Test migrations:

  1. Set temporary label in figma.config.json
  2. Publish to test: npx figma connect publish
  3. Verify in Figma
  4. Unpublish when done: npx figma connect unpublish

CLI Help

npx figma connect --help
npx figma connect publish --help
npx figma connect unpublish --help

Type Reference

SelectorOptions

interface SelectorOptions {
  /** Full path of parent layer names to match */
  path?: string[]

  /** Whether to search inside nested component instances */
  traverseInstances?: boolean
}

Example:

// Find icon only in specific hierarchy
const icon = instance.findInstance('Icon', {
  path: ['Header', 'Actions', 'IconSlot']
})

// Search everywhere including nested instances
const anyIcon = instance.findInstance('Icon', {
  traverseInstances: true
})

Metadata

interface Metadata {
  /**
   * Controls display in Code Connect panel:
   * - true: Shows code inline with parent
   * - false: Shows as expandable pill
   */
  nestable?: boolean

  /** Custom data accessible to parent templates */
  props?: Record<string, any>
}

Important: nestable must be set in two places for nested templates to work correctly:

  1. templateDataJson when calling add_code_connect_map — e.g. '{"isParserless": true, "nestable": true}'. This controls whether the child template is loaded into the parent's evaluation context. If missing, the parent cannot find or execute the child via findConnectedInstance, findConnectedInstances, or hasCodeConnect().
  2. metadata.nestable in the template's export default — controls the runtime rendering behavior (inline code vs. clickable pill).

ResultSection Types

type CodeSection = {
  type: "CODE"
  code: string
}

type InstanceSection = {
  type: "INSTANCE"
  guid: string      // Instance layer ID
  symbolId: string  // Component ID
}

type ErrorSection = {
  type: "ERROR"
  message: string
  errorObject?: ResultError
}

type ResultSection = CodeSection | InstanceSection | ErrorSection

Template Result

type SectionsResult = {
  result: "SUCCESS"
  data: {
    type: "SECTIONS"
    sections: ResultSection[]
    language: string
    metadata?: {
      __props: Record<string, any>
      [key: string]: any
    }
  }
}

Error Types

type PropertyNotFoundError = {
  type: "PROPERTY_NOT_FOUND"
  propertyName: string
}

type ChildLayerNotFoundError = {
  type: "CHILD_LAYER_NOT_FOUND"
  layerName: string
}

type PropertyTypeMismatchError = {
  type: "PROPERTY_TYPE_MISMATCH"
  propertyName: string
  expectedType: string
}

type TemplateExecutionError = {
  type: "TEMPLATE_EXECUTION_ERROR"
}

type ResultError =
  | PropertyNotFoundError
  | PropertyTypeMismatchError
  | ChildLayerNotFoundError
  | TemplateExecutionError

Complete Examples

Button with States

// url=https://www.figma.com/file/abc/Components?node-id=1-2
// source=src/components/Button.tsx
// component=Button

const figma = require('figma')
const instance = figma.selectedInstance

const label = instance.getString('Label')
const variant = instance.getEnum('Variant', {
  Primary: 'primary',
  Secondary: 'secondary',
  Tertiary: 'tertiary'
})
const size = instance.getEnum('Size', {
  Small: 'sm',
  Medium: 'md',
  Large: 'lg'
})
const disabled = instance.getBoolean('Has Disabled State')
const hasIcon = instance.getBoolean('Has Icon')
const icon = hasIcon ? instance.getInstanceSwap('Icon') : null

export default {
  example: figma.tsx`
    <Button
      variant="${variant}"
      size="${size}"
      ${disabled ? 'disabled' : ''}
      ${icon ? figma.tsx`icon={${icon.executeTemplate().example}}` : ''}
    >
      ${label}
    </Button>
  `,
  imports: ['import { Button } from "@/components/Button"'],
  id: 'button',
  metadata: {
    nestable: true
  }
}

Card with Children

// url=https://www.figma.com/file/abc/Components?node-id=10-20
// source=src/components/Card.tsx
// component=Card

const figma = require('figma')
const instance = figma.selectedInstance

const heading = instance.findText('Heading')
const body = instance.findText('Body')
const actions = figma.properties.children(['Button'])
const variant = instance.getEnum('Variant', {
  Elevated: 'elevated',
  Outlined: 'outlined',
  Filled: 'filled'
})

export default {
  example: figma.tsx`
    <Card variant="${variant}">
      <Card.Header>
        ${heading.textContent}
      </Card.Header>
      <Card.Body>
        ${body.textContent}
      </Card.Body>
      <Card.Actions>
        ${actions.map(action => action.executeTemplate().example).join('\n')}
      </Card.Actions>
    </Card>
  `,
  imports: ['import { Card } from "@/components/Card"'],
  id: 'card',
  metadata: {
    nestable: false
  }
}

Form Field with Validation

// url=https://www.figma.com/file/abc/Components?node-id=30-40
// source=src/components/TextField.tsx
// component=TextField

const figma = require('figma')
const instance = figma.selectedInstance

const label = instance.getString('Label')
const placeholder = instance.getString('Placeholder')
const helperText = instance.findText('Helper Text')
const errorState = instance.getEnum('State', {
  Default: false,
  Error: true
})
const required = instance.getBoolean('Required')
const disabled = instance.getBoolean('Disabled')

export default {
  example: figma.tsx`
    <TextField
      label="${label}"
      placeholder="${placeholder}"
      ${helperText ? `helperText="${helperText.textContent}"` : ''}
      ${errorState ? 'error' : ''}
      ${required ? 'required' : ''}
      ${disabled ? 'disabled' : ''}
    />
  `,
  imports: ['import { TextField } from "@/components/TextField"'],
  id: 'text-field'
}

Navigation with Dynamic Items

// url=https://www.figma.com/file/abc/Components?node-id=50-60
// source=src/components/Navigation.tsx
// component=Navigation

const figma = require('figma')
const instance = figma.selectedInstance

const items = instance.findConnectedInstances(node => {
  return node.codeConnectId() === 'nav-item'
})

const direction = instance.getEnum('Direction', {
  Horizontal: 'horizontal',
  Vertical: 'vertical'
})

export default {
  example: figma.tsx`
    <Navigation direction="${direction}">
      ${items.map(item => item.executeTemplate().example).join('\n')}
    </Navigation>
  `,
  imports: ['import { Navigation } from "@/components/Navigation"'],
  id: 'navigation',
  metadata: {
    nestable: false
  }
}

Best Practices

1. Use Descriptive IDs

// Good - clear and descriptive
export default {
  id: 'primary-button',
  // ...
}

// Avoid - too generic
export default {
  id: 'btn',
  // ...
}

2. Handle Missing Properties Gracefully

// Good - check type before calling hasCodeConnect
const icon = instance.findInstance('Icon')
const iconCode = icon && icon.type === 'INSTANCE' && icon.hasCodeConnect()
  ? icon.executeTemplate().example
  : null

// Avoid - assumes icon exists
const iconCode = instance.findInstance('Icon').executeTemplate().example

3. Use Appropriate Tagged Templates

// Good - use specific template for language
const example = figma.tsx`<Button />`

// Avoid - generic when specific is available
const example = figma.code`<Button />`

4. Keep Templates Focused

// Good - one component per file
export default {
  example: figma.tsx`<Button {...props} />`,
  id: 'button'
}

// Avoid - multiple components in one template
export default {
  example: figma.tsx`
    <Button />
    <Input />
    <Select />
  `
}

5. Use Metadata Appropriately

// Good - small inline components
export default {
  id: 'icon',
  metadata: { nestable: true }
}
// Also set in templateDataJson when registering: {"isParserless": true, "nestable": true}

// Good - complex components as pills
export default {
  id: 'modal',
  metadata: { nestable: false }
}

Note: If using add_code_connect_map, nestable must also be set in templateDataJson for the child to be discoverable by parent templates. Setting metadata: { nestable: true } in the template alone is not sufficient — the stored templateData.nestable controls whether the child is loaded into instanceTemplates.


Troubleshooting

Property Not Found

Error: Property "Label" not found

Solution: Check property name in Figma matches exactly (case-sensitive):

// Property name in Figma: "Button Label"
const label = instance.getString('Button Label')

Layer Not Found

Error: Child layer "Icon" not found

Solution: Verify layer name and try with path:

const icon = instance.findInstance('Icon', {
  path: ['Content', 'IconSlot'],
  traverseInstances: true
})

Type Mismatch

Error: Property type mismatch

Solution: Use correct method for property type:

  • Text properties → getString()
  • Boolean properties → getBoolean()
  • Variant properties → getEnum()
  • Instance swap → getInstanceSwap()

Template Not Rendering

Issue: Template doesn't appear in Figma

Solution:

  1. Ensure URL comment matches component exactly
  2. Check figma.config.json includes the file pattern
  3. Verify file was published: npx figma connect publish
  4. Check Figma file permissions

Invalid Code Sections

Issue: Code appears broken in Figma

Solution: Never concatenate template results:

// Wrong
const result = snippet1 + snippet2

// Correct
const result = figma.code`${snippet1}${snippet2}`

Source: SKILL.md on GitHub

No alerts16d4 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill is a specialized tool for creating Figma Code Connect templates. It leverages official Figma MCP tools and the @figma/code-connect library to map design components to code. No security issues were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at ef474d1. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 20 hours ago.

Activeupdated 2 months ago
disable-model-invocation
false
  • TypeScript
  • figma
  • code-connect
  • design-to-code
  • component-mapping
  • figma-mcp
  • templates

README badge

README badge for figma/mcp-server-guide/figma-code-connect

Creates and maintains Figma Code Connect template files (`.figma.ts`) that map published Figma components to code snippets using the Figma MCP server. Extracts component properties from Figma and generates templates that handle variants, text, boolean toggles, instance swaps, and content slots.

Generated from the current SKILL.md.

What is the difference between Code Connect template files (.figma.ts) and parser-based files (.figma.tsx)?
This skill covers template files only—.figma.ts files that use MCP tools to fetch component context from Figma at runtime. Parser-based .figma.tsx files use figma.connect() and are published via CLI; they are not covered by this skill.
Does this skill require the Figma MCP server to be connected?
Yes. The Figma MCP server must be connected and tools like get_code_connect_suggestions must be available. If not available, the user must enable the Figma MCP server and restart their MCP client.
What plan level do I need to use Code Connect?
Code Connect requires an Organization or Enterprise Figma plan. It is not available on Free or Professional plans.
Do components need to be published before creating Code Connect mappings?
Yes. Components must be published to a Figma team library. Unpublished components cannot be mapped with Code Connect.
What TypeScript setup is required for .figma.ts files?
Add @figma/code-connect/figma-types to the types array in tsconfig.json compilerOptions for editor autocomplete and type checking.

Generated from the current SKILL.md. These answers refresh after source changes.