Export Variables & Styles
Complete guide to exporting tokens to Figma Variables and Styles: config.json setup, collections, modes, references, diff-id, and export flags.
What is Export
Export is the process of turning your JSON tokens into native Figma objects: Variables and Styles. After export, tokens become first-class elements of the Figma design system that can be bound to properties, published in libraries, and used across files.
What gets created
| JSON token | Figma object |
|---|---|
color | Variable (COLOR) |
dimension, spacing, sizing, borderRadius, borderWidth, opacity, number, fontSize, lineHeight, letterSpacing, paragraphSpacing, paragraphIndent, duration | Variable (FLOAT) |
fontFamily, fontWeight, fontStyle, text, cubicBezier, strokeStyle, textCase, textDecoration | Variable (STRING) |
boolean | Variable (BOOLEAN) |
typography | Text Style |
shadow, effects, blur, backdrop-blur, glass | Effect Style |
fill, gradient | Paint Style |
grid | Grid Style |
Composition and transition tokens are skipped during variable/style export — they are handled by a separate component generation mechanism.
The config.json file
config.json is the central configuration file that controls export. It defines:
- Which collections are created in Figma
- Which modes each collection has
- Which token files belong to each mode
- How collections reference each other
Full structure
{
"$schema": "sxl-studio/config",
"$version": "1.0",
"settings": {
"remBase": 16,
"autoExportOnPull": false
},
"collections": [
{
"name": "Primitives",
"enabled": true,
"hiddenFromPublishing": false,
"ref": [],
"modes": [
{
"name": "Default",
"enabled": true,
"ref": [],
"files": {
"colors.json": "enabled",
"spacing.json": "enabled",
"typography.json": "enabled"
}
}
]
}
],
"compositions": {
"outputMode": "component-set",
"files": {
"button.json": "enabled"
}
}
}
Field descriptions
Root fields
| Field | Type | Description |
|---|---|---|
$schema | "sxl-studio/config" | Schema identifier (set automatically) |
$version | string | Configuration version (defaults to "1.0") |
settings | object | Global settings |
collections | array | Array of variable collections |
compositions | object | Composition token settings (optional) |
settings
| Field | Type | Default | Description |
|---|---|---|---|
remBase | number | 16 | Base value for rem → px calculations. Must be > 0, otherwise defaults to 16 |
autoExportOnPull | boolean | false | Automatically export tokens after Git Pull |
collections[]
| Field | Type | Description |
|---|---|---|
name | string | Collection name in Figma (must be unique) |
enabled | boolean | Whether the collection is included in export |
hiddenFromPublishing | boolean | Hide the collection from library publishing |
ref | RefRule[] | References to other collections for alias resolution |
modes | ConfigMode[] | Array of collection modes |
modes[]
| Field | Type | Description |
|---|---|---|
name | string | Mode name in Figma |
enabled | boolean | Whether the mode is included in export |
ref | RefRule[] | References to other collections for this mode |
files | object | File map: { "file.json": "enabled" | "disabled" } |
compositions
| Field | Type | Default | Description |
|---|---|---|---|
outputMode | "component-set" | "separate" | "component-set" | Output format: as Component Set or separate components |
files | object | — | Composition file map |
Collections and modes
What is a collection
A Collection in Figma is a named group of variables. A typical design system has several collections:
{
"collections": [
{
"name": "Primitives",
"modes": [
{
"name": "Default",
"files": { "colors.json": "enabled", "spacing.json": "enabled" }
}
]
},
{
"name": "Semantic",
"modes": [
{
"name": "Light",
"files": { "semantic-light.json": "enabled" }
},
{
"name": "Dark",
"files": { "semantic-dark.json": "enabled" }
}
]
},
{
"name": "Component",
"modes": [
{
"name": "Default",
"files": { "components.json": "enabled" }
}
]
}
]
}
What is a mode
A mode is a collection variation. Classic examples: Light / Dark, Small / Medium / Large, LTR / RTL. Each mode has its own set of token files — the same token paths with different values.
Example: semantic-light.json and semantic-dark.json contain the same paths (text.primary, bg.surface) but with different colors.
Collection order
The order of collections in the collections array determines their order in Figma. If the order or set of collections in the config doesn't match the current state in Figma, the plugin will recreate collections to align them (except when adoptExisting is enabled).
Note: when collections are recreated, existing variable bindings to layers are preserved through the diff-id mechanism (variables are recreated with the same keys).
Enabling and disabling
Set "enabled": false for a collection or mode to exclude it from export. Same for files — "disabled" skips the file:
{
"name": "Experiments",
"enabled": false,
"modes": [
{
"name": "Default",
"files": {
"experimental-tokens.json": "disabled",
"stable-tokens.json": "enabled"
}
}
]
}
Hiding from publishing
hiddenFromPublishing: true creates the collection but hides it from other files when using the library. Useful for internal primitives that end users of the design system should not access.
{
"name": "Primitives",
"hiddenFromPublishing": true,
"modes": [...]
}
Cross-collection references (ref)
When one token references a token from another collection, you need to tell the plugin where to find the alias target. This is done through ref rules.
Local references
Reference to another collection in the same file:
{
"name": "Semantic",
"ref": [
{ "type": "local", "collection": "Primitives" }
],
"modes": [
{
"name": "Light",
"files": { "semantic-light.json": "enabled" }
}
]
}
If semantic-light.json contains {color.blue.500} and that token is defined in the Primitives collection, the plugin will find it thanks to ref.
Library references
Reference to a variable from a connected Figma library:
{
"ref": [
{
"type": "library",
"library": "Design System Core",
"collection": "Primitives"
}
]
}
| Field | Type | Description |
|---|---|---|
type | "local" | "library" | Reference type |
collection | string | Collection name (required) |
library | string | Figma library name (only for "library") |
mode | string | Mode name (optional) |
Reference levels
- Collection level (
collections[].ref) — applies to all modes in the collection - Mode level (
modes[].ref) — applies only to that specific mode
When resolving an alias, the plugin checks references in order: mode → collection → all local collections → libraries.
Alias resolution order
When the plugin encounters a reference {path.to.token}, it searches for the target variable in this order:
- Tokens in the current collection / current mode
- Explicit
localrefs (other collections in the config) - All other local collections in the file
- Memory from other diff-id files (by
figmaKey) - Explicit
libraryrefs (by library name and collection) - All library indexes by collection name
- All library variables by name
- Import cache
Export process
Stages
Export runs through several stages:
- Parse config.json — validate structure, check names, detect duplicates
- Collect tokens — read files from each mode, parse DTCG JSON
- Load diff-id — restore the mapping from the previous export
- Index libraries — scan local variables and connected libraries
- Export variables — loop through collections and modes: create, update, delete
- Export styles — create / update Text, Effect, Paint, Grid styles
- Save diff-id — write the mapping to plugin storage
- Cleanup — remove orphans (if
deleteOrphansis enabled)
What are "orphans"
Orphans are variables and styles in Figma that were created by a previous export but no longer exist in the JSON files. When deleteOrphans is enabled, the plugin:
- Deletes variables whose paths no longer exist in the config
- Deletes modes that are not in the config
- Deletes collections that are not in the config
- Deletes styles whose paths no longer match
diff-id files
What they are
diff-id is a JSON file that stores the correspondence map between JSON tokens and Figma objects. It allows the plugin to:
- Determine which tokens were changed, added, or deleted
- Update existing variables without duplication
- Track collections, modes, variables, and styles
File naming
The file is created automatically on first export:
diff-id.<file-key>.json— if the Figma file key is availablediff-id.<document-name-slug>.json— otherwise
diff-id structure
{
"version": 2,
"$figmaFileName": "Design System",
"$figmaFileKey": "abc123def456",
"collections": {
"Primitives": {
"figmaId": "VariableCollectionId:123:456",
"modes": {
"Default": "123:789"
}
}
},
"variables": {
"color.primary": {
"figmaId": "VariableID:123:100",
"figmaKey": "abc123...",
"hash": "a1b2c3d4...",
"collectionPath": "Primitives"
}
},
"styles": {
"typography.heading.xl": {
"figmaId": "S:abc123...",
"hash": "e5f6g7h8...",
"type": "text"
}
}
}
How hashing works
A hash is computed for each token that includes:
- Value (
$value) - Scopes (
figma.scopes) - Code Syntax (
figma.codeSyntax) - Hide (
figma.hide) - Modify (
figma.modify)
On subsequent exports, the plugin compares hashes — if unchanged, the variable is skipped. This significantly speeds up repeat exports.
Storage
diff-id is stored in the document's Plugin Data in Figma. The file is saved to disk when using Git integration. During tree-based serialization, variables and styles are nested in JSON by path segments (for compactness), then flattened back when read.
Tip: if export behaves incorrectly (duplicated variables, values not updating), try resetting diff-id through the plugin menu. This forces the plugin to rescan all tokens.
Export flags
The following settings are available during export:
Variable types
Filter by the type of variables to create:
| Flag | Figma type | Default |
|---|---|---|
color | COLOR | ✅ Enabled |
number | FLOAT | ✅ Enabled |
string | STRING | ✅ Enabled |
boolean | BOOLEAN | ✅ Enabled |
Disable a type to skip all variables of that type during export.
Style types
Filter by the type of styles to create:
| Flag | Style type | Default |
|---|---|---|
typography | Text Style | ✅ Enabled |
shadow | Effect Style | ✅ Enabled |
blur | Effect Style | ✅ Enabled |
effects | Effect Style | ✅ Enabled |
glass | Effect Style | ✅ Enabled |
fill | Paint Style | ✅ Enabled |
gradient | Paint Style | ✅ Enabled |
grid | Grid Style | ✅ Enabled |
border | Paint Style | ⬜ Disabled |
Behavior flags
| Flag | Default | Description |
|---|---|---|
| Apply Code Syntax & Scopes | ✅ | Write figma.scopes, figma.codeSyntax, and figma.hide to variables. Also adds Code Syntax to style descriptions. When enabled, all tokens are additionally checked for metadata changes |
| Force Update All | ⬜ | Ignore diff hash and update all variables and styles (useful when synchronization is suspected to be broken) |
| Delete Orphans | ⬜ | Delete variables, styles, modes, and collections that no longer exist in the config. Irreversible operation — make sure your config is up to date |
| Adopt Existing | ⬜ | When creating new variables, try to bind existing variables by name instead of creating duplicates. Disables collection recreation when order doesn't match |
| Selected Collections | All | Export only selected collections. Empty list = all collections |
Tip for Delete Orphans: use with caution. If you renamed a collection or mode in the config, the plugin will treat the old name as an "orphan" and delete it. It's better to export first without this flag, verify everything is correct, then run with
Delete Orphans.
Figma Styles
How styles are created
Styles are created from composite tokens. For multi-modal collections, style values are taken from the first enabled mode.
| Token type | Figma style type |
|---|---|
typography | Text Style |
shadow | Effect Style |
effects | Effect Style |
blur | Effect Style |
backdrop-blur | Effect Style |
glass | Effect Style |
fill | Paint Style |
gradient | Paint Style |
grid | Grid Style |
Style naming
The token path is converted to a style name by replacing dots with slashes:
- Token
typography.heading.xl→ Styletypography/heading/xl - Token
shadow.card.md→ Styleshadow/card/md
Code Syntax in styles
When the Apply Code Syntax & Scopes flag is enabled, figma.codeSyntax values are added to the style description as a text block. This lets developers see the correct syntax directly in the style's properties.
Destructive actions: deleting collections and style groups
The Destructive actions panel inside the Export window is split into two sub-blocks — Collections and Styles. Both support:
- Search by name (collection or style group).
- Multi-select by clicking individual rows. By default, all items are
selected, so the button reads
Delete all variable collections/Delete all styles. As soon as you uncheck anything, the button switches toDelete N selected collection(s)/Delete N selected group(s). - The two global buttons stay available — keeping every row selected is
equivalent to the old
Delete All …behaviour.
Collections
- Lists every local variable collection in the current Figma file with its variable count and number of modes.
- Delete everything at once, or any subset.
- On delete:
- Collections are removed from Figma (variables bound to layers lose their bindings).
- Only matching entries are removed from
diff-id.<fileKey>.json(collections[name],variableswithcollectionPath = name, and any linkedcompositions). - If the resulting
diff-idis empty, the file is marked for deletion on Git (the push indicator will show it as a removed file).
Styles
- Lists style groups, grouped by the first segment of the style name. For
example,
w-mylib/typography/body,w-mylib/fill/brandandlegacy/shadow/cardcollapse into groupsw-mylibandlegacy. - Each row shows a breakdown by style kind (
paint / text / effect / grid) and the total count. - Delete all groups at once, or any subset.
- On delete:
- All local styles whose name starts with the selected prefix (followed by
/, or matching exactly) are removed from Figma. diff-id.styles[path]entries whose first segment matches one of the deleted groups are purged.- If
diff-idbecomes empty after purging, the file is marked for Git deletion, same as the Collections block.
- All local styles whose name starts with the selected prefix (followed by
Bug fix
Previously Delete All Collections / Delete All Styles only cleared
diff-id in the plugin's memory. The diff-id.<fileKey>.json file stayed on
the Git remote, and the plugin's internal caches kept references to deleted
variables. As a result, binding new tokens to layers after a deletion could
resurrect variables that had already been removed. The current release:
- Always updates
diff-idcorrectly (partial or full clear). - On full clear, flags
diff-id.<fileKey>.jsonfor deletion so it disappears from the Git remote on the next push. - Invalidates every resolver cache immediately after deletion — no more "ghost" variables reappearing.
Warning: all operations inside the Destructive actions panel are irreversible. Before a bulk delete, save a version of the Figma file and commit your current token state to Git.
Full config.json example
A typical configuration for a design system with primitives, semantic tokens, and component tokens:
{
"$schema": "sxl-studio/config",
"$version": "1.0",
"settings": {
"remBase": 16,
"autoExportOnPull": false
},
"collections": [
{
"name": "Primitives",
"enabled": true,
"hiddenFromPublishing": true,
"modes": [
{
"name": "Default",
"enabled": true,
"files": {
"core/colors.json": "enabled",
"core/spacing.json": "enabled",
"core/typography.json": "enabled",
"core/effects.json": "enabled"
}
}
]
},
{
"name": "Semantic",
"enabled": true,
"ref": [
{ "type": "local", "collection": "Primitives" }
],
"modes": [
{
"name": "Light",
"enabled": true,
"files": {
"themes/light.json": "enabled"
}
},
{
"name": "Dark",
"enabled": true,
"files": {
"themes/dark.json": "enabled"
}
}
]
},
{
"name": "Components",
"enabled": true,
"ref": [
{ "type": "local", "collection": "Semantic" },
{ "type": "local", "collection": "Primitives" }
],
"modes": [
{
"name": "Default",
"enabled": true,
"files": {
"components/button.json": "enabled",
"components/input.json": "enabled",
"components/card.json": "enabled"
}
}
]
}
],
"compositions": {
"outputMode": "component-set",
"files": {
"compositions/button.json": "enabled",
"compositions/card.json": "enabled"
}
}
}
In this example:
- Primitives — base values (colors, spacing), hidden from publishing
- Semantic — has two modes (Light / Dark), references Primitives
- Components — component tokens, references both Semantic and Primitives
Auto-export after Git Pull
Set autoExportOnPull: true in settings to make the plugin automatically export tokens after every Git Pull. Export runs with default settings (all types enabled, Delete Orphans disabled).
{
"settings": {
"autoExportOnPull": true
}
}
More about Git integration in Git — Integration.
Tips and common issues
Variables are duplicated
- Check if diff-id was reset. Enable Adopt Existing so the plugin binds existing variables by name.
Values are not updating
- The hash might not have changed. Enable Force Update All to force a full update.
Aliases are not resolving
- Check
refin the config — is the collection containing the target token specified? - Make sure the file with the target token is
"enabled".
Collections keep getting recreated
- The collection order in the config doesn't match the order in Figma. Align the
collectionsarray to the desired order, or enable Adopt Existing.
Related sections
- Tokens Overview — general tab structure
- Scopes & Code Syntax — visibility and code settings
- Tokens to Code — code generation from tokens
- Composition — component generation from JSON
- Git — Integration — sync through Git