Skip to main content

Connecting code with template files

Template files provide a framework-agnostic way to connect your code to Figma components. Instead of relying on framework-specific parsers, you write JavaScript files that explicitly define how your components should be displayed. This approach is simpler to maintain, more flexible, and more powerful than framework-specific APIs.

Template files give you full control over code generation, making them ideal when you need:

  • Framework-agnostic connections: Connect any codebase, regardless of framework or language
  • Precise code control: Generate exactly the code you want, without relying on parser APIs

We're actively investing in template files as the primary Code Connect format. If you're starting a new Code Connect integration or want to be involved in shaping its future, we encourage you to try it out and share feedback.

Setup

  1. Make sure your figma.config.json includes .figma.js files, and set label and language. Note, the .figma.template.js extension is also supported for backwards compatibility, but .figma.js is now the recommended extension (See Configuring your project):
{
"codeConnect": {
"include": ["**/*.figma.js"],
"label": "React",
"language": "jsx"
}
}
  1. Write your .figma.js file (see Writing template files)

  2. Publish your template files to Figma when ready:

npx figma connect publish

Writing template files

Template files connect your code to a component in Figma, and specify how instances of that component should appear in the code snippet. Here's an example file:

MyComponent.figma.js
// url=https://www.figma.com/file/your-file-id/Component?node-id=123
const figma = require('figma')
const instance = figma.selectedInstance

const labelText = instance.getString('Label')
const iconInstance = instance.findInstance('Icon')

export default {
example: figma.code`
<MyComponent
label={${labelText}}
icon={${iconInstance.executeTemplate().example}}
/>
`,
imports: ['import MyComponent from "components/MyComponent"'],
id: 'my-component',
metadata: {
nestable: true,
},
}

Metadata comments

Each template file must start with a block of special comments in the below format:

  • url - The Figma component your template is published to. In Figma, right-click on your component and select "Copy link to selection" or copy the URL from the browser.
  • source (optional) - The filepath (or URL) of your code component. Is displayed in Figma.
  • component (optional) - The name of your code component. Is displayed in Figma.
// url=https://www.figma.com/file/your-file-id/Component?node-id=123
// source=src/components/MyButton.tsx
// component=MyButton

Building the snippet

The example snippet is the main part of the template file, describing how your code snippet should appear according to the Figma component instance.

Accessing instance properties

Use the methods on figma.selectedInstance to read properties from your Figma component:

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

// Get the value of the Figma instance "Label" string property
const label = instance.getString('Label')

// Get the value of the Figma instance "Disabled" boolean property
const disabled = instance.getBoolean('Disabled')

// Map the possible values of the "Size" enum property to code values
// (e.g. if the Figma "Size" property is "Small", map to 'sm' in code)
const size = instance.getEnum('Size', {
Small: 'sm',
Medium: 'md',
Large: 'lg',
})

Working with nested instances

To include nested component instances (like an icon inside a button), use findInstance() or getInstanceSwap() to locate the child, then call executeTemplate() to render it:

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

// Find a nested instance by layer name
const iconInstance = instance.findInstance('Icon')

// Get the snippet from the nested instance
const iconSnippet = iconInstance.executeTemplate().example
important

Important: While snippets are written in a string-like syntax, they use an array structure under the hood to ensure pills or errors can be rendered correctly.

It's important when you're building the snippet to not perform string operations (like concatenation) on them. Instead, wrap them in figma.code:

figma.code`<MyExample/>${showIcon ? iconSnippet : null}`

Rendering your snippet

Finally, build your example by writing your code wrapped in figma.code:

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

const example = figma.code`Button(
variant = ButtonVariant.Primary
)`

For the complete API including all available methods, helpers, and advanced features, see the Template V2 API Reference.

Export format

Your template file should contain a default export in this format:

export default {
example: ResultSection[],
imports: string[]
id: string,
metadata?: {
nestable?: boolean,
props?: Record<string, any>,
}
}
  • example - Your constructed snippet. Importantly, this should be wrapped in figma.code`<MyExample/>`
  • imports - An array of strings that will be rendered at the top of your snippet. If the snippet is nested, the imports will be hoisted to the top and deduplicated.
  • id - This identifies this Code Connect template, allowing other templates to reference it
  • metadata
    • nestable (optional) - whether your snippet should be displayed inline if nested in a parent. If false, displays as a clickable link
    • props (optional) - makes data available to parent templates through executeTemplate().metadata.props

Migration script (beta)

info

The migration script is under active development. If you have any feedback or issues with the script, please let us know by creating a GitHub issue.

The Code Connect command line tool offers a script to locally create template files from your existing Code Connect files. As this creates new files, we recommend committing any uncommitted changes in your codebase first. We also recommend using the --outDir for testing for ease of publishing/unpublishing the new files.

npx figma connect migrate --outDir <dest folder>

Migrated files

Migrated template files make use of figma.helpers to ensure correct rendering of code. If you know exactly how your code should appear, it may be simpler to remove some of these. For example, if you're rendering a required prop in React that is always of a known type, then this code:

figma.code`<Counter${figma.helpers.react.renderProp('count', count)} />`

Can be simplified to:

figma.code`<Counter count={${count}} />`

Testing in Figma

For testing out these changes in Figma, you will need to set up your figma.config.json. We recommend setting label to a temporary value so you can easily publish / unpublish without affecting your existing Code Connect, and limiting include to only publish the new files. See Setup for more details on these values.

{
"include": ["**/*.figma.js"],
"label": "TEST",
"language": "jsx" // Swap out with your connected code's language
}

You can then publish under your temporary label to test these out in Figma :

npx figma connect publish --config <your figma.config.json path>

When you're done, you can remove these from Figma with unpublish:

npx figma connect unpublish --config <your figma.config.json path>