{"id":"l-ds-2-4","courseId":"design-systems","lang":"en","kind":"lesson","summary":"Read and write design tokens in the DTCG 2025.10 JSON format, with types, groups, aliases and deprecation, so one token file can feed Figma, CSS and native apps.","html":"<p>CSS custom properties are a great way to <em>consume</em> tokens on the web, but they are a poor place to <em>store</em> them. The iOS app can’t read your stylesheet, Figma can’t import it, and a script that checks contrast across themes has to parse CSS to find the values. Northwind’s tokens live in JSON files instead, in the format defined by the Design Tokens Community Group (DTCG), and every platform’s code is generated from them.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">Where the format stands in 2026</h2>\n<p>The DTCG is a W3C Community Group with members from design tool makers and large design system teams. On 28 October 2025 it published the first stable version of its specification, <strong>2025.10</strong>, made of three modules: Format, Color, and a Resolver module for combining sets and themes.</p>\n<p>Be precise when you describe it to others. It is a stable Community Group report, not a W3C Recommendation; Community Groups don’t produce formal web standards. In practice it is the format tools converge on: Style Dictionary, Tokens Studio and Terrazzo implement it, and Figma imports and exports variables as DTCG JSON. Support for the newer parts, such as the object color format and the Resolver module, still varies between tools, so check what your pipeline actually reads before adopting a feature.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Anatomy of a token file</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"json\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">tokens/primitives.tokens.json</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"color\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"$type\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"color\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"blue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"600\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">        \"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"colorSpace\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"srgb\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"components\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.122</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.353</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.878</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"hex\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"#1f5ae0\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">        \"$description\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Northwind brand blue. Passes 4.5:1 on white.\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"white\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"colorSpace\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"srgb\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"components\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"hex\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"#ffffff\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"space\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"$type\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"dimension\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"4\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"unit\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rem\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>Read it from the outside in:</p>\n<ul>\n<li><strong>Groups</strong> are plain nested objects (<code dir=\"ltr\">color</code>, <code dir=\"ltr\">blue</code>, <code dir=\"ltr\">space</code>). They organize tokens and form the path used in references.</li>\n<li>A <strong>token</strong> is any object with a <code dir=\"ltr\">$value</code>. Here, <code dir=\"ltr\">color.blue.600</code> and <code dir=\"ltr\">space.4</code> are tokens.</li>\n<li><strong><code dir=\"ltr\">$type</code></strong> declares what kind of value the token holds. Set on a group, it is inherited by every token inside, which is why <code dir=\"ltr\">color</code> declares it once.</li>\n<li><strong><code dir=\"ltr\">$description</code></strong> is free text that tools show in pickers and documentation.</li>\n</ul>\n<p>Properties starting with <code dir=\"ltr\">$</code> are reserved for the format, so token and group names can’t start with <code dir=\"ltr\">$</code>. Names also can’t contain <code dir=\"ltr\">{</code>, <code dir=\"ltr\">}</code> or <code dir=\"ltr\">.</code>, because those characters belong to the reference syntax.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">Types and value shapes</h2>\n<p>Each type has a fixed value shape. The ones you will use daily:</p>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"Scrollable table\" tabindex=\"0\"><table><thead>\n<tr>\n<th><code dir=\"ltr\">$type</code></th>\n<th>Example <code dir=\"ltr\">$value</code></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code dir=\"ltr\">color</code></td>\n<td><code dir=\"ltr\">{ &quot;colorSpace&quot;: &quot;srgb&quot;, &quot;components&quot;: [1, 1, 1], &quot;hex&quot;: &quot;#ffffff&quot; }</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">dimension</code></td>\n<td><code dir=\"ltr\">{ &quot;value&quot;: 16, &quot;unit&quot;: &quot;px&quot; }</code> (unit is <code dir=\"ltr\">px</code> or <code dir=\"ltr\">rem</code>)</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">duration</code></td>\n<td><code dir=\"ltr\">{ &quot;value&quot;: 150, &quot;unit&quot;: &quot;ms&quot; }</code> (unit is <code dir=\"ltr\">ms</code> or <code dir=\"ltr\">s</code>)</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">fontWeight</code></td>\n<td><code dir=\"ltr\">600</code> or <code dir=\"ltr\">&quot;semi-bold&quot;</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">number</code></td>\n<td><code dir=\"ltr\">1.5</code></td>\n</tr>\n</tbody>\n</table></div><p>There are also <code dir=\"ltr\">fontFamily</code> and <code dir=\"ltr\">cubicBezier</code>, plus composite types that bundle several values: <code dir=\"ltr\">typography</code>, <code dir=\"ltr\">shadow</code>, <code dir=\"ltr\">border</code>, <code dir=\"ltr\">transition</code>, <code dir=\"ltr\">gradient</code> and <code dir=\"ltr\">strokeStyle</code>.</p>\n<p>The color object is new in 2025.10. Earlier drafts, and many token files in the wild, store a plain hex string. The object form can describe colors outside sRGB, such as <code dir=\"ltr\">display-p3</code> or <code dir=\"ltr\">oklch</code>, which is why it replaced the string. Keep the optional <code dir=\"ltr\">hex</code> for tools that only understand sRGB.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Letting a tool guess the type</span></p>\n<p>A token with no <code dir=\"ltr\">$type</code> anywhere up its tree is invalid, even if its value looks obviously like a color. The format deliberately forbids inference, because <code dir=\"ltr\">&quot;16&quot;</code> could be a number, a font size or a z-index. Put <code dir=\"ltr\">$type</code> on your top-level groups and you rarely have to think about it again.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">Aliases</h2>\n<p>The semantic tier from earlier lessons lives in the same format, as references:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"json\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">tokens/semantic.tokens.json</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"color\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"$type\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"color\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"action\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"bg\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"{color.blue.600}\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"text\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"{color.white}\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"bg-hover\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"{color.blue.700}\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"bg-dark\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">        \"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"{color.blue.700}\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">        \"$deprecated\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Use color.action.bg-hover instead. Removed in 5.0.\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>A curly-brace reference names a token by its path with dots and resolves to that token’s whole <code dir=\"ltr\">$value</code>. It must point at a token, never at a group. References can chain (semantic → primitive), and a tool must reject circular ones. For the rare case where you need one part of a value, such as a single color component, the format also supports JSON Pointer references with <code dir=\"ltr\">$ref</code>.</p>\n<p>Here is the core of what every token tool does with aliases:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"2\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> tokens</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  color: {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    $type: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'color'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    blue: { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">600</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { $value: { colorSpace: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'srgb'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, components: [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.122</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.353</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.878</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], hex: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'#1f5ae0'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } } },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    action: {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      bg: { $value: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'{color.blue.600}'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">      'bg-subtle'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { $value: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'{color.action.bg}'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">};</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> lookup</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">path</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> node</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> path.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">split</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'.'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">reduce</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">n</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">key</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> n?.[key], tokens);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">node </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">||</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> !</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'$value'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> node)) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">throw</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> new</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> Error</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">`{${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">path</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">}} is not a token`</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> node;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> resolve</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">path</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">seen</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> []) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (seen.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">includes</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(path)) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">throw</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> new</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> Error</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">`circular reference: ${</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">[</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">seen</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">, </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">path</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">].</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">join</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">' -> '</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">}`</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$value</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> lookup</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(path);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> ref</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> typeof</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> $value </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">===</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> 'string'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x26;&#x26;</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> $value.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">match</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">/</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">^</span><span style=\"color:#116329;--shiki-light-font-weight:bold;--shiki-dark:#7EE787;--shiki-dark-font-weight:bold\">\\{</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">)</span><span style=\"color:#116329;--shiki-light-font-weight:bold;--shiki-dark:#7EE787;--shiki-dark-font-weight:bold\">\\}</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">$</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">/</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> ref </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> resolve</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(ref[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], [</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">seen, path]) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> $value;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">resolve</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'color.action.bg-subtle'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).hex);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">try</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">resolve</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'color.action'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">); } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">catch</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (e) { console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(e.message); }</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<h2 id=\"sec-5\" tabindex=\"-1\">Two more features worth knowing</h2>\n<p><code dir=\"ltr\">$deprecated</code>, shown above on <code dir=\"ltr\">bg-dark</code> (a name that describes a look, which the naming lesson warned against), marks a token as on its way out. Its value is <code dir=\"ltr\">true</code> or a string explaining what to use instead, and tools can warn when someone picks it. You’ll build a deprecation process around it in Section 4.</p>\n<p>Groups can also inherit from other groups with <code dir=\"ltr\">$extends</code>, overriding only what differs. That is handy for a Tidewater group that reuses most of Northwind’s structure. For full light, dark and brand combinations, the Resolver module defines how separate token sets and modifiers combine, but it is the newest part of the specification, so Northwind still assembles themes in its build pipeline. The recommended file extensions are <code dir=\"ltr\">.tokens</code> and <code dir=\"ltr\">.tokens.json</code>; Northwind uses the second so editors highlight the files as JSON.</p>\n<p>In the exercise below, you review a token file the way a pipeline would and find the lines it rejects. Next, you build that pipeline.</p>\n","toc":[{"id":"sec-1","text":"Where the format stands in 2026","level":2},{"id":"sec-2","text":"Anatomy of a token file","level":2},{"id":"sec-3","text":"Types and value shapes","level":2},{"id":"sec-4","text":"Aliases","level":2},{"id":"sec-5","text":"Two more features worth knowing","level":2}],"takeaways":["The DTCG format stores tokens as JSON objects with a <code dir=\"ltr\">$value</code>, and a <code dir=\"ltr\">$type</code> set on the token or inherited from its group.","Aliases use curly braces with dot-separated paths, such as <code dir=\"ltr\">{color.blue.600}</code>, and must point at a token, not a group.","Since 2025.10 a color value is an object with <code dir=\"ltr\">colorSpace</code> and <code dir=\"ltr\">components</code>, with an optional <code dir=\"ltr\">hex</code> fallback.","Version 2025.10 is the first stable release of a W3C Community Group report, not a W3C Recommendation, and tool support still varies."],"further":[{"title":"Design Tokens specification reaches first stable version (W3C Community Group)","url":"https://www.w3.org/community/design-tokens/2025/10/28/design-tokens-specification-reaches-first-stable-version/"},{"title":"Design Tokens Community Group repository","url":"https://github.com/design-tokens/community-group"},{"title":"Modes for variables, including importing and exporting tokens (Figma)","url":"https://help.figma.com/hc/en-us/articles/15343816063383-Modes-for-variables"}],"quiz":[{"q":"<p>What does <code dir=\"ltr\">{color.action}</code> resolve to in this file?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"json\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JSON</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">  \"color\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"$type\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"color\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">    \"action\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: {</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"bg\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"{color.blue.600}\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#116329;--shiki-dark:#7EE787\">      \"text\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: { </span><span style=\"color:#116329;--shiki-dark:#7EE787\">\"$value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"{color.white}\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"The value of <code dir=\"ltr\">color.action.bg</code>, because it is the first token in the group.","why":"The format has no “first token” rule; a reference must name one token exactly."},{"text":"An object containing both <code dir=\"ltr\">bg</code> and <code dir=\"ltr\">text</code>.","why":"Curly-brace references only resolve to a single token’s <code dir=\"ltr\">$value</code>, never to a whole group."},{"text":"The string “color”.","why":"The group’s <code dir=\"ltr\">$type</code> is inherited by its tokens; it isn’t a value a reference can return."},{"text":"Nothing valid; <code dir=\"ltr\">color.action</code> is a group, so the reference is an error.","why":"Correct. References must target a token, an object with a <code dir=\"ltr\">$value</code>."}],"answer":3},{"q":"<p>A token has no <code dir=\"ltr\">$type</code>, and neither does any group above it. Its value is <code dir=\"ltr\">&quot;#1f5ae0&quot;</code>. What must a conforming tool do?</p>","options":[{"text":"Infer that it is a color from the <code dir=\"ltr\">#</code> prefix.","why":"The format forbids guessing types from values, because the same string can mean different things to different tools."},{"text":"Treat the token as invalid.","why":"Correct. Every token needs an explicit type, either on itself, inherited from a group, or from the token it aliases."},{"text":"Treat it as a string token.","why":"String is not a type in the format; tools can’t fall back to it silently."}],"answer":1},{"q":"<p>A teammate says, “DTCG is a W3C standard now, so every tool reads every feature.” What’s the accurate correction?</p>","options":[{"text":"It is a stable Community Group report, not a W3C Recommendation, and tools implement it at different speeds.","why":"Correct. Stability means the format won’t change under you; it doesn’t guarantee every tool supports every type or the resolver yet."},{"text":"It is still an early draft that no tool supports.","why":"The 2025.10 release is stable, and Style Dictionary, Tokens Studio, Terrazzo and Figma’s variable import and export support it."},{"text":"It is a W3C Recommendation, but only for color tokens.","why":"It isn’t a Recommendation at all, and it covers many types beyond color."},{"text":"It replaces CSS custom properties in browsers.","why":"The format is an interchange file for tools; browsers still consume CSS that a pipeline generates from it."}],"answer":0}],"exercise":{"kind":"spot-bug","language":"json","code":"{\n  \"color\": {\n    \"$type\": \"color\",\n    \"blue\": {\n      \"600\": { \"$value\": { \"colorSpace\": \"srgb\", \"components\": [0.122, 0.353, 0.878], \"hex\": \"#1f5ae0\" } },\n      \"700\": { \"$value\": { \"colorSpace\": \"srgb\", \"components\": [0.094, 0.282, 0.722], \"hex\": \"#1848b8\" } }\n    },\n    \"white\": { \"$value\": { \"colorSpace\": \"srgb\", \"components\": [1, 1, 1], \"hex\": \"#ffffff\" } },\n    \"action\": {\n      \"bg\": { \"$value\": \"{color.blue.600}\" },\n      \"bg.hover\": { \"$value\": \"{color.blue.700}\" },\n      \"text\": { \"$value\": \"{color.white}\" },\n      \"border\": { \"$value\": \"{color.blue}\" }\n    }\n  },\n  \"space\": {\n    \"$type\": \"dimension\",\n    \"inset-md\": { \"$value\": { \"value\": 16 } },\n    \"inset-lg\": { \"$value\": { \"value\": 24, \"unit\": \"px\" } }\n  },\n  \"radius\": {\n    \"control\": { \"$value\": { \"value\": 6, \"unit\": \"px\" } }\n  }\n}","bugLines":[11,13,18,22],"title":"Find what the pipeline will reject","prompt":"<p>Northwind’s CI validates every token file against the DTCG 2025.10 format before building. This file fails. Select <strong>every line</strong> that a conforming tool would reject. Assume the rest of the file, including the color values, is correct.</p>\n","hints":["Check every name for characters the reference syntax reserves.","Check every reference: does it point at a token (an object with <code dir=\"ltr\">$value</code>) or at a group?","Check every token’s type: is it declared on the token or a parent group, and does the value have every required field?"],"explanation":"<p>Four lines break the format:</p>\n<ul>\n<li><strong>Line 11</strong>: <code dir=\"ltr\">bg.hover</code> contains a period, which is reserved for reference paths. Rename it <code dir=\"ltr\">bg-hover</code>.</li>\n<li><strong>Line 13</strong>: <code dir=\"ltr\">{color.blue}</code> points at a group, not a token. It needs a specific step, such as <code dir=\"ltr\">{color.blue.700}</code>.</li>\n<li><strong>Line 18</strong>: a <code dir=\"ltr\">dimension</code> value must include a <code dir=\"ltr\">unit</code> (<code dir=\"ltr\">px</code> or <code dir=\"ltr\">rem</code>), even when the meaning seems obvious: <code dir=\"ltr\">{ &quot;value&quot;: 16, &quot;unit&quot;: &quot;px&quot; }</code>.</li>\n<li><strong>Line 22</strong>: <code dir=\"ltr\">radius.control</code> has no <code dir=\"ltr\">$type</code>, and neither does the <code dir=\"ltr\">radius</code> group, so the token is invalid. Add <code dir=\"ltr\">&quot;$type&quot;: &quot;dimension&quot;</code> to the <code dir=\"ltr\">radius</code> group.</li>\n</ul>\n","checkLabels":{}},"words":772,"readMinutes":4}