Skip to main content
Praveen Manchi
By Praveen Manchi
Mar 14, 202615 min
Figma
Design Systems
Design Tokens
REST API
Multi-Brand

Figma Variables & Multi-Brand Design System: Modes, Tokens, and the REST API

Figma Variables unlock a new level of design system power — enabling true multi-brand theming through Modes, seamless light/dark switching, and a direct pipeline to code via the Figma REST API. This deep-dive covers how to architect a scalable multi-brand system and automate token extraction for your dev workflow.

Figma Variables & Multi-Brand Design System: Modes, Tokens, and the REST API

Figma Variables & Multi-Brand Design System: Modes, Tokens, and the REST API

Figma Variables, introduced in 2023, fundamentally changed how design systems are built. Instead of managing dozens of static styles, you can now define a single token — say, color/brand/primary — and let it resolve to a different value depending on the active Mode: light vs dark, Brand A vs Brand B. When paired with the Figma REST API, you can extract every variable programmatically and feed it directly into your codebase as design tokens.

This guide walks through the full stack: architecture, Modes setup, and the REST API workflow that closes the gap between design and development.

1. Understanding Figma Variables

Figma Variables are typed tokens stored in a Variable Collection. Each collection has one or more Modes, and each variable has a value per Mode.

Variable Types

  • COLOR — hex/rgba values; used for fills, strokes, backgrounds
  • NUMBER — spacing, border radius, font sizes, opacity values
  • STRING — font families, icon names, locale strings
  • BOOLEAN — feature flags, visibility toggles

Variable Scopes

Each variable carries a scopes array that tells Figma where it can be applied: FILL_COLOR, STROKE_COLOR, CORNER_RADIUS, GAP, FONT_SIZE, etc. Scopes prevent a spacing token from accidentally being applied to a color field, keeping your system clean.

2. Designing a Multi-Brand System with Modes

A well-structured multi-brand system separates concerns into at least two Variable Collections:

Collection 1 — Primitives (no Modes needed)

Raw, alias-free values: every color in your palette, every step of your spacing scale, every font weight. These never change between brands.

  • primitive/blue-500#0049B8
  • primitive/space-44
  • primitive/radius-sm8

Collection 2 — Semantic / Brand Tokens (Modes = Brands)

Semantic tokens alias into Primitives and use Modes to resolve per-brand. Add one Mode per brand (Brand A, Brand B, Brand C). Each brand Mode maps the same semantic name to a different Primitive value.

  • brand/primary → Brand A: primitive/blue-500 | Brand B: primitive/purple-600
  • brand/surface → Brand A: #FFFFFF | Brand B: #0F0F1A

Collection 3 — Theme Tokens (Modes = Light / Dark)

A third collection handles appearance modes. Each variable aliases into the semantic brand token, which in turn aliases into a Primitive. This creates a clean three-level chain: Primitive → Brand → Theme.

  • color/background/page → Light: brand/surface | Dark: primitive/gray-950
  • color/text/primary → Light: primitive/gray-900 | Dark: primitive/gray-50

Setting the Active Mode in Figma

In the Design panel, select any frame and click the Variables icon. You'll see each collection with a Mode dropdown. Switch Brand Mode to "Brand B" and your entire frame instantly re-skins. Switch Theme Mode to "Dark" and all semantic color tokens resolve to their dark-mode aliases. No re-applying styles — just Mode switches.

3. Figma REST API — Getting Variables

Once your system is solid in Figma, the REST API lets you pull every variable out programmatically. The key endpoint:

GET https://api.figma.com/v1/files/:file_key/variables/local
Authorization: Bearer <FIGMA_PERSONAL_ACCESS_TOKEN>

This returns meta.variables (the tokens) and meta.variableCollections (the collections + Modes). Here is a minimal Node.js script to fetch and log them:

// fetch-figma-variables.mjs
import fetch from 'node-fetch';

const FILE_KEY = 'YOUR_FILE_KEY'; // from the Figma file URL
const API_TOKEN = process.env.FIGMA_TOKEN;

async function getFigmaVariables() {
const res = await fetch(
`https://api.figma.com/v1/files/${FILE_KEY}/variables/local`,
{ headers: { 'X-Figma-Token': API_TOKEN } }
);

if (!res.ok) throw new Error(`Figma API ${res.status}: ${await res.text()}`);

const { meta } = await res.json();
const { variables, variableCollections } = meta;

// Build a lookup: collectionId → { name, modes }
const collections = Object.fromEntries(
Object.values(variableCollections).map(c => [c.id, c])
);

// Print each variable with its values per Mode
for (const v of Object.values(variables)) {
const col = collections[v.variableCollectionId];
console.log(`[${col.name}] ${v.name} (${v.resolvedType})`);
for (const [modeId, value] of Object.entries(v.valuesByMode)) {
const modeName = col.modes.find(m => m.modeId === modeId)?.name ?? modeId;
console.log(` ${modeName}:`, value);
}
}
}

getFigmaVariables().catch(console.error);

4. Converting Figma Variables to Design Tokens (W3C Format)

The W3C Design Token Community Group defines a standard JSON format. Here's how to transform the Figma API response into it — one file per Mode, ready to be processed by Style Dictionary or Tokens Studio:

// transform-tokens.mjs
function toW3CValue(variable, rawValue) {
if (typeof rawValue === 'object' && rawValue.type === 'VARIABLE_ALIAS') {
// Reference to another token — use the aliased variable's name
return { $value: `{alias.${rawValue.id}}`, $type: variable.resolvedType.toLowerCase() };
}
if (variable.resolvedType === 'COLOR') {
const { r, g, b, a } = rawValue;
const toHex = n => Math.round(n * 255).toString(16).padStart(2, '0');
const hex = `#${toHex(r)}${toHex(g)}${toHex(b)}`;
return { $value: a < 1 ? `rgba(${Math.round(r*255)},${Math.round(g*255)},${Math.round(b*255)},${a})` : hex,
$type: 'color' };
}
return { $value: rawValue, $type: variable.resolvedType.toLowerCase() };
}

function buildTokenTree(variables, variableCollections, targetModeId) {
const tree = {};
for (const v of Object.values(variables)) {
const col = variableCollections[v.variableCollectionId];
const modeId = targetModeId ?? col.defaultModeId;
const rawValue = v.valuesByMode[modeId];
if (rawValue === undefined) continue;

// Nest by variable name path (e.g. "color/brand/primary" → tree.color.brand.primary)
const parts = v.name.split('/');
let node = tree;
for (const part of parts.slice(0, -1)) {
node[part] ??= {};
node = node[part];
}
node[parts.at(-1)] = toW3CValue(v, rawValue);
}
return tree;
}

// Usage:
// const lightTokens = buildTokenTree(variables, variableCollections, lightModeId);
// fs.writeFileSync('tokens/light.json', JSON.stringify(lightTokens, null, 2));

5. Plugging Tokens into Your Dev Workflow

Once you have the W3C-format JSON files, pipe them through Style Dictionary to auto-generate CSS custom properties, SCSS variables, or TypeScript constants — whatever your stack needs.

# tokens/
# light.json
# dark.json
# brand-a.json
# brand-b.json

# style-dictionary.config.mjs
export default {
source: ['tokens/light.json'],
platforms: {
css: {
transformGroup: 'css',
prefix: 'dt',
buildPath: 'src/styles/generated/',
files: [{ destination: 'light.css', format: 'css/variables' }]
},
ts: {
transformGroup: 'js',
buildPath: 'src/tokens/',
files: [{ destination: 'light.ts', format: 'javascript/es6' }]
}
}
};

6. Automating the Pipeline with GitHub Actions

Wire the whole thing into CI so tokens update automatically whenever the Figma file changes (via a Figma webhook) or on a nightly schedule:

# .github/workflows/sync-design-tokens.yml
name: Sync Design Tokens
on:
schedule:
- cron: '0 6 * * *' # every day at 6 AM UTC
workflow_dispatch: # manual trigger from GitHub UI

jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: node scripts/fetch-figma-variables.mjs
env:
FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
FIGMA_FILE_KEY: ${{ secrets.FIGMA_FILE_KEY }}
- run: npx style-dictionary build
- uses: peter-evans/create-pull-request@v6
with:
title: 'chore: sync design tokens from Figma'
branch: 'design-tokens/auto-sync'

Key Takeaways

  • Three-level alias chain (Primitive → Brand → Theme) keeps your tokens composable and brand-swappable without duplication.
  • Modes are the superpower — one semantic token, many values. Use them for brand, theme, density, locale, or any dimension you need.
  • The REST API is the bridge/variables/local gives you every variable with its per-Mode values in a single request.
  • Automate the pipeline — use Style Dictionary + GitHub Actions to turn Figma into a live source-of-truth that pushes tokens to your codebase on every design update.

The result: designers own the token values in Figma, developers consume generated CSS/TS files, and both sides stay in sync automatically — no more copy-pasting hex codes from Zeplin or Inspect panels.