Get started

Style Dictionary with DTCG tokens: verify what gets converted and emitted

Style Dictionary can consume tokens written with DTCG properties, but ingestion, legacy conversion, and platform output are different operations. Decide which one you need, pin the version and configuration, then inspect the generated artifact and a named consumer before adopting the token set.

Updated September 10, 2026

Choose the operation before the tool

The search for "Style Dictionary DTCG tokens" can point to three different jobs. They share token data, but they don't produce the same evidence. Classify the input and desired output first.

Direct ingestionLegacy conversionPlatform transformation
Authoritative inputToken data using documented DTCG propertiesLegacy Style Dictionary token dataToken data plus a Style Dictionary configuration
OperationParse and process the existing representationConvert legacy properties to DTCG-shaped propertiesApply configured transforms and formats
Source-file mutationNoneOnly if the caller deliberately writes the returned conversionNone by the build itself
Primary resultA processed dictionaryConverted token dataA platform artifact such as CSS
What completion provesThis installed version accepted the fixtureThe selected conversion completedThe configured build emitted a file
What remains unprovenFull specification support and consumer behaviorSemantic normalization and platform compatibilityCorrect mapping and behavior in named consumers
Three operations with distinct proof boundaries

If the source already uses $value, don't convert it merely because Style Dictionary is the next tool. Ingestion reads the source. Conversion changes its representation. Transformation produces a consumer-facing format.

Don't claim more for the fixture than the evidence supports

The fixtures below use Style Dictionary's documented DTCG property syntax. They don't prove conformance to a named DTCG report. Style Dictionary's current documentation also warns that the 2025.10 format is not fully supported.

Pin a Style Dictionary 5 build contract

This build is scoped to Style Dictionary 5, so it requires Node.js 22 or later. Pin the resolved package version in your own record. Results from another version apply to that version and configuration, not to every release.

Save this complete source as tokens.json. The group-level $type is inherited by both leaf tokens, and the semantic token aliases the base token.

{
  "color": {
    "$type": "color",
    "base": {
      "indigo": {
        "$value": "#4f46e5"
      }
    },
    "action": {
      "primary": {
        "$value": "{color.base.indigo}",
        "$description": "Illustrative primary action color"
      }
    }
  }
}
tokens.json using Style Dictionary's documented DTCG property syntax

Save the following ES module as style-dictionary.config.js. It defines one CSS platform, reads only tokens.json, uses build/ as the build path, applies the css transform group, and writes tokens.css with the css/variables format. No filter is configured, so both tokens remain eligible for output. outputReferences: true retains the alias in the CSS where the format can do so. Setting showFileHeader: false removes the generated comment header.

export default {
  source: ['tokens.json'],
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'build/',
      files: [
        {
          destination: 'tokens.css',
          format: 'css/variables',
          options: {
            outputReferences: true,
            showFileHeader: false
          }
        }
      ]
    }
  }
};
style-dictionary.config.js for a Style Dictionary 5 CSS build

Run the build with the project-installed executable so the recorded package version governs the result.

npx style-dictionary build --config style-dictionary.config.js
Exact build invocation

For this fixture and configuration, the block below is the expected content of build/tokens.css. The base variable appears because the configuration has no filter. The semantic variable retains a CSS reference because outputReferences is enabled. Treat this as the expected artifact, then compare it with the file produced by the pinned installation.

:root {
  --color-base-indigo: #4f46e5;
  --color-action-primary: var(--color-base-indigo);
}
Expected generated file: build/tokens.css

Application CSS belongs to a separate evidence layer. The following rule is an illustrative consumer expectation. It isn't generated output or an observation from a running application.

.primary-button {
  background-color: var(--color-action-primary);
}
Illustrative consumer CSS, kept separate from generated output

Write the expectation before running the build

Record --color-base-indigo: #4f46e5 and --color-action-primary: var(--color-base-indigo) as expectations. Add observed values only after inspecting the generated file. This keeps copied expectations from being mistaken for evidence.

Understand what direct ingestion does internally

Direct ingestion doesn't rewrite tokens.json. Parsing creates a separate processed representation inside Style Dictionary. According to the utility reference, Style Dictionary runs typeDtcgDelegate by default after parsing and before user preprocessors. It delegates an inherited group $type to the token leaves, then removes the group-level $type from the processed representation.

This distinction matters when you're debugging preprocessors. The source fixture still has one $type on color, while a user preprocessor can receive token leaves with delegated type information and no group-level property. Record which representation you inspected instead of reporting only that "the type moved."

  1. 1

    Inspect source evidence

    Confirm that color.base.indigo and color.action.primary exist, that the group declares $type: color, and that the semantic value is {color.base.indigo}. Record the source hash.

  2. 2

    Run the pinned build

    Use the exact configuration and command above. Capture the resolved Style Dictionary version, Node.js version, exit status, and warnings.

  3. 3

    Inspect processed token data

    Keep the source alias, delegated type, and resolved value in separate fields. Note whether the evidence came from source data, processed data, or a diagnostic format.

  4. 4

    Inspect the emitted artifact

    Open build/tokens.css. Confirm that both expected symbols exist and that the semantic symbol retains the expected reference.

  5. 5

    Inspect the named consumer

    Confirm that .primary-button or the real named consumer uses --color-action-primary in the tested mode and state. Record the observation separately from the CSS artifact.

Start with a DTCG token handoff

Identity Forge can supply a DTCG token export as upstream design-system input. Apply the same pinned build and source-to-consumer trace in the consuming project.

Convert a complete legacy fixture

Legacy conversion answers a narrower question: can the selected utility express the supplied legacy object with DTCG-shaped properties? The fixture must be complete enough to test its alias, so keep the base token and semantic token in the same input.

const dictionary = {
  color: {
    base: {
      indigo: {
        value: '#4f46e5',
        type: 'color'
      }
    },
    action: {
      primary: {
        value: '{color.base.indigo}',
        type: 'color',
        description: 'Illustrative primary action color'
      }
    }
  }
};
Complete legacy input with a resolvable alias

The concise DTCG overview and the utility reference describe type placement from different angles. The overview explains conversion as moving group types to tokens. For this named convertToDTCG call, however, the current utility reference is authoritative and documents a different default: it condenses common types to the highest shared group. The output shown here keeps $type on each token, so the call explicitly disables that default with applyTypesToGroup: false.

import { convertToDTCG } from 'style-dictionary/utils';

const converted = convertToDTCG(dictionary, {
  applyTypesToGroup: false
});

console.log(JSON.stringify(converted, null, 2));
Exact conversion invocation with non-default token-level type placement
{
  "color": {
    "base": {
      "indigo": {
        "$value": "#4f46e5",
        "$type": "color"
      }
    },
    "action": {
      "primary": {
        "$value": "{color.base.indigo}",
        "$type": "color",
        "$description": "Illustrative primary action color"
      }
    }
  }
}
Corresponding converted output with token-level $type properties

In this fixture, value, type, and description become $value, $type, and $description. The alias stays intact, and both ends of the reference are present. If you omit applyTypesToGroup, don't expect this exact type placement: the documented default can condense common types to the highest common group.

DTCG-shaped output isn't semantic normalization

Style Dictionary's DTCG guidance says conversion doesn't automatically refactor common legacy type values. A converter can rename structural properties while preserving a legacy type name that the next operation doesn't support. Converted JSON isn't platform CSS either. It still needs ingestion, transformation, emission, and consumer verification.

Run the conversion and build preflight

These small fixtures establish a reproducible route. Before applying it to a full token set, check the conditions that can produce plausible but incorrect output.

  • Input convention: confirm that one Style Dictionary instance isn't receiving mixed legacy and DTCG property conventions.
  • Specification boundary: list the constructs used by the source and compare them with documented support for the pinned version, especially if the project targets DTCG 2025.10.
  • Type values: identify legacy names preserved by conversion and confirm that the selected transforms understand them.
  • Type placement: record whether conversion uses the default group condensation or explicit token-level placement.
  • Inherited types: compare the source representation with the processed representation created by typeDtcgDelegate.
  • Aliases: test reachable direct, chained, missing, and circular references without claiming that the two-token fixture covers the full graph.
  • Source collisions: preserve warnings from merged sources and identify every file that defines a duplicated path.
  • Metadata: decide which descriptions, extensions, deprecation markers, and source metadata must survive each operation.
  • Output settings: record the transform group, format, filters, outputReferences value, file-header setting, and destination.
  • Consumer mapping: name the component, mode, and state that should use each reviewed symbol.

A collision warning needs a disposition. Style Dictionary merges token sources, so a duplicate path may represent intentional precedence or an accidental replacement. Record the path, every defining source, the winner, why that precedence is allowed, and who owns the decision.

Route failures to the owning layer

Owning layerInspection criterionBlock condition
Input rejectedSpecification target, parser, or installed versionCompare the exact construct with documented support for the pinned releaseA required construct is unsupported and no approved source change exists
Legacy type remains unfamiliarMigration decisionCompare the preserved type value with transform requirementsThe next operation cannot interpret a required type
Alias failsSource token graph or reference handlingConfirm both paths, braces, separator, and absence of a cycleA required reference cannot resolve reliably
Token is replacedSource merge and precedenceIdentify every source defining the path and review collision warningsThe winning source or precedence is unknown
Generated value is wrongSource, alias chain, or transformCompare source value, processed value, and emitted representation in orderThe artifact contradicts the approved source decision
Expected symbol is absentFilter, name transform, format, or destinationInspect the processed dictionary and exact output fileA required consumer symbol is not emitted
Artifact is correct but component is wrongConsumer mapping, mode, state, or local overrideInspect the named consumer under recorded conditionsAn in-scope consumer uses another value with no approved exception
A practical failure-routing matrix

Fix the earliest layer that contains the mismatch. Editing generated CSS can hide a wrong source alias. Changing an upstream token can't repair a component that ignores a correct emitted symbol.

Record acceptance from source to consumer

Keep source identity, execution details, artifact inspection, and consumer evidence in one record. The placeholders stay incomplete until a real run supplies the observations.

style_dictionary_dtcg_acceptance:
  recorded_at: "YYYY-MM-DDTHH:MM:SS+02:00"
  owner: "name-or-team"
  correction_owner: "name-or-team"
  style_dictionary_version: "resolved-v5-version"
  node_version: "resolved-v22-or-later-version"
  dtcg_target: "named-report-or-not-claimed"
  documented_support_status: "supported | partial | unknown"

  input:
    mode: "documented-dtcg-properties | legacy"
    source_path: "tokens.json"
    source_hash: "algorithm:value"
    syntax_review: "pass | revise | block"

  execution:
    operation: "direct-ingestion | legacy-conversion | platform-build"
    entry_point: "exact-command-or-function"
    conversion_options:
      applyTypesToGroup: "true | false | not-applicable"
    configuration_path: "style-dictionary.config.js"
    configuration_hash: "algorithm:value"
    transform_group: "css"
    format: "css/variables"
    filter: "none"
    output_references: true
    show_file_header: false
    warnings: []

  trace:
    source_token: "color.action.primary"
    source_type_expected: "inherited color"
    processed_type_observed: "unrecorded"
    source_value_expected: "{color.base.indigo}"
    source_value_observed: "unrecorded"
    resolved_value_expected: "#4f46e5"
    resolved_value_observed: "unrecorded"
    output_file: "build/tokens.css"
    base_symbol_expected: "--color-base-indigo"
    base_symbol_observed: "unrecorded"
    semantic_symbol_expected: "--color-action-primary"
    semantic_symbol_observed: "unrecorded"
    emitted_reference_expected: "var(--color-base-indigo)"
    emitted_reference_observed: "unrecorded"

  consumers:
    - name: "primary-button"
      mode_and_state: "light/default"
      test_content: "button with a visible label"
      expected: "background uses --color-action-primary"
      observed: "unrecorded"
      evidence: "path, test, or capture ID"
      failure_condition: "another value wins without an approved exception"

  exceptions: []
  disposition: "accept | revise | block"
  rationale: "state only what the collected evidence proves"
Copyable acceptance record

Choose accept when the selected operation matches its contract, required warnings have dispositions, both expected symbols appear in the reviewed artifact, the alias behavior matches the configuration, and every named consumer in scope shows the expected result. Use revise when the route is viable but a specific source, option, transform, format, or consumer correction remains. Reserve block for cases where a required construct is unsupported, references can't resolve reliably, collision precedence is unknown, or the emitted artifact contradicts the approved design decision.

Validation is another evidence layer

A DTCG validator can report whether a fixture passed the checks it implements for a stated target. That result doesn't replace Style Dictionary ingestion, conversion, platform emission, or consumer inspection.

Keep the product boundary explicit

Identity Forge ships DTCG token exports for developer handoff. An export can serve as the authoritative upstream input to this workflow, but it doesn't imply a native Style Dictionary integration or guaranteed compatibility with an arbitrary release, configuration, transform set, component library, or application.

The consuming project owns its Style Dictionary version, runtime, configuration, source precedence, conversion options, transforms, formats, generated files, consumer mapping, tests, and adoption decision. Classify the input, pin those choices, and complete one source-to-consumer trace before adopting the full token set.

Sources

  • Design Tokens - Style Dictionary: Style Dictionary accepts DTCG or legacy token property syntax and documents aliases, metadata, source merging, and collision warnings.
  • Design Tokens Community Group - Style Dictionary: Style Dictionary has first-class DTCG support from version 4, warns that the 2025.10 format is not fully supported, and describes the limits of legacy conversion.
  • Design Tokens Community Group utility reference: The utility reference documents convertToDTCG, its type-placement option, and typeDtcgDelegate processing behavior.
  • Token utility reference: Style Dictionary provides DTCG-aware token-data utilities and identifies convertTokenData as the replacement for the deprecated flattenTokens utility.
  • Formats - Style Dictionary: Style Dictionary formats define generated files, including CSS variables, filtering, retained references, and file-header behavior.
  • Using the CLI | Style Dictionary: The Style Dictionary command-line interface provides the build command used to generate configured platform artifacts.
  • Migration Guidelines | Style Dictionary: Style Dictionary 5 requires Node.js 22 or later and changes reference handling to align its reference characters with the DTCG specification.
  • The design tokens spec (DTCG) explained: DTCG types, aliases, composite tokens, and uneven tool support create practical interoperability boundaries between sources and consumers.
  • Identity Forge: Identity Forge produces complete design kits and offers DTCG tokens as a developer handoff format.