Tailwind CSS

Keeping Tailwind design tokens in sync automatically from Figma

TW

Design tokens defined in Figma and consumed by Tailwind's CSS-based theming have been synced manually for a while now, a process reliable enough day to day but always one missed export away from drifting, usually discovered only when a designer noticed a color in production didn't quite match what they'd last set in Figma. We finally automated the whole thing end to end this quarter, after enough small drift incidents accumulated that the manual process stopped feeling like an acceptable steady state.

A scheduled job now pulls variable changes from Figma on a regular interval and opens a pull request updating the corresponding Tailwind theme file automatically, with a human still reviewing and merging rather than letting the change land unattended. That review step matters more than it might sound like it should: an automated pull request makes an intentional design change from an accidental one, like someone nudging a spacing token while exploring an unrelated mockup, equally visible in a diff, and a human glancing at that diff before merging catches the accidental ones before they ship.

Drift between design and code has effectively stopped being a recurring complaint since this went live, which was the whole point, but a secondary benefit surprised us a little: the automated pull requests themselves have become a lightweight audit trail of design decisions over time, in a way the old manual export process never gave us. Scrolling back through merged token-sync pull requests shows a clean history of exactly when a given color or spacing value changed and why, tied to the Figma change that triggered it, which has been genuinely useful during a couple of "wait, when did this change" conversations that used to require someone's memory rather than a record.

The one adjustment we made after the initial rollout was slowing the sync frequency down from near-real-time to a few times a day, after the first version generated enough small pull requests during active design exploration to feel noisy rather than helpful. Batching changes into a few daily syncs struck a better balance between staying current and not asking engineers to review a design-token pull request every hour.

We also had to think carefully about what counts as a token in the first place, since Figma's variable system is more flexible than Tailwind's theme structure and not every Figma variable maps cleanly onto a Tailwind token category. Composite variables that reference other variables, for instance, needed explicit handling in the translation layer rather than a naive one-to-one mapping, since a naive approach either flattened them into duplicated literal values or broke the reference chain entirely. Getting that translation right took a few iterations early on, including one embarrassing week where a color alias silently resolved to the wrong value across the entire site because the translation layer picked the wrong variable in a reference chain, caught only because a designer happened to notice a slightly-off shade on the homepage.

That incident became the reason we added a validation step to the sync pipeline: before opening a pull request, the job renders a small visual diff of key components against both the old and new token values, attached directly to the pull request description, so a reviewing engineer can see at a glance whether a token change looks like what the designer actually intended rather than trying to mentally simulate the effect of a hex code change. That visual diff has caught more than one accidental variable reference since, well before it ever reached production.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients