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 TypeScript 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
- Make sure your
figma.config.jsonincludes.figma.ts(or.figma.js) files, and setlabelandlanguage(See Configuring your project):
{
"codeConnect": {
"include": ["**/*.figma.ts"],
"label": "React",
"language": "jsx"
}
}
- If using TypeScript, add the template type definitions to your
tsconfig.jsonso your editor can provide autocomplete and type checking in template files:
{
"compilerOptions": {
"types": ["@figma/code-connect/figma-types"]
}
}
-
Write your
.figma.tsfile (see Writing template files) -
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:
// url=https://www.figma.com/file/your-file-id/Component?node-id=123
import figma from '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:
import figma from '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:
import figma from '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: 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:
import figma from '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 infigma.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 itmetadatanestable(optional) - whether your snippet should be displayed inline if nested in a parent. Iffalse, displays as a clickable linkprops(optional) - makes data available to parent templates through executeTemplate().metadata.props
Migration script (beta)
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 --outDir for testing for ease of publishing/unpublishing the new files.
By default the migration script outputs .figma.ts files. If you need JavaScript output instead, pass the --javascript flag:
npx figma connect migrate [options]
Options:
--outDir <dir>— write template files to a specific directory instead of alongside the source files--javascript— output.figma.jsfiles instead of the default.figma.ts--include-props— preserve__propsmetadata blocks in the migrated output. By default these are removed, since they are an implementation detail of parser-based files and are not needed in template files. Pass this flag if using the React.getProps()or.render()modifiers, or if you have other template files that readexecuteTemplate().metadata.__propsfrom the migrated components.
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.ts"],
"label": "TEST",
"language": "jsx"
}
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>