Skip to content

Core concepts

DTA follows Figma’s variable model. A collection groups variables; a mode is one set of values for all of them (a brand, a theme, a breakpoint). On disk, every collection and mode is one JSON file named {Collection}.{Mode}.json:

tokens/Primitives.Value.json one collection, one mode
tokens/Brand(Alias).BrandA.json one collection, a mode per brand
tokens/Brand(Alias).BrandB.json
tokens/ScreenType.Desktop.json one collection, a mode per breakpoint

Inside, the files use the W3C Design Tokens (DTCG) format: nested groups, and tokens with $type and $value. The full format: Token files.

A value in braces points at another token: "$value": "{Colors.Foundation.Blue.500}". In Figma the same path reads Colors/Foundation/Blue/500; DTA converts between the two when it pulls and pushes.

Aliases carry no collection name, so variable names must be unique across all collections. That is what lets DTA resolve {Colors.Foundation.Blue.500} wherever it lives, and it is the one rule DTA asks your Figma file to follow.

dta graph shows the alias structure, and dta lint fails on aliases that point nowhere or in a circle.

Most token sets end up with layers, whatever they call them. DTA works with any names, but its checks and defaults speak this model:

Layer Example collection Modes Values
Primitives Primitives one raw values: #0057b8, 8
Brand Brand(Alias) one per brand aliases into the primitives
Dimension ScreenType one per breakpoint aliases or values that differ per screen

dta analyze reads a Figma file and suggests which collection plays which role, and dta init uses that to propose collections and brands. The semantic-must-alias lint rule keeps a brand layer made of aliases only.

dta build writes one set of files for the single-mode collections and one theme per brand:

  • Single-mode collections (the primitives) become :root custom properties in variables.css (aliases stay var() references) and base.css (values resolved).
  • Each brand listed in brands becomes themes/<brand>.css, scoped to [data-brand="<brand>"]. Switch brands by setting the attribute on any element, <html data-brand="branda"> for the whole page.
  • The breakpoint collection named in breakpoints is added to variables.css: its default mode on :root, the other modes inside their media queries.
  • JavaScript and Tailwind files are written next to them.
output/css/themes/branda.css
[data-brand="branda"] {
--colors-brand-primary: var(--colors-foundation-blue-500);
--colors-brand-primary-dark: var(--colors-foundation-blue-700);
--colors-brand-accent: var(--colors-foundation-sky-500);
…
}

Every file and its format: Outputs.

The project config is dta.config.ts (also .mts, .js, .mjs or .json). Unknown keys are rejected, so a typo shows up as an error instead of being ignored:

dta.config.ts
export default {
figma: { source: 'file' }, // 'api' on an Enterprise plan
tokens: { dir: 'tokens' },
collections: ['Primitives', 'Brand(Alias)', 'ScreenType'], // default: all
brands: ['BrandA', 'BrandB'],
breakpoints: {
collection: 'ScreenType',
default: 'Mobile', // on :root
modes: { Tablet: '(min-width: 768px)', Desktop: '(min-width: 1024px)' },
},
outputs: {
formats: ['css', 'tailwind-v4'], // default: all four ('tailwind-v3', 'js' too)
css: { outDir: 'output/css' },
tailwind: { outDir: 'output/tailwind' },
},
lint: { rules: { 'semantic-must-alias': { severity: 'error', collections: ['Brand(Alias)'] } } },
}

Once DTA is installed as a package, defineConfig from design-token-authority wraps the object for editor completion; it changes nothing else.

Every key, with its type and default: Configuration. A dta.config.json can point "$schema" at /schemas/dta.config.schema.json on this site for completion in editors.