Style Dictionary 5 for React Native and web teams: our review
What Style Dictionary does well, where it still lags the 2025.10 token spec, a working config for CSS variables plus a React Native module, and when we would pick something else.

Most teams that ship a React Native app next to a web product end up with the same problem: the same blue lives in a CSS file, a TypeScript theme object and a Figma library, and the three drift apart within a quarter. Design tokens fix that only if something turns one source file into the code each platform actually uses.
Style Dictionary is the tool we reach for first for that job. It started at Amazon, now lives in its own open-source GitHub organisation, and is one of the reference implementations named when the W3C Design Tokens Community Group (DTCG) published its first stable format. This review covers the current major version, 5, from the point of view of a team shipping React Native plus web.
What it does
Style Dictionary reads token files (JSON, JSON5 or JavaScript), merges them into one tree, resolves references such as {color.blue.500}, and then runs each platform in your config. A platform is a list of transforms (change a token's name or value, for example camelCase names or px to rem) and one or more formats (write the result as CSS variables, an ES module, Swift, Kotlin and so on).
That model is the reason it has lasted. The core does very little that is opinionated; nearly everything is a named hook you can swap or extend. The built-in catalogue covers CSS, SCSS, Less, JavaScript, TypeScript declarations, Android XML, Jetpack Compose, iOS Swift and Flutter, plus a react-native transform group.
What changed in v4 and v5
If your last look at Style Dictionary was v3, the API you remember is gone. Version 4 (June 2024) was a rewrite, and version 5 (May 2025) tightened it further. The changes that matter in practice:
| Change | Version | What it means for you |
|---|---|---|
| ES modules only | v4 | Your build script is an .mjs file or lives in a "type": "module" package. CommonJS projects need a dynamic import(). |
| Class and async API | v4 | new StyleDictionary(config), then await sd.buildAllPlatforms(). Hooks can be async too. |
| Hooks renamed and grouped | v4 | Custom code goes under hooks.transforms, hooks.formats and friends; transformer became transform, matcher became filter. |
| First-class DTCG format | v4 | $value, $type and $description work out of the box, and $type set on a group is inherited by its tokens. |
| No more CTI dependency | v4 | Built-in transforms read the token's type instead of guessing from a category/type/item path. |
| Node 22 minimum | v5 | CI images and local machines need Node 22 or newer. |
| Stricter references | v5 | References must point at a token, not at a group or a sub-property, and the { } syntax is fixed to match the DTCG spec. |
| 2025.10 colour objects | v5.3 | Colour transforms accept { colorSpace, components, alpha, hex } across all 14 DTCG colour spaces, with new color/oklch, color/p3 and similar outputs. |
| 2025.10 dimension objects | v5.4 | Dimension tokens can be { value, unit } objects, and the CSS shorthand transforms for shadow, border and typography handle them. |
A config that produces CSS variables and a React Native module
Here is the smallest setup we would actually ship. One token file in DTCG 2025.10 syntax: a primitive blue, a semantic alias that points at it, and a spacing pair.
{
"color": {
"$type": "color",
"blue": {
"500": {
"$value": { "colorSpace": "srgb", "components": [0.15, 0.39, 0.92], "hex": "#2663eb" }
}
},
"action": {
"primary": { "$value": "{color.blue.500}", "$description": "Main call-to-action fill" }
}
},
"space": {
"$type": "dimension",
"md": { "$value": { "value": 16, "unit": "px" } },
"card": { "$value": "{space.md}" }
}
}
The build script defines one custom transform, because React Native styles take plain numbers rather than 16px strings. Everything else is built in. Note there is no usesDtcg flag: Style Dictionary detects the $value syntax on its own.
// build.mjs (run with Node 22+)
import StyleDictionary from 'style-dictionary';
// React Native wants unitless numbers (density-independent pixels).
StyleDictionary.registerTransform({
name: 'size/rn-number',
type: 'value',
filter: (token) => token.$type === 'dimension',
transform: (token) => {
const v = token.$value;
return typeof v === 'object' ? v.value : parseFloat(v);
},
});
const sd = new StyleDictionary({
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/web/',
files: [{
destination: 'tokens.css',
format: 'css/variables',
options: { outputReferences: true },
}],
},
rn: {
transforms: ['name/camel', 'color/hex', 'size/rn-number'],
buildPath: 'dist/native/',
files: [
{ destination: 'tokens.js', format: 'javascript/es6' },
{ destination: 'tokens.d.ts', format: 'typescript/es6-declarations' },
],
},
},
});
await sd.buildAllPlatforms();
Running node build.mjs against Style Dictionary 5 gives this output (file banners trimmed). The CSS keeps the alias chain as var() references because of outputReferences, which makes theme overrides cheap. The React Native module gets resolved values and a .d.ts file typing the colours as string and the spacing as number.
/* dist/web/tokens.css */
:root {
--color-blue-500: #2663eb;
--space-md: 16px;
--color-action-primary: var(--color-blue-500); /** Main call-to-action fill */
--space-card: var(--space-md);
}
// dist/native/tokens.js
export const colorBlue500 = "#2663eb";
export const colorActionPrimary = "#2663eb"; // Main call-to-action fill
export const spaceMd = 16;
export const spaceCard = 16;
We deliberately do not use the built-in react-native transform group for spacing. Its size/object transform turns 10px into an object with original, number, decimal and scale keys, which is flexible but means every style has to reach into .number. A three-line custom transform gives engineers the value they expect.
Where it is strong
- Extensibility without forking. Transforms, formats, filters, parsers, preprocessors and actions are all plain functions. When a platform needs something odd (a NativeWind theme, a Tailwind preset, an Android
colors.xml), we write a format, not a fork. - Reference handling.
outputReferenceskeeps aliases as CSS custom properties, so a dark theme can override the semantic layer only. Few tools get this right. - Breadth of outputs. One config can cover web, React Native, native iOS and Android, which matters when a client later adds a native widget or watch app.
- Typed output. The TypeScript declaration formats mean a renamed token breaks the build instead of silently falling back to
undefined. - It is the default. Tokens Studio, Figma exports and most token tutorials assume Style Dictionary, so new hires have usually seen it.
Where it is weak
- Themes are your problem. Light/dark and multi-brand builds are usually one Style Dictionary instance per theme, driven by a loop in your build script. It works, but you design the folder layout and the merge rules yourself until resolver support lands.
- Composite tokens on native. The CSS shorthand transforms for typography and shadow are good. On React Native you still write your own format to turn a typography token into a style object and a shadow into platform-specific shadow props.
- Migration cost. v3 to v4 touched every custom hook; v4 to v5 is described in the docs as close to drop-in, but the reference rules changed. Pin the major version and read the migration guide before upgrading.
- Node 22 requirement. Fine for most teams in 2026, but it bites on older CI images and on design tooling that bundles its own Node.
Alternatives worth knowing
| Tool | What it is | Pick it when |
|---|---|---|
| Tokens Studio + sd-transforms | A Figma plugin for managing tokens, plus @tokens-studio/sd-transforms, a package of Style Dictionary transforms and a preprocessor for its export (version 2 targets Style Dictionary 5). | Designers already manage tokens in Tokens Studio and you want Style Dictionary to read that export without hand-written glue. |
| Terrazzo | A DTCG-native token build tool (CLI tz, config in terrazzo.config.ts) with plugins for CSS, JS/TS, Sass, Tailwind, Swift, Vanilla Extract and more. Its 2.0 release (March 2026) claims full DTCG 2025.10 support, including resolvers. | Your source of truth is strict DTCG files with resolver-based themes, and your outputs are mostly web. Check the plugin list for the native outputs you need. |
| A hand-written script | Fifty lines of Node that read JSON and write a TS object. | You have under a hundred tokens, one theme and one platform. Graduate to a real tool the day a second platform or theme appears. |
Verdict
For a team shipping React Native and web from one set of tokens, Style Dictionary 5 remains our default. The hook model covers every output we have needed, outputReferences makes CSS theming clean, and adding a React Native module costs one small transform.
The one place we hesitate is themes. If your design system leans on DTCG resolvers for many brands and modes, try Terrazzo first and compare the output side by side. For one product with light and dark modes, Style Dictionary plus a small theme loop is the safer bet today.
- Pin the major version
style-dictionary@^5inpackage.json, and read the migration guide before any major bump. - Write tokens in DTCG syntax
$value,$type,$description. It costs nothing now and keeps your options open if you switch tools. - Commit the generated files or build them in CI, not bothPick one so reviewers know whether a token diff is source or output.
- Add a custom number transform for React NativeKeep spacing, radius and font sizes as plain numbers in the native module.
- Keep broken references fatalStyle Dictionary throws on a broken reference by default (
log.errors.brokenReferences). Leave it that way, and uselog: { verbosity: 'verbose' }while setting up.
Sources
- Style Dictionary: Design Tokens Community Group format · Style Dictionary
- Style Dictionary: v4 migration guidelines · Style Dictionary
- Style Dictionary: v5 migration guidelines · Style Dictionary
- Style Dictionary: predefined formats · Style Dictionary
- Style Dictionary v5.3.0 release notes · GitHub
- Tokens Studio sd-transforms · GitHub
- Terrazzo documentation · Terrazzo
- Design Tokens Format Module 2025.10 · Design Tokens Community Group


