Deep Dive: DTCG 1.0 Structured Formats

Why Follow DTCG?

The W3C Design Tokens Community Group (DTCG) 1.0 specification defines a standard format for design tokens that enables interoperability between tools, platforms, and organizations. By following this specification, our tokens work with Figma, Style Dictionary, Tokens Studio, and any other DTCG-compliant tool.

More importantly, DTCG mandates structured object formats instead of simple strings. This enables type safety, platform flexibility, and scalable theming that wouldn't be possible with primitive string values.

Token Anatomy

Every DTCG token is an object with specific properties:

{
  "tokenName": {
    "$type": "color",                    // Required: token type
    "$value": "#0a65fe",                 // Required: token value
    "$description": "Primary brand blue", // Optional: documentation
    "$extensions": {                     // Optional: custom metadata
      "design.paths.dark": "#4d9fff"
    }
  }
}
PropertyRequiredPurpose
$typeYesDeclares the token's data type for validation
$valueYesThe token's value (format depends on type)
$descriptionNoHuman-readable documentation
$extensionsNoCustom metadata (theming, platform variants)

DTCG Type System

DTCG defines a fixed set of token types. Each type has specific value format requirements:

TypeValue FormatExample
colorHex string or color object"#0a65fe"
dimensionNumber with unit (px, rem)"16px"
numberUnitless number1.5
durationTime with unit (ms, s)"250ms"
cubicBezierArray of 4 numbers[0.4, 0, 0.2, 1]
fontFamilyString or array of strings"Inter, sans-serif"
fontWeightNumber or keyword700 or "bold"
typographyComposite objectSee below
shadowComposite objectSee below
borderComposite objectSee below

Color Values

Colors can be specified as hex strings or structured objects. We primarily use hex strings for simplicity, but structured objects enable advanced color space support.

Hex String (Simple)

{
  "$type": "color",
  "$value": "#0a65fe"
}

Structured Color Object

For advanced use cases, DTCG supports structured color objects with explicit color space and components:

{
  "$type": "color",
  "$value": {
    "colorSpace": "srgb",
    "components": [0.04, 0.4, 0.996]
  }
}

Modern Color Spaces

Structured objects support modern color spaces like OKLCH for better perceptual uniformity:

{
  "$type": "color",
  "$value": {
    "colorSpace": "oklch",
    "components": [0.65, 0.25, 240]
  },
  "$description": "OKLCH blue - perceptually uniform"
}

Color with Alpha

// Hex with alpha
{
  "$type": "color",
  "$value": "#0a65fe80"  // 50% opacity
}

// Structured with alpha
{
  "$type": "color",
  "$value": {
    "colorSpace": "srgb",
    "components": [0.04, 0.4, 0.996],
    "alpha": 0.5
  }
}

Dimension Values

Dimensions represent spatial values with units. DTCG 1.0 restricts units to px and rem for consistency.

// Pixel dimension
{
  "$type": "dimension",
  "$value": "16px"
}

// Relative dimension
{
  "$type": "dimension",
  "$value": "1rem"
}

// Zero (no unit required)
{
  "$type": "dimension",
  "$value": "0"
}

Dimension vs Number

Use dimension for spatial values that need units. Use number for unitless values like line-height multipliers:

// Dimension: has unit
{
  "fontSize": {
    "$type": "dimension",
    "$value": "16px"
  }
}

// Number: unitless multiplier
{
  "lineHeight": {
    "$type": "number",
    "$value": 1.5
  }
}

Composite Tokens

Complex tokens like typography and shadows combine multiple values into a single token. These are called composite tokens.

Typography Composite

{
  "$type": "typography",
  "$value": {
    "fontFamily": "{core.typography.family.inter}",
    "fontSize": "16px",
    "fontWeight": 400,
    "lineHeight": 1.5,
    "letterSpacing": "0em"
  },
  "$description": "Body text style"
}

Shadow Composite

{
  "$type": "shadow",
  "$value": {
    "offsetX": "0px",
    "offsetY": "4px",
    "blur": "8px",
    "spread": "0px",
    "color": "#00000014"
  },
  "$description": "Subtle elevation shadow"
}

Border Composite

{
  "$type": "border",
  "$value": {
    "color": "{semantic.color.border.default}",
    "width": "1px",
    "style": "solid"
  },
  "$description": "Standard border"
}

Token References

Tokens can reference other tokens using the {token.path} syntax. This creates a graph of dependencies that the build system resolves.

// Core token (leaf node)
{
  "palette": {
    "blue": {
      "500": {
        "$type": "color",
        "$value": "#0a65fe"
      }
    }
  }
}

// Semantic token (references core)
{
  "background": {
    "brand": {
      "$type": "color",
      "$value": "{core.color.palette.blue.500}"
    }
  }
}

Reference Resolution

References are resolved at build time. The build system follows the reference chain and substitutes the final value:

// Source
semantic.color.background.brand = "{core.color.palette.blue.500}"

// Resolved
semantic.color.background.brand = "#0a65fe"

Extensions for Advanced Features

The $extensions property provides custom metadata for features beyond the DTCG spec. We use it for theming and calculations.

Theme-Specific Overrides

{
  "$type": "color",
  "$value": "{core.color.palette.neutral.600}",
  "$extensions": {
    "design.paths.light": "{core.color.palette.neutral.600}",
    "design.paths.dark": "{core.color.palette.neutral.300}"
  }
}

CSS Calculations

{
  "$type": "dimension",
  "$value": "16px",
  "$extensions": {
    "design.calc": "calc({core.spacing.size.04} + 2px)"
  }
}

Pitfalls to Avoid

1. Wrong Type for Value

The $type must match the $value format. Mismatches cause validation errors.

// BAD: Type/value mismatch
{
  "$type": "dimension",
  "$value": "#0a65fe"  // Color value with dimension type!
}

// GOOD: Matching type and value
{
  "$type": "color",
  "$value": "#0a65fe"
}

2. Missing Units on Dimensions

Dimensions require units (except zero). Numbers are for unitless values.

// BAD: Dimension without unit
{
  "$type": "dimension",
  "$value": "16"  // Missing unit!
}

// GOOD: Dimension with unit
{
  "$type": "dimension",
  "$value": "16px"
}

// GOOD: Zero doesn't need unit
{
  "$type": "dimension",
  "$value": "0"
}

3. Invalid Unit Types

DTCG 1.0 only allows px and rem for dimensions. Other units like em, %, or vh are not valid.

// BAD: Invalid units
{
  "$type": "dimension",
  "$value": "1em"     // em not allowed
}
{
  "$type": "dimension",
  "$value": "100%"    // % not allowed
}

// GOOD: Valid units
{
  "$type": "dimension",
  "$value": "16px"
}
{
  "$type": "dimension",
  "$value": "1rem"
}

4. Circular References

References cannot form cycles. The validator catches these at build time.

// BAD: Circular reference
{
  "primary": { "$value": "{semantic.color.secondary}" },
  "secondary": { "$value": "{semantic.color.primary}" }
}

// GOOD: Linear reference chain
{
  "primary": { "$value": "{core.color.palette.blue.500}" },
  "secondary": { "$value": "{core.color.palette.blue.400}" }
}

5. Referencing Non-Existent Tokens

References must point to tokens that exist. Typos in paths cause build failures.

// BAD: Typo in reference
{
  "$value": "{core.color.pallete.blue.500}"  // "pallete" typo!
}

// GOOD: Correct path
{
  "$value": "{core.color.palette.blue.500}"
}

Build System Integration

Our build pipeline transforms DTCG tokens into platform-specific formats:

DTCG FormatCSS OutputTypeScript Output
#0a65fe#0a65fe'#0a65fe'
16px16px'16px'
250ms250ms'250ms'
[0.4, 0, 0.2, 1]cubic-bezier(0.4, 0, 0.2, 1)[0.4, 0, 0.2, 1]
Typography compositeMultiple CSS propertiesTyped object

Summary

  • DTCG 1.0 provides a standard format for interoperability
  • Every token has $type and $value; $description and $extensions are optional
  • Colors can be hex strings or structured objects with color space
  • Dimensions require units (px, rem) except for zero
  • Composite tokens combine multiple values (typography, shadow, border)
  • References use {token.path} syntax and cannot be circular
  • Extensions enable theming and custom features beyond the spec

Next Steps

Understanding DTCG formats is foundational. From here, explore how the core vs semantic model uses these formats, how schema validation enforces them, and how the build pipeline transforms them into CSS and TypeScript.

← Back to Design Tokens