Creating Design System Rules for Figma-to-Code Workflows in Plugins: Architecture and Implementation

OpenAI Plugins enforces design system rules by separating primitive tokens from semantic tokens, restricting variable scopes to specific UI roles, and embedding platform-specific code syntax to generate production-ready CSS, Android, and iOS variables from Figma files.

The OpenAI Plugins repository ships a full-stack Figma integration that transforms static designs into maintainable code. By implementing strict architectural patterns when creating design system rules for Figma-to-code workflows in plugins, developers ensure that generated token collections remain idempotent across multiple runs while supporting Light, Dark, and high-contrast modes.

Understanding the Figma-to-Code Pipeline Architecture

The workflow is orchestrated by the /implement-from-figma command defined in plugins/figma/commands/implement-from-figma.md. This command parses a Figma URL, extracts node IDs, captures screenshots, and delegates to a design-system generator that executes a series of token-creation scripts.

The Command Layer

When a user invokes /implement-from-figma, the system fetches the Figma file and initializes the token pipeline. The command hands off to scripts located in plugins/figma/skills/figma-generate-library/references/token-creation.md, which handle collection creation, primitive variable definition, and semantic aliasing.

Token Creation and Collections

The pipeline distinguishes between two fundamental collection types:

  • Primitive collections store raw design values (HEX colors, spacing units) with scopes = [] to hide them from designer pickers.
  • Semantic collections expose aliased variables with targeted scopes (e.g., FRAME_FILL, SHAPE_FILL) that map to specific UI component roles.

Each variable must carry code syntax metadata for Web (var(--...) wrapper mandatory), Android, and iOS to enable Dev Mode handoff.

Design-System Rules for Token Architecture

Strict adherence to these rules prevents token leakage and ensures deterministic builds.

Separate Primitives from Semantics

Primitive variables are mode-agnostic values stored in a collection named Primitives. Semantic variables reside in collections like Color or Spacing and reference primitives via VARIABLE_ALIAS for each mode (Light, Dark, etc.).

This separation enables global changes—updating a single primitive updates every semantic alias across all modes. In token-creation.md, primitives are created with v.scopes = [] while semantic variables receive explicit scopes like v.scopes = ['FRAME_FILL','SHAPE_FILL'].

Scope Variables Precisely (Never Use ALL_SCOPES)

Never assign ALL_SCOPES to design tokens. Broad scoping floods every Figma picker with irrelevant tokens, violating the principle of least privilege.

Instead, assign specific scopes based on the variable's intended use. The reference table in plugins/figma/skills/figma-use/references/variable-patterns.md maps scopes to design-system roles:

  • FRAME_FILL for background colors
  • SHAPE_FILL for component fills
  • TEXT_FILL for typography colors

Enforce Code Syntax for Web, Android, and iOS

Every variable must declare platform-specific code syntax using setVariableCodeSyntax. For Web output, the value must wrap the CSS variable in var():

variable.setVariableCodeSyntax('WEB', 'var(--color-bg-primary)');

Without this wrapper, Figma Dev Mode displays raw hex values rather than the CSS variable reference. Android and iOS syntax strings follow the same pattern but omit the var() wrapper.

Maintain Idempotency with Shared Plugin Data

All created entities must be tagged with sharedPluginData to prevent duplication on re-runs. The standard keys are:

  • 'dsb' – namespace
  • 'run_id' – unique execution identifier
  • 'key' – semantic path (e.g., 'collection/primitives', 'color/bg/primary')

This tagging enables the "check-before-create" logic that makes the pipeline idempotent.

Implementing the Token Pipeline

Creating Primitive Collections

Begin by initializing a collection for raw values. In plugins/figma/skills/figma-generate-library/references/token-creation.md, the implementation follows this pattern:

const RUN_ID = "dsb-2024-01";
const primColl = figma.variables.createVariableCollection("Primitives");
primColl.renameMode(primColl.modes[0].modeId, "Value");
primColl.setSharedPluginData('dsb', 'run_id', RUN_ID);
primColl.setSharedPluginData('dsb', 'key', 'collection/primitives');

Primitives are populated with empty scopes to hide them from the UI:

const collections = await figma.variables.getLocalVariableCollectionsAsync();
const primColl = collections.find(c => c.getSharedPluginData('dsb','key') === 'collection/primitives');
const valueMode = primColl.modes[0].modeId;

const palette = [
  { name: 'blue/500', hex: '#3B82F6' },
  { name: 'gray/900', hex: '#111827' },
];

for (const {name, hex} of palette) {
  const v = figma.variables.createVariable(name, primColl, 'COLOR');
  v.setValueForMode(valueMode, hexToRgb(hex));
  v.scopes = []; // hide from UI
  v.setVariableCodeSyntax('WEB', `var(--${name.replace('/','-')})`);
  v.setSharedPluginData('dsb','run_id',RUN_ID);
  v.setSharedPluginData('dsb','key',`primitive/${name}`);
}

Building Semantic Variables with Mode Aliasing

Semantic variables reference primitives via createVariableAlias. First, retrieve the mode IDs from the semantic collection:

const collections = await figma.variables.getLocalVariableCollectionsAsync();
const primColl = collections.find(c => c.getSharedPluginData('dsb','key') === 'collection/primitives');
const colorColl = collections.find(c => c.getSharedPluginData('dsb','key') === 'collection/color');

const lightMode = colorColl.modes.find(m => m.name === 'Light').modeId;
const darkMode  = colorColl.modes.find(m => m.name === 'Dark').modeId;

function getPrim(name) {
  const v = allVars.find(v => v.getSharedPluginData('dsb','key') === `primitive/${name}`);
  if (!v) throw new Error(`Missing primitive ${name}`);
  return v;
}

Create the semantic variable and bind it to primitives for each mode:

const v = figma.variables.createVariable('color/bg/primary', colorColl, 'COLOR');
v.setValueForMode(lightMode, figma.variables.createVariableAlias(getPrim('white/1000')));
v.setValueForMode(darkMode,  figma.variables.createVariableAlias(getPrim('gray/900')));
v.scopes = ['FRAME_FILL','SHAPE_FILL'];
v.setVariableCodeSyntax('WEB', 'var(--color-bg-primary)');
v.setSharedPluginData('dsb','run_id',RUN_ID);
v.setSharedPluginData('dsb','key','color/bg/primary');

Validation and Error Recovery

After each phase, run validation scripts to catch missing scopes or broken aliases. The token-creation.md reference includes verification helpers:

const collections = await figma.variables.getLocalVariableCollectionsAsync();
const allVars = await figma.variables.getLocalVariablesAsync();

const missingScopes = allVars.filter(v => v.scopes.length === 0 && v.resolvedType !== 'BOOLEAN');
if (missingScopes.length) console.warn('Unscoped non-primitive vars:', missingScopes);

For error recovery after failed use_figma calls, consult plugins/figma/skills/figma-use/references/validation-and-recovery.md.

Summary

  • Separate concerns by storing raw values in primitive collections (hidden scopes) and design tokens in semantic collections with specific scopes.
  • Avoid ALL_SCOPES to keep Figma pickers clean; use targeted scopes like FRAME_FILL and TEXT_FILL as defined in variable-patterns.md.
  • Wrap Web syntax in var() using setVariableCodeSyntax('WEB', 'var(--token)') to ensure Dev Mode displays usable CSS.
  • Tag every entity with sharedPluginData keys (run_id, key) under the 'dsb' namespace to enable idempotent re-runs.
  • Validate after each phase using the count and alias verification scripts from token-creation.md to prevent downstream errors.

Frequently Asked Questions

How do I prevent duplicate variables when re-running the Figma-to-code pipeline?

Tag every created collection and variable with setSharedPluginData('dsb', 'run_id', RUN_ID) and setSharedPluginData('dsb', 'key', uniqueKey). Before creation, query existing variables using getSharedPluginData('dsb', 'key') to check for existence, ensuring the script remains idempotent across multiple executions.

Why must Web code syntax use the var() wrapper?

Figma Dev Mode requires the var() wrapper to recognize and display CSS custom properties. Without it, the interface shows raw hex values, breaking the design-to-code handoff. Always call variable.setVariableCodeSyntax('WEB', 'var(--token-name)') when creating semantic variables.

What is the difference between primitive and semantic variable collections?

Primitive collections store raw, mode-agnostic values (e.g., blue/500 = #3B82F6) with scopes = [] to hide them from designers. Semantic collections contain variables that reference primitives via aliases and carry specific modes (Light, Dark) and scopes (e.g., FRAME_FILL), serving as the API between design and engineering.

Where are the validation scripts for checking broken aliases?

Validation helpers are documented in plugins/figma/skills/figma-generate-library/references/token-creation.md under the "Validation" section. These scripts verify that every semantic variable resolves to a valid primitive alias and that all non-primitive variables have explicit scopes assigned.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →