How to sync your design tokens from Figma to Tailwind

· 6 min read

Why use an automatic sync tool?

Keeping in sync design decisions coming from design to code helps your branding be consistent at scale. Let me explain you what I mean by "from design to code".

It means your design decisions must go through several steps:

  1. Extract those decisions from your design tool (i.e. Figma)
  2. Make those decisions available to developers so they can use them in a specific platform (i.e. web)

Developers are not the only one to use those design decisions. Other parties like designers and business stakeholders will need them too.

Hence, your design decisions must be extracted from design and synchronised into your organization's design system.

Let's go back on developers. More precisely, web developers who are using design tokens thanks to the Tailwind framework. How can they ensure to always use the latest design tokens in their Tailwind configuration? Manually updating is a way to go but it's error-prone and surely not the most efficient.

What if you could have your Tailwind theme always in sync with the latest design decisions — automatically?

Thanks to Specify and the to-tailwind parser, it's now possible.

What is this parser?

From your Specify repository, you can easily extract all your design decisions using the to-tailwind parser. It helps you format design tokens to create a theme compatible with the TailwindCSS specification. By the way, the theme is also compatible with WindiCSS.

This parser creates a file containing the whole theme. It can then be used in your tailwind.config.js file. To use this parser head into your Specify configuration file.

Setting up the automatic sync

Let's setup a simple config to sync our colors coming from a Specify repository.

A Specify repository set up for the example with design tokens

From this repository, we will extract all the colors using this configuration.

{
  "repository": "@my_organization/my-repository",
  "personalAccessToken": "my_personal_access_token",
  "rules": [
    {
      "name": "Design Tokens / Colors",
      "path": "tailwind-theme.js",
      "filter": {
        "types": ["colors"]
      },
      "parsers": [
        {
          "name": "to-tailwind"
        }
      ]
    }
  ]
}

The personal access token can be extracted from our application in your personal settings.

This configuration will generate a file named tailwind-theme.js in your root directory containing:

const theme = {
  colors: {
    accent: "#6650ef",
    black: "#1e212b",
    green: "#58cd52",
    grey: "#ccd5e1",
    orange: "#ff8e05",
    red: "#f5483f",
    white: "#ffffff",
  },
};

module.exports = theme;

You can now use the freshly extracted colors in your tailwind.config.js:

const { colors } = require('./tailwind-theme');

module.exports = {
  // ... your Tailwind config
  theme: {
    extend: {
      colors,
    },
  },
};

And you're all set. You can now use the class .text-accent in your HTML document.

A more advanced setup

Colors are easily synced but sometimes you will:

  • Need more than just colors
  • Need to be able to override values
  • Need to extract design tokens from another source

For example, let's say you are currently transitioning from a CSS-in-JS to a Tailwind style implementation.

You want to extract your colors, text styles, fonts and shadows from your Specify repository but you still want to keep some of the old shadow values until you have completely migrated.

You can easily extract all the information from your Specify repository using this configuration:

{
  "repository": "@my_organization/my-repository",
  "personalAccessToken": "my_personal_access_token",
  "rules": [
    {
      "name": "Design Tokens / Colors - Shadows - Text Styles",
      "path": "tailwind-theme.js",
      "filter": {
        "types": ["color", "shadow", "textStyle"]
      },
      "parsers": [
        {
          "name": "to-tailwind",
          "options": {
            "formatName": "kebabCase",
            "formatConfig": {
              "module": "commonjs"
            }
          }
        }
      ]
    },
    // Rule to extract the fonts assets in the `.woff2` format
    {
      "name": "Assets / Font files",
      "path": "public/fonts",
      "filter": {
        "types": ["font"]
      },
      "parsers": [
        {
          "name": "convert-font",
          "options": {
            "formats": ["woff2"]
          }
        }
      ]
    },
    // Rule to create a css file that import the correct
    // `@font-face` in a `fonts.css` file
    {
      "name": "Design Tokens / Font face",
      "path": "public/fonts/fonts.css",
      "filter": {
        "types": ["font"]
      },
      "parsers": [
        {
          "name": "to-css-font-import",
          "options": {
            "formats": ["woff2"]
          }
        }
      ]
    }
  ]
}

This configuration allows you to extract every design tokens you need.

Now, let's say you have some old shadows coming from a style file like this one:

const shadows = {
    elevation1: 'box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);'
};

module.exports = shadows;

To use them in your config file, you would use it like this:

const { colors, boxShadow, fontSize, fontFamily } = require('./tailwind-theme');
const { shadows as oldShadows } = require('./style/shadows');

module.exports = {
  // your Tailwind config
  theme: {
    extend: {
      colors,
            boxShadow: {
                ...boxShadow,
                ...oldShadows, // this way, oldShadows will override the new ones
            },
      fontSize,
      fontFamily,
    },
  },
};

You can find more examples on our Github configuration examples repository.

Conclusion

Figma → Specify → Tailwind = 🔥

By using Specify and its to-tailwind parser you can easily extract design tokens from Figma to Specify and then from your Specify repository to your codebase.

Stay in control of your design tokens with Specify

We're currently in invite-only access and we're prioritizing teams willing to make evolve their token setup. Applications will be screened based on fit.

During your 30 days trial period, you will be able to take advantage of all our features without limitation.

We care about protecting your data. Read our Privacy Policy.

More articles from the blog