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, paragraphIndentVariable (FLOAT)
fontFamily, fontWeight, textVariable (STRING)
booleanVariable (BOOLEAN)
typographyText Style
shadow, effects, blur, backdrop-blur, glassEffect Style
fill, gradient, imgPaint Style
gridGrid Style

fontStyle, strokeStyle, textCase, textDecoration, duration, cubicBezier, transition, template, and composition do not produce standalone Variables during Export Variables. They are used in Apply/Generate workflows and code generation.

Rename behavior (ID-safe by default)

When you rename an already exported token path (for example sp.reg.mdsp.md) and keep the same token meaning, Export now treats it as a rename update:

  • the existing Variable/Style is reused;
  • its Figma id is preserved;
  • bindings in components and files remain valid;
  • in export statistics this change is counted as modified, not as create+delete.

If Delete orphaned variables & styles is enabled and the rename candidate is ambiguous (for example multiple old paths could map to one new path), Export uses a safe fallback:

  • it defers orphan deletion for that ambiguous old path in the current run;
  • keeps IDs stable instead of guessing a risky mapping;
  • retries deletion automatically in a later run when the mapping becomes unambiguous.

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.
In the current version, destructive reorder is OFF by default:

  • if Sort variables & styles is OFF, export does not perform order sync and keeps current order as-is;
  • if Sort variables & styles is ON, export first tries non-destructive alignment;
  • if strict collection order still mismatches and Allow destructive reorder is OFF, export keeps collections as-is and returns a warning;
  • if the flag is ON and explicitly confirmed, the plugin performs a controlled remove + recreate reorder;
  • if Bind existing by name is enabled, destructive reorder is not applied.

Note: recreating collections can change Figma IDs of those collections. Enable destructive reorder only intentionally to align order with config.json.

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 base primitives that should not be exposed to library consumers.

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

When Selected Collections is used, orphan cleanup is scoped to the selected collections. Managed styles that belong to unselected collections are preserved, so a partial export does not wipe unrelated style groups. Run a full export only when you intentionally want orphan cleanup across the whole token project.


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 — unchanged tokens are usually skipped, which keeps repeat exports fast.
Additionally, alias/binding drift checks run for unchanged entries: if the target identity in Figma drifted (for example after library updates), the plugin performs a targeted rebind without forcing a full re-export.

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

Notes:

  • img tokens are exported through the fill toggle.
  • backdrop-blur tokens are exported through the blur toggle.
  • border is currently not exported to Figma styles in the current runtime (kept for schema compatibility).

Export behavior options

By default, all behavior toggles are OFF.
This gives the safest baseline: stable IDs, no destructive operations, and minimal side effects.

OptionDefaultWhat it does
Apply codeSyntax & scopesApplies $extensions.figma.scopes, $extensions.figma.codeSyntax, and figma.hide metadata to Variables, and updates Code Syntax blocks in Style descriptions
Force update allIgnores hash optimization and rewrites all matched variables/styles in selected collections
Delete orphaned variables & stylesRemoves managed Figma items that no longer exist in token files/config. Irreversible
Sort variables & stylesTries to align variables and styles with JSON order non-destructively (preserves IDs and Diff-ID bindings)
Allow destructive reorderRequires Sort variables & styles. If order still mismatches, allows controlled collection recreate to enforce JSON order (ID churn risk)
Bind existing by nameAdopts matching existing Figma variables/styles into Diff-ID to avoid duplicates on first rollout
Selected CollectionsAllExports only selected collections. Empty selection means all collections

Practical examples

  1. Daily export (recommended): keep all behavior options OFF. You get fast diff-based updates and stable IDs.
  2. Line height/token value changed, but style looks stale: first try normal export; if needed, run one pass with Force update all ON, then turn it OFF again.
  3. JSON order changed: enable Sort variables & styles first. Enable Allow destructive reorder only if strict order is required and non-destructive sync could not align collections.
  4. Migrating an existing Figma file without duplicates: enable Bind existing by name for the migration pass, verify result, then turn it OFF for regular runs.
  5. Partial collection export with cleanup: select the target collections and enable Delete orphaned variables & styles only if you want to clean those selected collections. Styles from unselected collections stay protected.
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.

When to enable each option

OptionEnable whenKeep disabled when
Apply codeSyntax & scopesYou intentionally sync publishing metadata from token filesYou only want value updates and want to avoid metadata churn
Force update allAfter migrations/manual edits, or when you need a one-time full refreshNormal daily export runs
Delete orphaned variables & stylesYou confirmed removed paths should be physically deleted from FigmaDuring refactors/renames before final verification
Sort variables & stylesJSON order changed and you want non-destructive align for variables and style folders/itemsOrder is already acceptable, or not important
Allow destructive reorderStrict JSON order is mandatory and non-destructive order sync did not convergeID stability is critical
Bind existing by nameFirst rollout into files that already contain compatible Figma variables/stylesYou want strict isolated creation from current token source only
CombinationTogglesWhat you get
Daily safe diff exportApply codeSyntax & scopes = OFF, Force update all = OFF, Delete orphaned... = OFF, Sort variables & styles = OFF, Allow destructive reorder = OFF, Bind existing by name = OFFFast export, only changed values/styles are updated, minimum Publish churn
Metadata sync passApply codeSyntax & scopes = ON, others OFFUpdates scopes/codeSyntax/hide metadata without forcing full value rewrite
Order alignment (safe)Sort variables & styles = ON, Allow destructive reorder = OFF, others usually OFFBest-effort JSON order alignment for variables + styles with ID preservation
Strict order migrationSort variables & styles = ON, Allow destructive reorder = ON (explicit consent)Enforces collection order when safe pass cannot converge; may churn collection IDs
Brownfield adoptionBind existing by name = ON, Force update all = OFF, Allow destructive reorder = OFFReuses matching local variables/styles, avoids duplicate creation during first migration
Recovery/full refreshForce update all = ON (temporary), others case-by-caseRewrites all matched items; useful after manual edits or stale state

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 could leave stale diff-id references after bulk deletion. As a result, binding new tokens to layers after a deletion could restore variables that were expected to stay 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.
  • Clears stale references 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.

Auto-export uses the current runtime defaults:

  • variable types: all enabled (color, number, string, boolean)
  • style types: enabled (typography, shadow, blur, effects, glass, fill, gradient, grid), border disabled
  • behavior flags: all OFF (Apply codeSyntax & scopes, Force update all, Delete orphaned..., Sort..., Allow destructive reorder, Bind existing by name)
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 Bind existing by name so the plugin adopts existing variables/styles 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

  • Check Allow destructive reorder:
    • OFF → collections should not be recreated (you should only see a warning);
    • ON → recreation is allowed after confirmation.