A frontend developer pinged me on Slack last Thursday. He was trying to style a custom dropdown component for our new dashboard. He just needed the active state border colour. It should have been a ten-second job. Instead he was completely stuck. He was writing a complex helper function to traverse a deeply nested JSON object. Our token pipeline had spit out a massive file. It looked something like this.
{ "color": { "brand": { "primary": { "500": { "value": "#0052CC", "type": "color" } } } } } He had to import this JSON file into his React component. Then he had to map the keys manually. Then he had to pass it down via a styled component prop. It took him twenty minutes just to colour a simple border. This happens every single day in frontend teams. We have convinced ourselves that design tokens must be abstract JSON files. We think we need complex build tools just to get colours onto a screen. It is a massive waste of time.
The abstraction trap
We started using JSON for design tokens with good intentions. We wanted a format that was agnostic. We wanted something that was independent of any specific programming language or framework. But we completely lost the plot along the way.
Browsers gave us the perfect token format years ago. They are called CSS custom properties. You probably know them as CSS variables. They are native to the web platform. They cascade beautifully through your DOM. They handle dark mode effortlessly without any JavaScript logic. Yet we still insist on exporting Figma variables to JSON first. Then we run Style Dictionary. Then we generate Sass maps or massive JavaScript objects. We are building a massive detour for absolutely no reason.
Let us look at how dark mode usually works when you rely on JSON tokens. You end up having to load multiple JSON files. You need one file for your light theme. You need another file for your dark theme. Then you have to write a React context provider to swap these objects based on the user preference. Your components have to re-render every time the theme changes.
const Button = styled.button` background-color: ${props => props.theme.color.brand.primary[500].value}; color: ${props => props.theme.color.text.inverse.value}; ` This is incredibly fragile. If a designer changes the token structure in Figma, your entire application breaks. The build fails. The developers have to hunt down every instance where that specific object path was used. It turns a simple design update into a stressful refactoring job.
The native web approach
Now imagine just using native CSS variables instead. Your component code becomes incredibly simple. It does not need to know about the theme context. It does not need to parse deeply nested objects.
.button { background-color: var(--color-brand-primary-500); color: var(--color-text-inverse); } The browser does all the heavy lifting for you. If you want to support dark mode, you just redefine those variables inside a media query. It requires zero JavaScript. It causes zero React re-renders. It just works immediately.
Debugging is also a completely different experience. When you use JSON and CSS-in-JS, you open Chrome DevTools and see a random generated class name. You have no idea where that colour came from. When you use CSS variables, DevTools shows you exactly which variable is applied. You can click it. You can change it right there in the browser. You can see the computed value instantly. It is a massive upgrade for developer experience.
The mobile argument
You are probably thinking about cross-platform support right now. People always say JSON is the universal language for tokens. They argue you need JSON to support iOS and Android applications. They say native platforms cannot read CSS variables.
That is totally fair. If you are actually building native mobile apps from the exact same Figma file as your web app, you might need a translation layer. But let us be honest with ourselves. Most teams are just building web applications. Many teams have completely separate design files for their native mobile apps anyway. We are paying the complexity tax of a massive multi-platform architecture for a simple React web app. We are making our web developers suffer just in case we build an iOS app three years from now.
Fixing the pipeline
We need to cut out the middleman entirely. We need to export our Figma variables directly to CSS. Your browser understands them natively. Your developers understand them instantly. If a designer changes a primary colour in Figma, you just want a pull request that updates a simple stylesheet. That is it. No parsing logic. No fragile build steps. No broken JSON schemas.
This exact frustration is why I built my own tool. I got tired of fixing broken JSON pipelines every single week. I created Design System Sync to solve this specific problem. It takes your Figma variables and exports them directly as CSS variables. It opens a pull request in GitHub or Bitbucket automatically. It handles all the tedious work for you.
You can still use W3C JSON formats if you really need them. But the best part is just getting raw CSS that works immediately. You can try it out for free at https://ds-sync.netlify.app?utm_source=devto&utm_medium=post&utm_campaign=bot. You can also grab it directly from the Figma Community at https://www.figma.com/community/plugin/1561389071519901700?utm_source=devto&utm_medium=post&utm_campaign=bot. I made sure it handles light and dark modes natively out of the box.
We need to stop over-engineering our design systems. We need to trust the web platform again. CSS variables are powerful enough to be your single source of truth in code.
Are you still running a massive build pipeline just to get a hex code onto your website?