Skip to content

Design tokens as the source of truth

A design system falls apart when colour lives in three places: Figma Variables, a React theme file, and an Angular Sass map.

The fix is not “put everything in Figma” and not “ignore designers.” It is one owned spec, then generated views.

                    AIRFRAME TOKENS
                 (source of truth)



        ┌────────────┴────────────┐
        │                         │
     DESIGN                     CODE
        │                         │
   Figma views              @airframeui
 (generated, planned)        (ships today)
        │                         │
  Variables / modes         CSS · JSON · TS
        │                         │
        └────────────┬────────────┘

            Same names. Same values.

If a designer changes a Variable in Figma and that never lands in git, code is already stale. If a developer edits a hex in CSS and Figma never updates, mockups lie.

Figma is not the source of truth. The repository is. Figma should consume the spec.

@airframeui/tokens is authored as CSS (tokens.base.css, light, dark, high-contrast). The build emits:

ViewPackage
CSS custom properties@airframeui/tokens/tokens.css (also bundled in @airframeui/core)
JSON + catalog@airframeui/tokens/tokens.json, catalog.json
TypeScript@airframeui/tokens

That JSON is an Airframe implementation shape (primitives, semantic, knobs, components, themes). It is not DTCG. It is not a Figma file.

Runtime branding is still CSS:

:root {
  --af-base-primary: #0e80eb;
  --af-font-body: 'Inter', system-ui, sans-serif;
}

Modes: light, dark, high-contrast light, high-contrast dark. Brands: [data-brand]. Theming. Full list: Tokens.

Theme Studio and @airframeui/theme already read:

  • DTCG (W3C Design Tokens)
  • Tokens Studio export
  • CSS custom properties
  • Figma Variables export JSON (variables[] / valuesByMode)
  • Style Dictionary-like JSON

They write --af-* CSS. That is how an existing design system maps into Airframe without a rewrite.

npx af theme generate --from ./tokens.json -o theme.css
npx af theme lint theme.css

Most projects never need that. Override primitives in :root and stop.

Designers cannot yet consume Airframe as Figma Variables generated from the same spec.

That export is on the roadmap. Until it ships, do not treat “everywhere” as including Figma in marketing. The loop you can run today is: git CSS (and optional Theme Studio inbound) → applications.

Target pipeline:

Airframe token spec (git)

      ├── CSS custom properties     (ships)
      ├── JSON / TypeScript         (ships)
      ├── DTCG interchange          (planned)
      ├── Figma Variables           (planned)
      └── Variables Studio dataset  (investigate)

Variables Studio is a specific plugin workflow. Native Figma Variables are another. Tokens Studio is a third. DTCG is the interchange standard those tools are moving toward.

Before writing an exporter, Airframe should confirm:

  1. Whether DTCG can be the file every adapter reads.
  2. Whether to generate native Figma Variables (plugin or REST), a Variables Studio dataset, or both.
  3. How modes map: Airframe already has light / dark / high-contrast, plus [data-brand].
  4. That we do not add a fourth proprietary interchange format. CSS stays the runtime. DTCG is the likely public file. @airframeui/tokens JSON stays an implementation view of the CSS source.

Possible long-term split:

  • Canonical in git: keep CSS (current), or move the authored spec to DTCG and generate CSS. That is an architecture choice, not a homepage line. Either way, git wins over Figma.
  • Generated: CSS (if DTCG becomes authored), DTCG (if CSS stays authored), Figma Variables, optional Variables Studio.

Do not reverse the arrow (Figma edits as the pipeline). Theme Studio inbound remains for mapping a foreign system into Airframe, not for round-tripping designer doodles.

The CSS already has these collections. Export should not flatten them into one paint list.

LayerCSSFigma-style names
Primitive--af-base-primary, --af-space-4color.blue.500, spacing.4
Semantic--af-color-background, --af-color-textcolor.background.default, color.text.primary
Component--af-btn-*, --af-card-*button.background, button.radius
Modes--*-light / --*-dark / --hc-*Light, Dark, High contrast
Brand[data-brand='…']Extra modes or a Brand collection

Component tokens are how a kit stays aligned without copying hex into every wrapper.

You do not need Airframe patterns to use the token layer.

  1. Tokens only — map --af-*. Keep existing widgets.
  2. Layoutsaf-stack, af-inline, af-grid.
  3. Patternsaf-btn, af-card, af-input.
  4. Wrappers — those patterns inside <my-button>.

Two palettes is the failure mode. Use as much as you need.

  • Pick one canonical set in git. Alias the rest.
  • If the brand is already in Tokens Studio or a Figma Variables export, run it through Theme Studio and commit theme.css.
  • Share that CSS in every app (React, Angular, HTML).
  • Wait for generated Figma Variables before promising designers a round trip.