<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dmitry Bychinsky</title>
    <description>The latest articles on DEV Community by Dmitry Bychinsky (@dbychinsky).</description>
    <link>https://dev.to/dbychinsky</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3996542%2Ffc20247a-b7b4-41d3-a4b0-b2a5aabcf252.jpg</url>
      <title>DEV Community: Dmitry Bychinsky</title>
      <link>https://dev.to/dbychinsky</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dbychinsky"/>
    <language>en</language>
    <item>
      <title>An LLM Thinks in Tokens</title>
      <dc:creator>Dmitry Bychinsky</dc:creator>
      <pubDate>Wed, 01 Jul 2026 14:03:10 +0000</pubDate>
      <link>https://dev.to/dbychinsky/an-llm-thinks-in-tokens-464i</link>
      <guid>https://dev.to/dbychinsky/an-llm-thinks-in-tokens-464i</guid>
      <description>&lt;p&gt;When a person looks at an interface, they see an image: buttons, spacing, colors, and the overall mood of the layout. We rarely think about it: perceiving design through a picture feels completely natural.&lt;/p&gt;

&lt;p&gt;A language model has no such channel. It never looks at a screen. And that&lt;br&gt;
changes almost everything about how you should feed it a design.&lt;/p&gt;
&lt;h2&gt;
  
  
  Everything Becomes Numbers
&lt;/h2&gt;

&lt;p&gt;It is tempting to think that modern multimodal models solve the problem: since they can work with images, you could just give the model a screenshot and it would see the design the way a human does.&lt;/p&gt;

&lt;p&gt;But multimodality is beside the point. Whatever you feed the model, text, image, or sound, becomes numbers on the inside. The model never handles a picture as a picture. It handles a numeric representation of one.&lt;/p&gt;

&lt;p&gt;So the question isn't whether the model "sees" the design. It's which numeric representation the model ends up with.&lt;/p&gt;

&lt;p&gt;And this is where a screenshot falls short. An image becomes numbers that describe pixels: lighter here, darker there, an edge over here. From that, the model can roughly guess that the spacing is around sixteen pixels and the color is some kind of blue. But that's guesswork from a picture, not knowledge of the design.&lt;/p&gt;
&lt;h2&gt;
  
  
  Which Numbers, Exactly
&lt;/h2&gt;

&lt;p&gt;The difference is roughly like the difference between a photo of a book page and the text of the book itself.&lt;/p&gt;

&lt;p&gt;The text is in the photo too. But to use it, you first have to recognize the letters, piece the words back together, and work out where a paragraph starts and where that's just a shadow on the page. Working with the text directly skips all of that guesswork.&lt;/p&gt;

&lt;p&gt;Design works the same way. A screenshot, or even HTML with styles, makes the model reconstruct intent from form. But you can give it the intent directly, spelled out. That's what design tokens do.&lt;/p&gt;

&lt;p&gt;A design token isn't a pixel or a line of CSS. It's a meaningful value with a name: the primary action color, the surface background, the padding inside a card, the corner radius of a panel. Tokens describe design the way a team talks about it: not "this blue right here," but "the primary action color, used everywhere there's a primary action."&lt;/p&gt;

&lt;p&gt;As it happens, a language model's basic unit is also called a token. They're not the same thing: a model token is a chunk of text, a design token is a named design value. But they meet at the same point. Both are about turning meaning into a structure a machine can work with.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why HTML and CSS Are Noise
&lt;/h2&gt;

&lt;p&gt;You might object: HTML and CSS are text too, and the model reads them just fine. It does. The problem isn't that the model can't understand CSS. The problem is that HTML and CSS are full of things that have nothing to do with design.&lt;/p&gt;

&lt;p&gt;Markup, nesting, utility classes, layout wrappers, color values copied from a mockup by hand over and over. The design is in there, but it's buried in noise. To work out that the same color in three different places is one and the same "primary color," the model has to guess all over again.&lt;/p&gt;

&lt;p&gt;Tokens clear that noise away. What's left is just the design and the relationships between its parts, and the model no longer has to reconstruct anything.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Experiment: One Task, Two Paths
&lt;/h2&gt;

&lt;p&gt;Rather than argue in the abstract, we ran a small blind experiment.&lt;/p&gt;

&lt;p&gt;We gave the task to several independent agents running on the same model, split into two groups. The design task was the same for everyone: build a product card. Only the prompt differed.&lt;/p&gt;

&lt;p&gt;The first group got a straight assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a product card with an image, title, price, rating and a buy button.
Return the HTML and a separate CSS file.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second group got the exact same task, with one requirement added on top: describe the design in tokens first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a product card with an image, title, price, rating and a buy
button. Return the HTML and a separate CSS file.

Before writing the CSS, define design tokens in the DTCG format in
three layers: primitive (raw values), semantic (roles referencing primitives), 
and component (component values referencing semantics).
The component styles must reference the tokens and must not hardcode values.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing else differed between the groups. Neither group knew about the other approach or that the results would be compared. The difference was exactly one thing: whether the model had to build a design vocabulary first or could jump straight to markup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path One: Straight to HTML and CSS
&lt;/h3&gt;

&lt;p&gt;The first observation caught us off guard. Even in direct mode, a modern model doesn't write colors straight into properties. It pulls the values out into CSS variables on its own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--color-surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4f46e5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-accent-hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4338ca&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--radius-lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--radius-md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--shadow-card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the model largely settles the "variables versus magic numbers" debate by itself. But look closer and you can see where the direct approach still comes up short.&lt;/p&gt;

&lt;p&gt;First, each variable does double duty. &lt;code&gt;--color-accent&lt;/code&gt; is both a specific color from the palette and the "primary action" role. A single name answers two separate questions: "which color is this" and "what is it for." While those questions stay fused, you can't answer one without disturbing the other. Change the brand color in the palette, and you change the role along with it. Reassign the role to a different color, and you're back editing the same name. And nothing in the code tells you that a color and its hover variant are one brand color and its shade; that link lives only in the head of whoever wrote it.&lt;/p&gt;

&lt;p&gt;Second, some values still ended up hardcoded in the components: a &lt;code&gt;border-radius: 12px&lt;/code&gt; sitting next to a radius variable here, an &lt;code&gt;outline&lt;/code&gt; with a color written as a standalone &lt;code&gt;rgba(...)&lt;/code&gt; that ties back to nothing there.&lt;/p&gt;

&lt;p&gt;Third, and this is the big one: the independent runs didn't line up. Different variable names (&lt;code&gt;--color-accent&lt;/code&gt; versus &lt;code&gt;--color-primary&lt;/code&gt;), different radii (18px versus 16px), one generation added a button shadow and the others didn't. Each agent reinvented its own vocabulary. No shared language emerged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path Two: Tokens First
&lt;/h3&gt;

&lt;p&gt;The second mode looks different. The component styles hold no raw values at all, only references to tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-card-default-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-card-default-radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-card-default-shadow&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__price&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-card-price-color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-card-button-background&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card__button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--component-card-button-background-hover&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind those names sits a structure that pulls apart the two questions the direct version fused together. "Which color is this" lives in the primitives. "What is it for" lives in the semantics. A raw value shows up exactly once, in the primitives, and everything after that is references:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"primitive"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"indigo-600"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"colorSpace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"srgb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.275&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.898&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"hex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#4f46e5"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"indigo-500"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"colorSpace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"srgb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.388&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.945&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"hex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#6366f1"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"semantic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"action-primary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{primitive.color.indigo-600}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"action-primary-hover"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{primitive.color.indigo-500}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"component"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"primary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"background"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{semantic.color.action-primary}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"background-hover"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{semantic.color.action-primary-hover}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format is explicit and unambiguous: every token states its type, and a&lt;br&gt;
reference to another token is plain to both a human and a tool. The model parses a format like this without misreading it, because there's nothing left to guess.&lt;/p&gt;

&lt;p&gt;But the individual file isn't the interesting part; what happened across the independent runs is. Every agent in this mode built almost the same structure. Three levels: &lt;code&gt;primitive&lt;/code&gt;, &lt;code&gt;semantic&lt;/code&gt;, &lt;code&gt;component&lt;/code&gt;. The same roles: &lt;code&gt;surface&lt;/code&gt; for the background, &lt;code&gt;action&lt;/code&gt; for the primary action, &lt;code&gt;text-primary&lt;/code&gt; and &lt;code&gt;text-secondary&lt;/code&gt; for text, &lt;code&gt;rating&lt;/code&gt; for the rating. Different palettes, but the same skeleton.&lt;/p&gt;

&lt;p&gt;Different agents, the same task, and out came a consistent design vocabulary. The direct mode never got there.&lt;/p&gt;
&lt;h3&gt;
  
  
  What the Experiment Showed
&lt;/h3&gt;

&lt;p&gt;The experiment didn't measure whether the card comes out "prettier." All the variants look fine. It measured something else: how steadily and consistently the model describes the design.&lt;/p&gt;

&lt;p&gt;In direct mode the model pulls values into variables, but a variable name carries the color and its role together, and the vocabulary comes out different every run. In token mode color and role sit on separate levels, the component has no raw values, and independent runs converge on one vocabulary.&lt;/p&gt;

&lt;p&gt;The reason is the one already covered above. Tokens hand the model a way to think: base values first, then roles, then usage. That's closer to how the model works with data anyway, so the results come out more predictable.&lt;/p&gt;

&lt;p&gt;There's one more takeaway, about the format. The model builds the structure with confidence, but it slips on the fine points of DTCG itself. Not one token run was valid on the first try: in one, dimensions were written as a string instead of a value-and-unit pair; in another, the primitive groups weren't grouped by type. But that's precisely the kind of problem tooling handles (see &lt;a href="https://github.com/design-token-kit/design-token-kit" rel="noopener noreferrer"&gt;Design Token Kit&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;
  
  
  The Design Lifecycle: With and Without Tokens
&lt;/h2&gt;

&lt;p&gt;The difference doesn't show up at one moment, it runs through the whole life of a design.&lt;/p&gt;

&lt;p&gt;Creating. Without tokens, the model scatters values through the code, or through a list of variables where color and role are fused, and it drifts out of sync from one run to the next. With tokens it sets up a design vocabulary first and then draws on it, so decisions get reused instead of reinvented.&lt;/p&gt;

&lt;p&gt;Changing. Without tokens, "make the brand color darker" becomes a hunt across the whole project. With tokens it's one line in the primitives, and the change flows out to every place that references it.&lt;/p&gt;

&lt;p&gt;Theming. Without tokens, a dark theme is often written almost from scratch. With tokens a theme is just a different set of values for the same roles, and the structure stays put.&lt;/p&gt;

&lt;p&gt;Checking. Without tokens, it's hard even to say what counts as an error. With tokens the rules are clear: a reference points nowhere, a type doesn't match, a component reaches straight into a primitive and skips the semantics. All of that can be checked automatically.&lt;/p&gt;

&lt;p&gt;At every stage tokens give the model the same thing: an explicit structure instead of a guess from form.&lt;/p&gt;
&lt;h2&gt;
  
  
  Token Formats
&lt;/h2&gt;

&lt;p&gt;The same tokens can be written in more than one format. They don't differ in meaning, only in what the notation is optimized for.&lt;/p&gt;

&lt;p&gt;DTCG (Design Tokens Community Group) is developed by the group of the same name at the W3C as an industry standard for describing tokens. It's already the de facto reference, even though work on the spec is still underway. Its main purpose is interoperability: the same tokens should be understood by different tools, and themes should be buildable on top of them. As the format's site puts it, DTCG JSON unlocks interoperability and theming between tools. That makes it a common language, a design written in DTCG moves between editors, build steps, and documentation without being rewritten. This is the format we gave the model in the experiment.&lt;/p&gt;

&lt;p&gt;HRDT (Human-Readable Design Tokens) comes from the authors of design-token-kit, a more readable way to write the same tokens in YAML by hand. It's more compact than DTCG and round-trips to it without loss, so you can edit in YAML and still move tokens between tools in shared DTCG.&lt;/p&gt;

&lt;p&gt;DESIGN.md comes from Google: Markdown with tokens in the YAML frontmatter, which design-token-kit supports. It covers a subset of a design (colors, typography, spacing, corner radii, components) and works well for keeping a short description of the system next to the docs. Richer types, such as shadows and gradients, fall outside it.&lt;/p&gt;
&lt;h2&gt;
  
  
  design-token-kit
&lt;/h2&gt;

&lt;p&gt;Working with tokens is more than writing them: you have to check the structure, catch broken references, turn tokens into CSS, and see the result. &lt;a href="https://github.com/design-token-kit/design-token-kit" rel="noopener noreferrer"&gt;Design Token Kit&lt;/a&gt; handles all of that.&lt;/p&gt;

&lt;p&gt;It checks tokens, converts them, and builds a showcase. The DTCG tokens from the experiment are what we ran through it.&lt;/p&gt;

&lt;p&gt;Checking tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens check tokens.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converting to CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens convert &lt;span class="nt"&gt;--outform&lt;/span&gt; css &lt;span class="nt"&gt;--out&lt;/span&gt; tokens.css tokens.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generating a showcase page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens showcase &lt;span class="nt"&gt;--out&lt;/span&gt; showcase.html tokens.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converting between formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens convert &lt;span class="nt"&gt;--inform&lt;/span&gt; dtcg &lt;span class="nt"&gt;--outform&lt;/span&gt; hrdt &lt;span class="nt"&gt;--out&lt;/span&gt; tokens.yaml tokens.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A person takes in design through an image. A model takes it in through numbers, and the only question is how meaningful those numbers are.&lt;/p&gt;

&lt;p&gt;A screenshot, or even clean CSS, hands the model a design where the value and its meaning are fused and the links live only in the author's head. Design tokens hand it a structure instead: value on one side, role on the other, explicit references between them. In that form the model describes design far more consistently, which is what the experiment showed.&lt;/p&gt;

&lt;p&gt;Design tokens aren't just for people. They turn out to be a good fit for the model too. And Design Token Kit makes that language easy to speak, without the busywork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.designtokens.org/" rel="noopener noreferrer"&gt;DTCG - Design Tokens Community Group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google-labs-code/design.md" rel="noopener noreferrer"&gt;DESIGN.md - a format from Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/design-token-kit/design-token-kit" rel="noopener noreferrer"&gt;Design Token Kit on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>designsystem</category>
      <category>design</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Design Token Kit: A Practical Toolkit for Design Tokens</title>
      <dc:creator>Dmitry Bychinsky</dc:creator>
      <pubDate>Mon, 22 Jun 2026 09:53:18 +0000</pubDate>
      <link>https://dev.to/dbychinsky/design-token-kit-a-practical-toolkit-for-design-tokens-dpi</link>
      <guid>https://dev.to/dbychinsky/design-token-kit-a-practical-toolkit-for-design-tokens-dpi</guid>
      <description>&lt;p&gt;Design tokens help keep colors, spacing, radius values, shadows, and other UI values in one place. It sounds simple: you create a JSON file, and things get better. In real work, validation, links between tokens, CSS variables, themes, showcase pages, and manual editing quickly appear around this simple idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem we wanted to solve
&lt;/h2&gt;

&lt;p&gt;In the simplest form, design tokens can look like a normal set of values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"primary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#3366ff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"background"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#ffffff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#111111"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This format is easy to read, but it is not enough for a full tool. We need&lt;br&gt;
types, rules, structure, theme support, aliases, and a clear processing&lt;br&gt;
pipeline.&lt;/p&gt;

&lt;p&gt;In a real project, questions appear very quickly: how to validate the token structure, how to make the format easy to edit by hand, how to convert tokens to CSS, and how to show the result on a static HTML page.&lt;/p&gt;

&lt;p&gt;We wanted to make a small and clear tool that covers the basic workflow:&lt;br&gt;
describe tokens, validate them, convert them to CSS, and view the result in a showcase.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Design Token Kit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/design-token-kit/design-token-kit" rel="noopener noreferrer"&gt;&lt;strong&gt;Design Token Kit&lt;/strong&gt;&lt;/a&gt; is an npm tool for working with design tokens.&lt;/p&gt;

&lt;p&gt;It helps you go from a token file to a result that can already be used in a project: check the structure, find errors, generate CSS variables, and build a simple HTML page for viewing tokens in a browser.&lt;/p&gt;

&lt;p&gt;The idea was not to create a large platform for design systems with everything inside. We wanted to build a clear tool: validation, conversion, and visual review.&lt;/p&gt;
&lt;h2&gt;
  
  
  DTCG JSON support
&lt;/h2&gt;

&lt;p&gt;For the main JSON format, we decided to use &lt;a href="https://www.designtokens.org/" rel="noopener noreferrer"&gt;DTCG&lt;/a&gt;, the format from the Design Tokens Community Group. The idea is to describe design tokens in a predictable way and move them between different tools without many custom rules.&lt;/p&gt;

&lt;p&gt;In DTCG, a token is not just a value. It is an object with a clear structure. For example, a color token can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"$type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"primary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"colorSpace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"srgb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"components"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"hex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#3366ff"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This format is longer than a simple JSON file with colors, but it is easier for a tool to work with it. The tool can see the token type, check the structure, process references, find errors, and then safely use this data for conversion.&lt;/p&gt;

&lt;p&gt;In Design Token Kit, DTCG JSON is one of the main input formats. It can be&lt;br&gt;
validated, converted to CSS custom properties, converted to another format, and used to generate a showcase.&lt;/p&gt;

&lt;p&gt;There is also an obvious downside: writing this JSON by hand is not always&lt;br&gt;
comfortable.&lt;/p&gt;

&lt;p&gt;When there are many tokens, themes, aliases, and nested groups, the file quickly becomes large. That is why we added a more compact format for manual editing together with DTCG JSON: HRDT YAML.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why we needed HRDT YAML
&lt;/h2&gt;

&lt;p&gt;HRDT means &lt;strong&gt;Human-Readable Design Tokens&lt;/strong&gt;. Its goal is to make token files more compact and easier for people to read, but still keep the same processing pipeline.&lt;/p&gt;

&lt;p&gt;It is not always convenient to write &lt;code&gt;$type&lt;/code&gt;, &lt;code&gt;$value&lt;/code&gt;, &lt;code&gt;colorSpace&lt;/code&gt;, &lt;code&gt;components&lt;/code&gt;, and several levels of nesting when you only need to add a new color or change a spacing value.&lt;/p&gt;

&lt;p&gt;In HRDT YAML, the same set of tokens can look much simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;primitive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#ffffff"&lt;/span&gt;
    &lt;span class="na"&gt;brand-500&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#2549f6"&lt;/span&gt;

&lt;span class="na"&gt;semantic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;background-page&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{primitive.color.white}"&lt;/span&gt;
    &lt;span class="na"&gt;action-primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{primitive.color.brand-500}"&lt;/span&gt;

&lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{semantic.color.action-primary}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file is easier to read, easier to edit, and easier to discuss with the team. Fewer brackets also mean fewer chances to get lost. YAML does not pretend to save the world, but for writing tokens by hand it is much more convenient.&lt;/p&gt;

&lt;p&gt;In real project files, HRDT is built around three top levels: &lt;code&gt;primitive&lt;/code&gt;, &lt;code&gt;semantic&lt;/code&gt;, and &lt;code&gt;component&lt;/code&gt;. &lt;code&gt;primitive&lt;/code&gt; stores base values. &lt;code&gt;semantic&lt;/code&gt; describes roles like background, text, or spacing. &lt;code&gt;component&lt;/code&gt; connects these roles to specific parts of the interface. Because of this, the structure shows where the base values are, where the meaning is, and where component settings are.&lt;/p&gt;

&lt;p&gt;At the same time, HRDT YAML does not replace DTCG JSON. Inside the tool, YAML is converted to the common token model and then goes through the same path: &lt;strong&gt;checking&lt;/strong&gt;, CSS &lt;strong&gt;conversion&lt;/strong&gt;, and **showcase **generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: core and cli
&lt;/h2&gt;

&lt;p&gt;We split the project into two parts: &lt;code&gt;@design-token-kit/core&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;@design-token-kit/cli&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;core&lt;/code&gt; is the main logic. It reads tokens, converts them to a common internal model, validates them, converts them to CSS, and prepares data for the showcase.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cli&lt;/code&gt; is the layer for terminal usage. It parses commands, accepts file paths and options, and calls the needed features from &lt;code&gt;core&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This split helps keep the main token processing logic separate from the command line. The CLI stays as a convenient way to run the tool, and &lt;code&gt;core&lt;/code&gt; can grow as a separate library.&lt;/p&gt;

&lt;p&gt;This is useful for the future. The same logic can be used not only through the &lt;code&gt;dtokens&lt;/code&gt; command, but also in other places: for example, in a project build, a CI pipeline, a separate interface, or design system documentation.&lt;/p&gt;

&lt;p&gt;As a result, the CLI is responsible for how the user runs commands, and &lt;code&gt;core&lt;/code&gt; is responsible for what happens with the tokens inside.&lt;/p&gt;
&lt;h2&gt;
  
  
  CLI commands
&lt;/h2&gt;

&lt;p&gt;The main work with Design Token Kit is done through the &lt;code&gt;dtokens&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Most examples below use files, but the tool can also read tokens from stdin and URLs. This is useful for pipelines, CI, and cases where tokens are passed between commands without a temporary file.&lt;/p&gt;

&lt;p&gt;When no output file is specified, command results can be written to stdout.&lt;/p&gt;

&lt;p&gt;Right now, the CLI has three main commands: &lt;code&gt;check&lt;/code&gt;, &lt;code&gt;convert&lt;/code&gt;, and &lt;code&gt;showcase&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Check
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;check&lt;/code&gt; command is the main way to validate token files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens check tokens.json
dtokens check tokens.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It helps find errors before tokens get into CSS or into the application.&lt;/p&gt;

&lt;p&gt;The command supports three scopes.&lt;/p&gt;

&lt;p&gt;Schema checks only the input structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens check tokens.json &lt;span class="nt"&gt;--scope&lt;/span&gt; schema
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validate runs schema checks and model-level checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens check tokens.yaml &lt;span class="nt"&gt;--scope&lt;/span&gt; validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lint runs everything from validate and then adds architecture checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens check tokens.yaml &lt;span class="nt"&gt;--scope&lt;/span&gt; lint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This split is useful because not every problem is the same kind of problem. A file can be structurally valid, but still contain broken references or architecture mistakes.&lt;/p&gt;

&lt;p&gt;At the validate level, the tool checks problems such as missing references, circular references, references to groups instead of tokens, type mismatches, deprecated references, and duplicate gradient stop positions.&lt;/p&gt;

&lt;p&gt;At the lint level, the tool also checks token architecture rules. For example, it can report invalid cross-layer references and raw values used above the lowest layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Convert
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;convert&lt;/code&gt; command converts tokens between formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens convert tokens.json
dtokens convert tokens.yaml &lt;span class="nt"&gt;--inform&lt;/span&gt; hrdt &lt;span class="nt"&gt;--outform&lt;/span&gt; css &lt;span class="nt"&gt;--out&lt;/span&gt; tokens.css
dtokens convert tokens.json &lt;span class="nt"&gt;--outform&lt;/span&gt; hrdt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this command, you can get CSS custom properties, convert DTCG JSON to HRDT YAML, or convert HRDT YAML back to DTCG JSON.&lt;/p&gt;

&lt;p&gt;For example, if tokens are written in YAML, they can be converted to a CSS file and used in a project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens convert tokens.yaml &lt;span class="nt"&gt;--inform&lt;/span&gt; hrdt &lt;span class="nt"&gt;--outform&lt;/span&gt; css &lt;span class="nt"&gt;--out&lt;/span&gt; tokens.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result will be a normal CSS file with variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Showcase
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;showcase&lt;/code&gt; command generates an HTML page for viewing tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dtokens showcase tokens.yaml &lt;span class="nt"&gt;--out&lt;/span&gt; showcase.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The showcase can be built from token files or from CSS.&lt;/p&gt;

&lt;p&gt;This is useful when you want to quickly check what you got after conversion: colors, spacing, radius values, shadows, and other values. You do not need to start a separate app or build large documentation. You just open an HTML file in the browser.&lt;/p&gt;

&lt;p&gt;The tool can be installed in a project, installed globally, or run with &lt;code&gt;npx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For us, it was important that the basic scenario stayed simple: you have a token file, and you can validate it, convert it, and view the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with themes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0o9zi72gjbbb0ez2fsl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq0o9zi72gjbbb0ez2fsl.png" alt="Css design tokens" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Design tokens rarely live in only one version. Usually, a dark theme or extra color schemes appear next to the base values quite quickly.&lt;/p&gt;

&lt;p&gt;That is why we treated theme support as one of the basic scenarios in Design Token Kit.&lt;/p&gt;

&lt;p&gt;The idea is simple: some tokens describe default values, and some tokens&lt;br&gt;
describe values for a specific theme. During CSS conversion, this becomes a set of variables for the base state and separate blocks for themes.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--background-color-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--text-color-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"dark"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;--background-color-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;--text-color-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Themes are also important in the showcase. The showcase should not only show a list of tokens. It should also help users understand which values belong to the base set and which values belong to a specific theme. Otherwise, you can get a table of variables, but still not really see how tokens are split between themes.&lt;/p&gt;

&lt;p&gt;For now, we keep theme display simple: we show information about available&lt;br&gt;
themes and the tokens themselves, without a complex switcher. For the first step, this is enough to check the structure and see that the theme was included in the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was the hardest part
&lt;/h2&gt;

&lt;p&gt;At first, design tokens look like a clean list of values: colors here, spacing there, radius values somewhere nearby. Almost like a shopping list, but instead of bread and milk, you have &lt;code&gt;primary&lt;/code&gt;, &lt;code&gt;background&lt;/code&gt;, and &lt;code&gt;spacing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the more you work with them, the clearer it becomes: the values are not the only important part. The links between them matter too. You need to understand the input format, convert tokens to a common model, check the structure, process references, keep themes working, and still return a result that can be used later.&lt;/p&gt;

&lt;p&gt;Errors are a separate story. Just saying “something went wrong” is not very helpful. The tool should show where the exact problem is: a reference points to a missing token, a circular dependency appeared, types do not match, or a whole group was used instead of a real token.&lt;/p&gt;

&lt;p&gt;Another difficult part is the balance between a strict format and comfort for people. A format that is too flexible is hard to validate. A format that is too strict is hard to write by hand. A good design token tool lives somewhere between these two sides.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Right now, Design Token Kit covers the basic scenario: tokens can be described, validated, converted to CSS, and viewed in a showcase. Next, we want to make the tool smarter when working with tokens.&lt;/p&gt;

&lt;p&gt;One direction is diagnostics: finding unused tokens, empty groups, tokens&lt;br&gt;
without descriptions, and other token hygiene problems.&lt;/p&gt;

&lt;p&gt;Some architecture diagnostics are already implemented. For example, the tool can already report invalid cross-layer references and raw values used above the primitive layer. The next step is to expand this set with more design-system rules and clearer diagnostics.&lt;/p&gt;

&lt;p&gt;We also want to improve the showcase. Right now, it is a simple HTML page for viewing tokens, but later it can become more useful: show themes better, group values better, add more visual examples, and help users understand faster what is really inside a token file.&lt;/p&gt;

&lt;p&gt;Another direction is export support. CSS custom properties are a good basic option, but tokens may also be needed in other formats: SCSS, Tailwind config, Android XML, and iOS Swift.&lt;/p&gt;

&lt;p&gt;Ideally, Design Token Kit should stay small and easy to understand, but slowly take more routine work around tokens: check them, give hints, show them, and convert them.&lt;/p&gt;

&lt;p&gt;Design Token Kit started as a small tool for our own workflow.&lt;br&gt;
Over time, it became a useful way to validate, convert, and inspect design tokens. We hope it can also be useful for other teams working with design systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/design-token-kit/design-token-kit" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designsystem</category>
      <category>css</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
