Batch files
Batch files let you connect many Figma components to code using a single shared template. This is the recommended approach when you have a large number of components that follow the same structure, the most common example being icon libraries, where hundreds or thousands of icons share identical code patterns but each maps to a different Figma node.
Without batch files, each component would need its own .figma.ts file. Batch files collapse this into two files: a template (.figma.batch.ts) that describes the code shape, and a JSON file (.figma.batch.json) that lists every component with its Figma URL and any custom data.
File structure
A batch integration consists of two files:
| File | Purpose |
|---|---|
*.figma.batch.ts | Template describing the code snippet |
*.figma.batch.json | List of components with their Figma URLs and custom data |
Writing a batch template
A batch template is structured like a regular template file, with two differences:
- There are no metadata comments (
// url=,// source=,// component=) at the top. Those values are defined in the JSON file instead. - Per-component data is accessed via
figma.batchrather than being hardcoded.
import figma from 'figma'
const instance = figma.selectedInstance
const size = instance.getEnum('Size', {
Small: '16px',
Medium: '24px',
Large: '32px',
})
export default {
example: figma.code`
<${figma.batch.name} size={${size}} />
`,
imports: [`import ${figma.batch.name} from "${figma.batch.importPath}"`],
id: figma.batch.id,
}
figma.batch
figma.batch gives your template access to data defined in the JSON file for each component. Three fields have special meaning, corresponding to the metadata comments used in regular template files:
| Field | Required | Replaces |
|---|---|---|
url | Yes | // url= |
source | No | // source= |
component | No | // component= |
Any additional fields you define in the JSON file, such as name, id, or importPath in the example above, are also available on figma.batch. This lets your template reference per-component values without hardcoding them, for example:
figma.code`<MyComponent ${figma.batch.myCustomField} />`
The full type of figma.batch is:
figma.batch: {
url: string
source?: string
component?: string
[key: string]: any
}
Writing the JSON file
The JSON file defines which components belong to a batch and what data each one provides to the template.
Single template (shorthand)
When all your components share one template, use the shorthand format with a templateFile and a components array:
{
"templateFile": "./icons.figma.batch.ts",
"components": [
{
"url": "https://www.figma.com/design/ABC/File?node-id=1-1",
"name": "Icon24Arrow",
"id": "icon-arrow",
"importPath": "@company/icons/arrow",
"source": "./src/icons/Icon24Arrow.tsx"
},
{
"url": "https://www.figma.com/design/ABC/File?node-id=1-2",
"name": "Icon24Check",
"id": "icon-check",
"importPath": "@company/icons/check",
"source": "./src/icons/Icon24Check.tsx"
}
]
}
Each entry in components must include a url. All other fields are passed to the template as properties on the batch object.
Multiple templates
If your batch file covers components that use different templates, use an array at the top level:
[
{
"templateFile": "./icons.figma.batch.ts",
"components": [
{
"url": "https://www.figma.com/design/ABC/File?node-id=1-1",
"name": "Icon24Arrow",
"id": "icon-arrow",
"importPath": "@company/icons/arrow"
}
]
},
{
"templateFile": "./buttons.figma.batch.ts",
"components": [
{
"url": "https://www.figma.com/design/ABC/File?node-id=2-1",
"name": "PrimaryButton",
"id": "button-primary",
"importPath": "@company/buttons/primary"
}
]
}
]
Setup
Discovery
The CLI discovers batch files through the same include/exclude mechanism as all other Code Connect files. The default include globs already include **/*.figma.batch.json, so batch files work out of the box for projects that don't have a custom include in their figma.config.json.
If your project defines a custom include list, add the batch glob explicitly:
{
"codeConnect": {
"include": ["**/*.figma.ts", "**/*.figma.batch.json"],
"label": "React",
"language": "jsx"
}
}
The template files (.figma.batch.ts) referenced by templateFile do not need to appear in include. They are read on demand when the CLI processes the JSON file.
Publishing
Once your files are in place, publish the same way as any other Code Connect file:
npx figma connect publish
Each entry in your components array is published as an independent Code Connect doc. Unpublishing also works automatically: each component is removed individually by its Figma node URL.
Complete example
Here is a full example connecting a library of icons, where each icon supports a Size variant and is imported from a package path unique to that icon.
import figma from 'figma'
const instance = figma.selectedInstance
const size = instance.getEnum('Size', {
Small: '16px',
Medium: '24px',
Large: '32px',
})
const iconSnippet = figma.code`
<${figma.batch.name} size={${size}} />
`
const importsList = figma.batch.withOutline
? figma.batch.name
: [figma.batch.name, 'IconOutline'].join(', ')
export default {
example: figma.batch.withOutline
? figma.code`
<IconOutline>${iconSnippet}</IconOutline>
`
: iconSnippet,
imports: [`import { ${importsList} } from "${figma.batch.importPath}"`],
id: figma.batch.id,
metadata: {
nestable: true,
},
}
{
"templateFile": "./icons.figma.batch.ts",
"components": [
{
"url": "https://www.figma.com/design/XYZ/Icons?node-id=10-1",
"name": "ArrowIcon",
"id": "icon-arrow",
"withOutline": false,
"importPath": "@acme/icons",
"source": "./src/icons/ArrowIcon.tsx"
},
{
"url": "https://www.figma.com/design/XYZ/Icons?node-id=10-2",
"name": "CheckIcon",
"id": "icon-check",
"withOutline": true,
"importPath": "@acme/icons",
"source": "./src/icons/CheckIcon.tsx"
},
{
"url": "https://www.figma.com/design/XYZ/Icons?node-id=10-3",
"name": "CloseIcon",
"id": "icon-close",
"withOutline": true,
"importPath": "@acme/icons",
"source": "./src/icons/CloseIcon.tsx"
}
]
}
See the Template API reference for the full API available inside your batch template.