Creating a design tokens automation pipeline with Figma and Style Dictionary

Gabriel Araújo
7 min readNov 23, 2022

--

In the last days, I was studying how I could create a good design system for a personal project and how I could understand better the design system and Figma as a frontend developer.

In this article, we are going to understand how we can create an automation pipeline on Figma, using the Design Tokens plugin, and converting it into JS code using Style Dictionary. With that, we can integrate any web project with our design system, in a automated way.

Link to the plugin

What are design systems and design tokens?

In Design Systems: The difference between a Style guide and Pattern Library Agonsi uses a definition that is perfect.

I’d define a design system as a set of rules, principles, scheme or procedures that consist of visual style guides, pattern libraries, brand guidelines and values, documentation which forms the base of a shared design language that aids in building standard, efficient and consistent products.

It is important to note that design systems are like living things.They constantly evolve and develop alongside the product and at the advent of new technologies.

How we can see in the last paragraph, the design system is a living thing — we are always updating, changing and evolving it. It’s very important to have this on sight. We need to make this change movement, something smoother and easier, because this changes are going to impact the whole product and for that we use the style dictionary.

Design tokens are all the values that are going to construct and maintain a design system, using a key / value format. Colors, spacing, opacities, border radius, etc.

What is Style Dictionary?

Style Dictionary is a tool from Amazon, a build system to convert JSON file of our design tokens into all kind of style variables: css, scss, JS, iOS, etc.

When you are managing user experiences, it can be quite challenging to keep styles consistent and synchronized across multiple development platforms and devices. At the same time, designers, developers, PMs and others must be able to have consistent and up-to-date style documentation to enable effective work and communication. Even then, mistakes inevitably happen and the design may not be implemented accurately. Style Dictionary solves this by automatically generating style definitions across all platforms from a single source — removing roadblocks, errors, and inefficiencies across your workflow.

Creating our project

The automation pipeline that we want, is going to work like this:

With the Design Tokens plugin on figma, we will generate our JSON file containing all the variables, we send this file using Github Actions to our Style Dictionary project that can be published into npm and installed in any frontend! In this way, we can create a fully integrated structure with the Github CI / CD.

For example: The designer add some color into the design system, then, he send it using the plugin. The project are going to be built using Github Actions and the developers can visualize in the pull requests what has been changed. After merging the pull request, we publish into NPM and all that we need to do, is update the package in our projects.

So, let’s do it! First, we need to have a design system — for this example we are going to use the Tailwind design system.

Let’s create our tokens project. First, we need to create a folder:

mkdir tokens-project && cd tokens-project

After that, start your project using: npm init -y and install the style dictionary using: npm install style-dictionary. Let’s install our dev dependencies too: npm install tsup typescript -D we will need this to import our tokens from the style dictionary build.
Now, we need to create our config.json file that will have the formats that we want to convert. We will convert our styles to JS in es6 format and to typescript.

// config.json
{
"source": ["input/**/*.json"],
"platforms": {
"js": {
"transformGroup": "js",
"buildPath": "build/js/",
"files": [
{
"destination": "index.js",
"format": "javascript/es6"
}
]
},
"ts": {
"transformGroup": "js",
"buildPath": "build/js/",
"files": [
{
"destination": "index.d.ts",
"format": "typescript/es6-declarations"
}
]
}
}
}

After creating our config.json file, we must create a build setup for our project in package.json

// package.json
{
"name": "token-project",
"version": "1.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"license": "MIT",
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts",
"build-tokens": "style-dictionary build"
},
"dependencies": {
"style-dictionary": "^3.7.1"
},
"devDependencies": {
"tsup": "^6.5.0",
"typescript": "^4.9.3"
}
}

With our build setup done, we are going to create our input folder and src folder, we can create then and put an index.ts file inside our src folder. Our files are going to look like this:

- node_modules/
- input/
- - .gitkeep
- src/
- - index.ts
- config.json
- package-lock.json
- package.json

The source files are going to be using typescript, they will import all the tokens from the style dictionary build that is going to be generated and tsup is going to convert them to javascript — basically we have two builds, one for the tokens from figma and the other for our source code files.

Now, we can test if our build is working. Export the JSON from a design system from figma and place into the input folder, then run npm run build-tokens. After building the json file, you can import in the index.ts

// src/index.ts

import {
ColorAmber100,
ColorAmber200,
ColorAmber300,
ColorAmber400,
} from "../build/js";

const colors = {
amber100: ColorAmber100,
amber200: ColorAmber200,
amber300: ColorAmber300,
amber400: ColorAmber400,
};

export { colors };

Basically, our structure is done — we just need to import all the other variables from the build and export them in index.ts as we did with the amber color. I highly recommend you creating a file for each collection of design tokens, like colors.ts , fonts.ts

We are going to use Github Actions to make this export from the design tokens automated. Create a .github folder in the root and a workflows folder inside it. Add a figma-workflow.yml file with this configuration:

#.github/workflows/figma-workflow.yml

name: Generate design tokens

on:
repository_dispatch:
types: update-tokens

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Create input JSON
id: create-json
uses: jsdaniell/create-json@1.1.2
with:
name: ${{ github.event.client_payload.filename }}
json: ${{ github.event.client_payload.tokens }}
dir: "input"

- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
cache: "npm"
cache-dependency-path: "**/package-lock.json"

- name: Install dependencies
run: npm ci

- name: Build tokens
run: npm run build-tokens

- name: Create PR
uses: peter-evans/create-pull-request@v4
with:
commit-message: "style: Update design tokens"
title: ${{ github.event.client_payload.commitMessage || 'Update design tokens' }}
body: "Design tokens have been updated via Figma and need to be reviewed."
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH_NAME: "main"

After creating the workflow, create a .gitignore and upload the repository to Github. Our final step is going to be adding the server url from Github into the Figma, and we are done!

# .gitignore

node_modules
input/*.json
dist

On your figma, click in the plugin design tokens and select send design tokens to url. In server url field you are going to add the following link, based on your repo: https://api.github.com/repos/:username/:repo/dispatches

In my case is going to be https://api.github.com/repos/araujooj/token-project/dispatches

We need to generate a Auth Token on Github. To do that, follow this documentation: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

After generating the token, you are all set to send your JSON file through the Github CI! Now, every change that is going to be done in the Figma file, we can send directly to our repo!

This is it! The project is done, and all we need to do is publish this to npm. We could create a CI to automate this process too, but we are not going to enter in this scope right now, who knows in the future?

To publish your package, follow this instructions:

This structure can be used in any JS project and we could use in a Monorepo too, using turborepo.

You can checkout one of my projects that is using this monorepo structure with React, Storybook and Style Dictionary

We as Frontend developers must understand how we can boost our productivity and how we can use everything that the design is providing to us. Approaching the design universe and trying to reduce the maximum of inconsistencies is the future of the frontend. We can see this in new libraries like Stitches and Radix, for example!

--

--