Skip to content

Integrations

dtcg-formulas is designed to be tool-agnostic. The core is a pure resolver that takes DTCG JSON in and writes computed $values back — no hard dependency on any particular build system. Integrations are thin wrappers over that core.

Three recipes cover the common cases.

Availability

The bare-JSON and CLI paths land in 0.2.0. The Style Dictionary plugin lands in 0.3.0. The Terrazzo plugin is on the 0.4.0+ track. This page documents the shape each integration will take so you can plan adoption.

1. Bare JSON pipeline (any Node build)

Use this when you don't have — or don't want — a larger build framework. It's the most direct path: a Node script that compiles one file to another.

ts
// build-tokens.mjs
import { compile } from '@dtcg-formulas/resolver'; // 0.2.0
import { readFileSync, writeFileSync } from 'node:fs';

const input = JSON.parse(readFileSync('tokens.json', 'utf-8'));

const { tokens, diagnostics } = await compile(input, {
  definitions: ['tokens/functions/**/*.module.scssdef'],
  // optional adapters, pulled from @dtcg-formulas/adapter-* packages
  adapters: ['@dtcg-formulas/adapter-leonardo'],
});

if (diagnostics.some((d) => d.severity === 'error')) {
  for (const d of diagnostics) {
    console.error(`${d.code} ${d.severity}: ${d.message}`);
  }
  process.exit(1);
}

writeFileSync('tokens.resolved.json', JSON.stringify(tokens, null, 2));

Or skip the script and use the CLI directly:

bash
npx dtcg-formulas compile tokens.json -o tokens.resolved.json
npx dtcg-formulas lint tokens.json           # preflight only
npx dtcg-formulas check tokens.json          # dry-run with full diagnostic report

This is the integration path the library optimizes for. Every other integration is a thin wrapper over this same core.

2. Style Dictionary

Style Dictionary consumers pull in @dtcg-formulas/style-dictionary-plugin, which registers a transitive preprocessor that runs after SD resolves token aliases but before platform-specific transforms.

ts
// style-dictionary.config.ts (Style Dictionary 4.x, ESM)
import StyleDictionary from 'style-dictionary';
import { register } from '@dtcg-formulas/style-dictionary-plugin'; // 0.3.0

register(StyleDictionary, {
  definitions: ['tokens/functions/**/*.module.scssdef'],
  adapters: ['@dtcg-formulas/adapter-leonardo'],
});

export default {
  source: ['tokens/**/*.json'],
  preprocessors: ['dtcg-formulas'],
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'build/css/',
      files: [{ destination: 'variables.css', format: 'css/variables' }],
    },
  },
};

Because formulas resolve before platform transforms, every SD format — CSS variables, iOS, Android, whatever — sees the computed $value and nothing else. Provenance in $extensions.org.dtcg-formulas is preserved for any format that wants to emit it.

See Style Dictionary DTCG docs for how SD handles the underlying DTCG syntax.

3. Terrazzo

Terrazzo ships its own DTCG-native compiler. The @dtcg-formulas/terrazzo-plugin hooks into its parser phase so formulas resolve before Terrazzo's built-in plugins (CSS, Sass, JS/TS) generate output.

ts
// terrazzo.config.ts (0.4.0+)
import { defineConfig } from '@terrazzo/cli';
import dtcgFormulas from '@dtcg-formulas/terrazzo-plugin';
import css from '@terrazzo/plugin-css';

export default defineConfig({
  tokens: 'tokens.json',
  plugins: [
    dtcgFormulas({
      definitions: ['tokens/functions/**/*.module.scssdef'],
      adapters: ['@dtcg-formulas/adapter-leonardo'],
    }),
    css({ filename: 'tokens.css' }),
  ],
});

Choosing an integration

You have...Use
A Node build and no token-processing frameworkBare JSON pipeline (CLI or resolver API)
An existing Style Dictionary 4.x setupStyle Dictionary plugin
An existing Terrazzo setupTerrazzo plugin
A different build toolBare JSON via the resolver API — wrap it in a script that fits your framework

All four paths share the same core and the same diagnostics. Switching later is a config change, not a rewrite.

Adapter packages

Any integration that resolves formulas calling contrast-aware color (leo()), named colors (color-name()), material shadows, etc. needs the matching adapter package installed at runtime:

bash
npm install @dtcg-formulas/adapter-leonardo      # 0.3.0
npm install @dtcg-formulas/adapter-color-names   # 0.3.0
npm install @dtcg-formulas/adapter-material-shadow  # 0.3.0

Adapters are opt-in to keep the core small and deterministic. Install only what your token set actually calls.

Next steps

Released under the MIT License.