Skip to content

tokens.json

Your tokens.json (or tokens.yaml) file is a complete manifest of all your design tokens. It follows the Design Token Community Group format (DTCG), an official standard for describing design tokens.

The format is currently in draft, and being developed by hundreds of design leaders that work at Figma, Adobe, Salesforce, Google, Amazon, Microsoft, Zeplin, Supernova, and more! But despite it still being a draft, it’s still a robust format and is becoming the de-facto standard for design tokens, and many popular design systems like GitHub Primer either have switched to DTCG or are planning to in the near future.

DTCG Format

The basic design token consists of a simple JSON object with $type and $value (required), as well as an optional $description (highly-recommended to use to describe the token’s purpose, as well as usage instructions).

json
{
  "tokenName": {
    "$description": "(optional) A description of this token",
    "$type": "[token type]",
    "$value": "[token value - different shape depending on $type]",
    "$extensions": "(optional) Used by third-party tools"
  }
}
yaml
tokenName:
  $description: (optional) A description of this token
  $type: "[token type]"
  $value: "[token value - different shape depending on $type]"
  $extensions: (optional) Used by third-party tools

Tokens can also be nested infinitely within other groups. A group counts as any arbitrary object wrapping the token (note that $ prefixes are reserved for tokens, to prevent name conflicts):

json
{
  "groupA": {
    "groupB": {
      "token": {
        "$type": "color",
        "$value": "#000"
      }
    }
  }
}
yaml
groupA:
  groupB:
    token:
      $type: color
      $value: "#000"

Managing tokens.json

Currently, the only way to manage tokens.json is manually. But there are tools to make editing friendlier, such as JSON Hero.

TIP

The Cobalt team is working on a visual GUI for editing/managing tokens, but it’s not ready yet. We’re planning on announcing it in early 2024.

Token Types

Within your tokens.json, you can use all of the following types of tokens:

And in addition to these, you can also group tokens in any hierarchy you’d like, as well as create your own custom tokens.

Cobalt extensions

Cobalt is NOT its own format; it is an implementation of DTCG as close to the spec as possible. However, just for quality of life, Cobalt supports a superset to DTCG, allowing:

  • Addition of a Link token for assets
  • YAML is supported in addition to JSON
  • Wider support for more values are expected, such as:
    • Color: any CSS-valid color is accepted, including Oklab/Oklch (the spec requires sRGB Hexadecimal)
    • Shadow: arrays of shadows are accepted (the spec only allows one shadow)
    • Typography: any CSS text property is accepted (the spec doesn’t allow things like font-variant).
  • Modes are allowed.

Any other deviations are considered unintentional. Please file an issue if you run across any!

JSON or YAML?

Though the original DTCG spec (and most examples) use JSON, Cobalt supports YAML equally well since it’s a 1:1 translation. But since YAML is an easier format to read and write, you may prefer it (the Cobalt maintainers do!). Wherever you see mention of tokens.json, know that Cobalt supports tokens.yaml equally well; the former is just used as the common term for simplicity.

Tip: Boop is a simple, secure tool to convert JSON to YAML in a snap.

Combining multiple tokens.json files

With Cobalt, you can organize your tokens into separate files if you’d like, and they can all be flattened together. Pass in an array to tokens in your config:

js
/** @type {import("@cobalt-ui/core").Config} */
export default {
  tokens: ["./token-src/colors.json", "./token-src/typography.json", "./token-src/icons.json", "./token-src/spacing.json"],
};

Note that this will flatten all tokens into one manifest, so you’ll have to handle conflicts if multiple tokens are named the same thing (including their groups).

Naming / organization

Organization is completely up to you! The DTCG spec allows infinite nesting, and lets you name tokens anything, with the following exceptions:

  • Token names or group names can’t …
    • … contain dots (.). These are reserved for shorthand IDs (e.g. color.base.blue.500).
    • … contain curly braces ({}). These are reserved for aliases (e.g. {color.base.blue.500}).
    • … start with $. These are reserved properties (e.g. $type).
  • Tokens can’t contain sub-tokens (an object is either a token or a group, but never both).

Best practices

Based on looking at dozens of design systems, here are a few tips and common patterns that we’ve seen:

  • Favor predictability. For naming colors, color.red is better than color.crimson. Expand into more “creative” only after you’ve exhausted the predictable names.
  • Use aliasing. You can create as many aliases as you’d like. For example, you could set color.brand.primary, color.semantic.action, and color.semantic.info all to {color.base.blue.500} and only have to manage one color instead of multiple.
  • Group tokens by type. Most DSs contain obvious top-level groups such as color.*, border.*, font.*, and space.*. As you develop more semantic groups, you can always alias back to these tokens.
  • Dedupe types. Groups let you set the default $type that apply to all children. So set "$type": "color" on your color.* group once to save typing on all child tokens (this also encourages good organization!).
  • Set descriptions. Tokens and groups all support adding $descriptions. Take the time to describe how this token should (or shouldn’t) be used!

Further Reading