My new ebook  Design Systems for Developers  is here! Start reading

Design

Documenting Design Tokens With Docusaurus

Adding Visuals To Your Style Dictionary

Last Updated: 2021-02-11

Table of Contents

1 | Introduction to Design Tokens
2 | Managing and Exporting Design Tokens With Style Dictionary
3 | Exporting Design Tokens From Figma With Style Dictionary
4 | Consuming Design Tokens From Style Dictionary Across Platform-Specific Applications
5 | Generating Design Token Theme Shades With Style Dictionary
6 | Documenting Design Tokens With Docusaurus
7 | Integrating Design Tokens With Tailwind
8 | Transferring High Fidelity From a Design File to Style Dictionary
9 | Scoring Design Tokens Adoption With OCLIF and PostCSS
10 | Bootstrap UI Components With Design Tokens And Headless UI
11 | Linting Design Tokens With Stylelint
12 | Stitching Styles to a Headless UI Using Design Tokens and Twind

What You’re Getting Into

In a previous article, I mentioned that a perk of using Style Dictionary is that it serves as a central place to document your design tokens and the generated platform deliverables.

With a little bit of work, we can create a site to provide a visual enhancement to this documentation.

documenting design tokens with docusaurus

We can create something similar to the graphic above where it lists outs all the tokens that are part of the design system.

From what I’ve written about consuming design tokens across applications of different platforms, we should have all the skills to build a documentation site.

We would just add a job to a GitHub Actions workflow that delivers the generated design tokens to a repository for a documentation site.

The repository could be a site that utilizes GitHub Pages, Gatsby, Next.js, or any other framework to provide a visual display for the platform deliverables generated by a style dictionary.

In this article, we will not try out all the possible ways in which you can build a documentation site.

Rather, we’ll walk through using Docusaurus, a framework for generating a fast documentation site built with React and following the Jamstack architecture.

You can read the documentation for a comparison between other alternatives.

The TL;DR is that it is open-source and is optimized for the specific niche of documentation sites.

Getting Our Bearings With Docusaurus

First things first, we’ll create a new Docusaurus project:

npx @docusaurus/init@latest init design-tokens-documentation classic

In the snippet above, design-tokens-documentation is the arg representing the name of our project. classic refers to the theme we want to use (facebook and bootstrap are the two alternative themes).

Change into the new design-tokens-documentation directory and open the project in a code editor.

As the documentation outlines, the project has the following structure:

design-tokens-documentation
├── blog
│   ├── 2019-05-28-hola.md
│   ├── 2019-05-29-hello-world.md
│   └── 2020-05-30-welcome.md
├── docs
│   ├── doc1.md
│   ├── doc2.md
│   ├── doc3.md
│   └── mdx.md
├── src
│   ├── css
│   │   └── custom.css
│   └── pages
│       ├── styles.module.css
│       └── index.js
├── static
│   └── img
├── docusaurus.config.js
├── package.json
├── README.md
├── sidebars.js
└── yarn.lock

In short, we can see that an example site has been generated.

Let’s see the site in the browser before we dive deeper into what exactly has been generated.

It appears to have generated a home screen with navigation, header, some content, and a footer.

documenting design tokens with docusaurus

It also comes with a dark mode toggle. 🎉

documenting design tokens with docusaurus

Clicking on the “Docs” link in the navigation, it looks like a standard, yet sleek, documentation site example.

documenting design tokens with docusaurus

It seems that the documentation pages are generated from GitHub-flavored Markdown.

There are some nice touches like a sidebar to the left for structuring the documentation and a table of contents for the current article to the right.

Clicking on the “Blog” link in the navigation, it looks like another standard, yet sleek, page, this time for blog posts.

documenting design tokens with docusaurus

Now that we have our bearings, we can review the code that was generated when we initialized the project.

sidebars.js contains the configuration for sidebars that you can have for your documentation (the “Docs” page).

module.exports = {
  someSidebar: {
    Docusaurus: ['doc1', 'doc2', 'doc3'],
    Features: ['mdx'],
  },
};

someSidebar is an object representing the organization of the sidebar used in the Docs page.

Docusaurus is a list containing the names of some Markdown files found in the docs folder. This drives the visual experience of a dropdown in the sidebar with links using the titles in the matching Markdown files.

The same goes for the other dropdown Features.

docusaurus.config.js reveals some more information about how this is all coming together.

In that file, some basic site metadata is configured such as the title, tagline, URL, etc.

There is also a themeConfig property that drives the look and functionality of the navigation and footer.

The presets property associates the sidebar in sidebars.js with the Docs page. It also associates an editUrl for the Docs and Blog pages so anyone can update the post.

Finally, the src/pages folder contains non-documentation pages, including the home page.

Of course, you can read the official documentation for even more details.

Design Tokens Documentation

Now that we have an understanding of how Docusaurus works, we could move along to updating the site for our design token documentation.

How one goes about updating the site will vary between use cases.

Some teams might want to leverage this technology to create the design system documentation. In those scenarios, there is going to be a lot more going on than documenting the design tokens that are exported by Style Dictionary.

I won’t cover what goes into all that, but I will make some suggestions as to what should be documented that pertains to Style Dictionary and the deliverables it exports.

After that, we can work together to add a documentation page that integrates with the deliverables from Style Dictionary.

Documentation Ideas

First, you could document the overview of the design to the developer process.

This would include a description of how design token files are generated from a design file that contains the specifications for the design system.

Additionally, it would include a description of how the generated design tokens are imported into a Style Dictionary repository. It would also describe the automation that occurs to transform those imported design tokens and then export them using a GitHub Actions workflow.

As I mentioned in my article on this automation, a new job will have to be registered in a GitHub Actions workflow for every consuming application that wants a platform deliverable.

Therefore, there should be documentation on a process describing how a team/application can “subscribe” to the Style Dictionary repository and get a platform deliverable via a new job in the workflow.

You can even create a visual tool for generating/modifying the GitHub Actions workflows.

Finally, you may want to include a page displaying the health status of systems that are relied upon to perform the design to developer handoff such as GitHub APIs and the serverless function used to transmit design tokens from a design file to the Style Dictionary repository.

documenting design tokens with docusaurus

Documenting Design Tokens

With some real-world documentation suggestions aside, let’s dive back into documenting the actual design tokens.

First things first, push your local Docusaurus project to a GitHub repository.

Next, fork my style-dictionary repository if you haven’t already and create a new branch off of the latest branch.

I’ll be naming my new branch documenting-design-tokens-with-docusaurus after this article.

On this branch, we’ll update the GitHub Actions workflow that delivers the platform deliverables from Style Dictionary to consuming applications.

We’ll want to add a job that delivers it to the Docusaurus repository that we just created.

Here the starter for my Docusaurus repository: https://github.com/michaelmang/design-tokens-documentation

In the style-dictionary branch, update the deliver-tokens-to-consumer.yml file so that it has a job that will deliver the output/css/_variables.css file to the Docusaurus repository.

Here’s what the diff looked like for me:

name: Deliver Tokens To Consumer
'on':
  push:
    paths:
      - output/**
jobs:
-  deliver_to_react_application:
+  deliver_to_docusaurus:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Deliver Platform Deliverable To Application
        uses: andstor/copycat-action@v3
        with:
          personal_token: '${{ secrets.API_TOKEN_GITHUB }}'
-          src_branch: generating-design-token-theme-shades-with-style-dictionary
+          src_branch: documenting-design-tokens-with-docusaurus
          src_path: output/css/_variables.css
          dst_owner: michaelmang
-          dst_repo_name: design-token-theme-shades
+          dst_repo_name: design-tokens-documentation
-         dst_branch: implement-shades
+         dst_branch: add-token-docs
          dst_path: tokens/_variables.css
          username: michaelmang
          email: mikemangialardi94@gmail.com
          commit_message: Update platform deliverable

Now, we can update a file in the output folder to trigger this workflow to run (this would usually be done automatically when design tokens are imported to the style dictionary):


- * Generated on Tue, 09 Feb 2021 18:12:11 GMT
+ * Generated on Tue, 10 Feb 2021 18:12:11 GMT 

Push these changes.

Once the GitHub Actions finish, we should see a tokens/_variables.css file in the Docusaurus project in GitHub.

documenting design tokens with docusaurus

Check out the new branch, add-token-docs, that was generated on the origin of the Docusaurus repository.

Next, let’s talk about what we want our Docusaurus documentation to look like after our changes.

I’m picturing that we’ll create a dropdown called “Tokens” and have a Markdown file for every platform deliverable that is exported by Style Dictionary.

To do this, let’s update sidebars.js in the Docusaurus project to have just this dropdown:

// sidebars.js
module.exports = {
  someSidebar: {
    Tokens: [],
  },
};

We’ll need to populate the Tokens dropdown with Markdown articles for every platform deliverable.

One way to do this would be to write a Node script that reads every file in the tokens directory (containing all our platform deliverables) and creates a Markdown file in the docs folder.

The contents of the Markdown file will be a table with the key-value pair of every token.

In our case, the script should generate a docs/CSS.md file with a table containing a cell for the CSS variable keys and their values.

Create a file called generateTokenDocs.js:

// generateTokenDocs.js
const fs = require("fs");

const TOKENS_FOLDER = './tokens/';

fs.readdirSync(TOKENS_FOLDER).forEach(file => {

});

We are in a position to read every file in the tokens folder and do something with the file.

Using the Node Path API, we can parse the extension of the file and strip the . to get the name of the Markdown file to be generated:


// generateTokenDocs.js
fs.readdirSync(TOKENS_FOLDER).forEach(file => {
  const extension = path.parse(file).ext;
  const docName = extension.replace(".", "").toUpperCase();
});

Now, the tricky part. We have to grab only the CSS variables from the file.

The good thing is that just a little bit of regex can be applied to the contents of the file to get what we need.

// generateTokenDocs.js
fs.readdirSync(TOKENS_FOLDER).forEach(file => {
  const extension = path.parse(file).ext;
  const docName = extension.replace(".", "").toUpperCase();

  const contents = fs.readFileSync(`${TOKENS_FOLDER}${file}`, 'utf-8');
  
  const cssVariableMatcher = /--.+: .+(?=;)/gm;
  const variables = contents.match(cssVariableMatcher);
});

The contents are grabbed by using fs.readFileSync which is part of the Node File System API. Applying the regex on the contents, we get the variables from the file.

The next step is to generate the contents for the new Markdown file.

Looking at the example doc.md, we need to include some metadata in the markdown file to wire up the sidebar configuration as well as specifying the title and slug:

---
id: doc1
title: Style Guide
sidebar_label: Style Guide
slug: /
---

We can start preparing the Markdown for the CSS tokens doc by writing out the metadata.

// generateTokenDocs.js
fs.readdirSync(TOKENS_FOLDER).forEach(file => {
  const extension = path.parse(file).ext;
  const docName = extension.replace(".", "").toUpperCase();

  const contents = fs.readFileSync(`${TOKENS_FOLDER}${file}`, 'utf-8');
  
  const cssVariableMatcher = /--.+: .+/gm;
  const variables = contents.match(cssVariableMatcher);
  
  const markdown = `
  ---
  id: ${docName}
  slug: /
  sidebar_label: ${docName}
  title: ${docName} Tokens
  ---
  `;
});

Next, we append a Markdown table containing the key-value pairs as table cells in a row.

// generateTokenDocs.js
fs.readdirSync(TOKENS_FOLDER).forEach(file => {
  const extension = path.parse(file).ext;
  const docName = extension.replace(".", "").toUpperCase();

  const contents = fs.readFileSync(`${TOKENS_FOLDER}${file}`, 'utf-8');
  
  const cssVariableMatcher = /--.+: .+(?=;)/gm;
  const variables = contents.match(cssVariableMatcher);
  
  const keyValueRows = variables.map(variable => {
    const [key, value] = variable.split(":");
    return `| ${key} | ${value} |`;
  });

  const markdown = `
  ---
  id: ${docName}
  slug: /
  sidebar_label: ${docName}
  title: ${docName} Tokens
  ---
  | Key | Value |
  | ------------- | ------------- |
  ${keyValueRows.join("\n")}
  `;
});

We want the slug to be / since it’s the default file in our “Tokens” sidebar.

The key and value in each string within variables are split into an array.

Then, the key and value are injected into a Markdown table row template containing two separate table cells.

The keyValueRows are then transformed from an array back into a string with a line break after each row.

We’re now ready for the final step of this script which is to write the new Markdown file to the docs folder with the name and contents we’ve created.

// generateTokenDocs.js
const fs = require("fs");
const path = require("path");
+ const prettier = require("prettier")

+ const DOCS_FOLDER = './docs/';
const TOKENS_FOLDER = './tokens/';

fs.readdirSync(TOKENS_FOLDER).forEach(file => {
  const extension = path.parse(file).ext;
  const docName = extension.replace(".", "").toUpperCase();

  const contents = fs.readFileSync(`${TOKENS_FOLDER}${file}`, 'utf-8');
  
  const cssVariableMatcher = /--.+: .+(?=;)/gm;
  const variables = contents.match(cssVariableMatcher);
  
  const keyValueRows = variables.map(variable => {
    const [key, value] = variable.split(":");
    return `| ${key} | ${value} |`;
  });

  const markdown = `
  ---
  id: ${docName}
  slug: /
  sidebar_label: ${docName}
  title: ${docName} Tokens
  ---
  | Key | Value |
  | ------------- | ------------- |
  ${keyValueRows.join("\n")}
  `;

+  const data = prettier.format(markdown, {
+    parser: "markdown",
+  });

+  fs.writeFileSync(`${DOCS_FOLDER}${docName}.md`, data)
});

We can utilize Prettier to format our Markdown so things look nice when the new doc is created.

You’ll have to install the dependency:

npm i prettier

To run this script via NPM, we’ll add a new script to package.json:

// package.json
"scripts": {
     // ...
+   "generate-token-docs": "node generateTokenDocs.js"
},

Let’s run npm run generate-tokens-docs to see if this is all working.

documenting design tokens with docusaurus

We should see a new file in our docs called CSS.md with some nice formatting! 🎉

Now, we need our sidebars.js to include our new doc in the Tokens list by adding the id in the metadata of our new docs/CSS.md file:

// sidebars.js
module.exports = {
  someSidebar: {
    Tokens: [], // add "CSS" id here
  },
};

We can achieve this by having sidebars.js read the files in the docs folder. It can look for a “tag” in the metadata to know that it belongs in the sidebar.

First, let’s go back to generateTokenDocs.js add a “tokens” tag to the Markdown contents:

// generateTokenDocs.js
 const markdown = `
 ---
 id: ${docName}
 slug: /
 sidebar_label: ${docName}
 title: ${docName} Tokens
+ tags: [tokens]
 ---
 | Key | Value |
 | ------------- | ------------- |
 ${keyValueRows.join("\n")}
 `;

Run npm run generate-tokens-docs one more time to generate the file that should now contain the tags metadata.

Then, we can update sidebars.js to populate the Tokens with the id from any file that contains a “tokens” tag:

// sidebars.js
const fs = require("fs");

const DOCS_FOLDER = "./docs/";

let tokens = [];

fs.readdirSync(DOCS_FOLDER).forEach((file) => {
  const contents = fs.readFileSync(`${DOCS_FOLDER}${file}`, "utf-8");

  const tagsMatcher = /tags: \[.*\]/gm;
  const tags = contents.match(tagsMatcher);
  if (tags && tags[0].includes("tokens")) {
    const idMatcher = /id: .*/gm;
    const id = contents.match(idMatcher)[0].split(":")[1].trim();
    tokens.push(id);
  }
});

module.exports = {
  someSidebar: {
    Tokens: tokens,
  },
};

The true test will be to run npm run start and see if the CSS tokens doc is showing up on the “Docs” page.

documenting design tokens with docusaurus

Woohoo! It works! 🎉

Improving Our Design Tokens Documentation Process

The sky’s the limit for what you can do with the power of Docusaurus, but I won’t be diving into that.

However, I do want to call out some ways that the process for generating documentation for design tokens could be improved.

First, we only handled the scenario where there is a single platform deliverable, CSS tokens.

If we want to handle the documenting of additional platform deliverables, our generateTokenDocs.js script will have to become more robust.

It will need to either generalize the logic to extract the key-value pairs or handle each file extension differently and have custom logic for each platform deliverable.

We won’t do that together, but I wanted to provide the heads up.

Second, we can automate the generation of the token docs.

We can do this by adding a GitHub Actions workflow in our Docusaurus repository that will run the npm run generate-tokens-docs script whenever new tokens are received.

Let’s create a .github/workflows/generate-docs-on-tokens.yml file.

# generate-docs-on-tokens.yml
name: Generate Docs On Tokens

on:
  push:
    paths:
      - "tokens/**"

jobs:
  generate_token_docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: "12"
      - name: Install Node Dependencies
        run: npm install
      - name: Generate Token Docs
        run: npm run generate-token-docs
      - name: Commit Generated Platform Deliverables
        id: "auto-commit-action"
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: Update token docs

This workflow is very similar to the workflow in the style-dictionary repository to generate design tokens with Style Dictionary when it receives the design tokens from a design file.

With our new workflow, it will run the npm run generate-token-docs and commit the files generated during the workflow.

Let’s commit and push our code.

To test this automation all the way through, let’s go back to the style-dictionary repository and update the output/css/_variables.css file one more time:

- --color-background-page-primary-70: hsl(262, 100%, 68%);
+ --color-background-page-primary-70: hsl(162, 100%, 68%); 

We’ll modify the first variable in the file to have a hue of 162 instead of 262.

Push this change.

After both workflows run (first in style-dictionary then in the Docusaurus repository), we should see that the docs/CSS.md was modified with the change!

documenting design tokens with docusaurus

So cool! 🎉

Here is the final code for the style-dictionary repository:
https://github.com/michaelmang/style-dictionary/pull/5

Here is the final code for the Docusaurus repository:
https://github.com/michaelmang/design-tokens-documentation/pull/1

Conclusion

I hope that this article gives you a clear direction on how to automate the generation of documentation for design tokens exported by Style Dictionary.

I also hope that it gives you a sampling of the Docusaurus which you can use for more than just design tokens documentation.

In my next article, I go over integrating design tokens with Tailwind.

If you’re interested in the ebook version of these articles, the easiest thing would be to subscribe to my newsletter where I’ll provide updates.

Cheers! Pow, discuss, and share.

Design Systems for Developers

Read my latest ebook on how to use design tokens to code production-ready design system assets.

Design Systems for Developers - Use Design Tokens To Launch Design Systems Into Production | Product Hunt

Michael Mangialardi is a software developer specializing in UI development with React and fluent in UI/UX design. As a survivor of impostor syndrome, he loves to make learning technical skills digestible and practical. Formerly, he published articles, ebooks, and coding challenges under his brand "Coding Artist." Today, he looks forward to using his mature experience to give back to the web development community. He lives in beautiful, historic Virginia with his wife.