Tokens

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 tokenFigma object
colorVariable (COLOR)
dimension, spacing, sizing, borderRadius, borderWidth, opacity, number, fontSize, lineHeight, letterSpacing, paragraphSpacing, paragraphIndent, durationVariable (FLOAT)
fontFamily, fontWeight, fontStyle, text, cubicBezier, strokeStyle, textCase, textDecorationVariable (STRING)
booleanVariable (BOOLEAN)
typographyText Style
shadow, effects, blur, backdrop-blur, glassEffect Style
fill, gradientPaint Style
gridGrid 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

JSON
{
  "$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

FieldTypeDescription
$schema"sxl-studio/config"Schema identifier (set automatically)
$versionstringConfiguration version (defaults to "1.0")
settingsobjectGlobal settings
collectionsarrayArray of variable collections
compositionsobjectComposition token settings (optional)

settings

FieldTypeDefaultDescription
remBasenumber16Base value for rem → px calculations. Must be > 0, otherwise defaults to 16
autoExportOnPullbooleanfalseAutomatically export tokens after Git Pull

collections[]

FieldTypeDescription
namestringCollection name in Figma (must be unique)
enabledbooleanWhether the collection is included in export
hiddenFromPublishingbooleanHide the collection from library publishing
refRefRule[]References to other collections for alias resolution
modesConfigMode[]Array of collection modes

modes[]

FieldTypeDescription
namestringMode name in Figma
enabledbooleanWhether the mode is included in export
refRefRule[]References to other collections for this mode
filesobjectFile map: { "file.json": "enabled" | "disabled" }

compositions

FieldTypeDefaultDescription
outputMode"component-set" | "separate""component-set"Output format: as Component Set or separate components
filesobjectComposition 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:

JSON
{
  "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:

JSON
{
  "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.

JSON
{
  "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:

JSON
{
  "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:

JSON
{
  "ref": [
    {
      "type": "library",
      "library": "Design System Core",
      "collection": "Primitives"
    }
  ]
}
FieldTypeDescription
type"local" | "library"Reference type
collectionstringCollection name (required)
librarystringFigma library name (only for "library")
modestringMode 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:

  1. Tokens in the current collection / current mode
  2. Explicit local refs (other collections in the config)
  3. All other local collections in the file
  4. Memory from other diff-id files (by figmaKey)
  5. Explicit library refs (by library name and collection)
  6. All library indexes by collection name
  7. All library variables by name
  8. Import cache

Export process

Stages

Export runs through several stages:

  1. Parse config.json — validate structure, check names, detect duplicates
  2. Collect tokens — read files from each mode, parse DTCG JSON
  3. Load diff-id — restore the mapping from the previous export
  4. Index libraries — scan local variables and connected libraries
  5. Export variables — loop through collections and modes: create, update, delete
  6. Export styles — create / update Text, Effect, Paint, Grid styles
  7. Save diff-id — write the mapping to plugin storage
  8. Cleanup — remove orphans (if deleteOrphans is enabled)
Full token export cycle in Figma

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 available
  • diff-id.<document-name-slug>.json — otherwise

diff-id structure

JSON
{
  "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:

FlagFigma typeDefault
colorCOLOR✅ Enabled
numberFLOAT✅ Enabled
stringSTRING✅ Enabled
booleanBOOLEAN✅ Enabled

Disable a type to skip all variables of that type during export.

Style types

Filter by the type of styles to create:

FlagStyle typeDefault
typographyText Style✅ Enabled
shadowEffect Style✅ Enabled
blurEffect Style✅ Enabled
effectsEffect Style✅ Enabled
glassEffect Style✅ Enabled
fillPaint Style✅ Enabled
gradientPaint Style✅ Enabled
gridGrid Style✅ Enabled
borderPaint Style⬜ Disabled

Behavior flags

FlagDefaultDescription
Apply Code Syntax & ScopesWrite 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 AllIgnore diff hash and update all variables and styles (useful when synchronization is suspected to be broken)
Delete OrphansDelete variables, styles, modes, and collections that no longer exist in the config. Irreversible operation — make sure your config is up to date
Adopt ExistingWhen creating new variables, try to bind existing variables by name instead of creating duplicates. Disables collection recreation when order doesn't match
Selected CollectionsAllExport only selected collections. Empty list = all collections
Export settings dialog with flags

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 typeFigma style type
typographyText Style
shadowEffect Style
effectsEffect Style
blurEffect Style
backdrop-blurEffect Style
glassEffect Style
fillPaint Style
gradientPaint Style
gridGrid Style

Style naming

The token path is converted to a style name by replacing dots with slashes:

  • Token typography.heading.xl → Style typography/heading/xl
  • Token shadow.card.md → Style shadow/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 to Delete 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], variables with collectionPath = name, and any linked compositions).
    • If the resulting diff-id is 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/brand and legacy/shadow/card collapse into groups w-mylib and legacy.
  • 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-id becomes empty after purging, the file is marked for Git deletion, same as the Collections block.

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-id correctly (partial or full clear).
  • On full clear, flags diff-id.<fileKey>.json for 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:

JSON
{
  "$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).

JSON
{
  "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 ref in 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 collections array to the desired order, or enable Adopt Existing.