Уявіть команду, де продукт живе на трьох платформах: веб на React, iOS на SwiftUI і Android на Compose. Основний акцентний колір — один. Але в коді він продубльований тричі: #A8FF57 у CSS-змінній, той самий hex у Swift-константі і ще раз в Android XML. Дизайнер оновлює бренд — і хтось має вручну знайти всі три місця. Одне забули — і на iOS кнопка вже трохи іншого відтінку, ніж на вебі.
Це і є проблема, яку вирішує Style Dictionary — інструмент від Amazon, що бере одне джерело правди (JSON з токенами) і генерує з нього платформенні файли: CSS, Swift, Kotlin, TypeScript, будь-що. Оновлюєте колір в одному місці — перезбираєте — і всі три платформи отримують нове значення. Розберемо, як це працює, на реальному прикладі.
Що таке Style Dictionary насправді
Це не плагін і не хмарний сервіс. Це build-інструмент — npm-пакет, який запускається командою в терміналі й перетворює токени у код. Ментальна модель проста, три кроки:
- Source — ваші токени у вигляді JSON-файлів (джерело правди).
- Transforms — правила перетворення: як записати колір, як перевести
16у16pxдля вебу і16.0для iOS, як назвати змінну. - Formats — фінальні файли для кожної платформи:
variables.css,Tokens.swift,tokens.xml.
Ви описуєте токени й конфіг один раз. Далі кожна збірка детермінована: той самий вхід завжди дає той самий вихід. Ніякого ручного копіювання hex-кодів між репозиторіями.
Крок 1: токени у JSON
Style Dictionary очікує токени як дерево. У версії 4 нативно підтримується формат W3C DTCG — з полями $value і $type. Починаємо з примітивів (сирі значення):
// tokens/primitive/color.json
{
"color": {
"green": {
"500": { "$value": "#A8FF57", "$type": "color" }
}
}
}
А далі — семантичний шар, який посилається на примітив, а не дублює значення. Це та сама трирівнева ієрархія (primitive → semantic → component), про яку варто думати ще на етапі дизайну:
// tokens/semantic/color.json
{
"color": {
"action": {
"primary": { "$value": "{color.green.500}", "$type": "color" }
}
}
}
Фігурні дужки {color.green.500} — це посилання (alias). Style Dictionary розв'яже його під час збірки. Зміните green.500 — оновляться всі токени, що на нього посилаються. Це і є суть: значення живе в одному місці.
Крок 2: конфіг збірки
Файл config.json описує, звідки брати токени і які платформи генерувати. Кожна платформа — це transformGroup (готовий набір перетворень) + buildPath + список файлів із форматом:
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformGroup": "css",
"buildPath": "build/web/",
"files": [{ "destination": "variables.css", "format": "css/variables" }]
},
"ios": {
"transformGroup": "ios-swift",
"buildPath": "build/ios/",
"files": [{ "destination": "Tokens.swift", "format": "ios-swift/class.swift" }]
},
"android": {
"transformGroup": "android",
"buildPath": "build/android/",
"files": [{ "destination": "colors.xml", "format": "android/resources" }]
}
}
}
Запускаєте npx style-dictionary build — і в теці build/ з'являються три файли. Той самий color.action.primary стане --color-action-primary у CSS, colorActionPrimary у Swift і <color name="color_action_primary"> в Android. Одне джерело, три ідіоматичні виходи.
Що на виході: три файли з одного токена
Найкраще суть видно на результаті. Один семантичний токен color.action.primary, який посилається на color.green.500, після збірки перетворюється на три ідіоматичні файли — кожен у стилі своєї платформи:
/* build/web/variables.css */
:root { --color-action-primary: #A8FF57; }
// build/ios/Tokens.swift
public static let colorActionPrimary = UIColor(...)
<!-- build/android/colors.xml -->
<color name="color_action_primary">#FFA8FF57</color>
Зверніть увагу: розробнику вебу не треба знати про Swift, а iOS-інженер не бачить XML. Кожен працює зі звичним для себе форматом, але значення гарантовано однакове — бо народилося з одного рядка JSON. Оце і є «single source of truth» не на словах, а в коді.
Transforms і formats: чому це не просто пошук-заміна
Різні платформи мають різні конвенції — і Style Dictionary це знає. Кілька прикладів, що робить transformGroup за вас:
- Іменування. Web любить
kebab-case, Swift —camelCase, Android —snake_case. Трансформname/*робить це автоматично. - Розміри.
16стане1remабо16pxдля вебу,16.0(CGFloat) для iOS,16dp/16spдля Android. - Кольори. Один hex перетворюється на
UIColorдля iOS чи Android-ресурс з альфою у правильному порядку байтів.
Якщо стандартних трансформів мало — пишете власний у JavaScript. Наприклад, додати префікс до всіх CSS-змінних чи згенерувати Jetpack Compose-об'єкт замість XML. Саме тут дизайн-система перестає бути статичним артефактом і стає програмованим конвеєром — навичка, яку ми окремо розбираємо на YouTube-каналі UX Hero на живих прикладах.
Темна тема і мультибренд
Тут криється найпоширеніша помилка новачків: генерувати окремий набір токенів на кожну тему й дублювати примітиви. Правильний підхід — перевизначати лише семантичний шар. Тримаєте одну колекцію примітивів, а для теми підмінюєте семантичні посилання:
// світла: color.bg.primary → {color.white}
// темна: color.bg.primary → {color.gray.900}
На практиці роблять два прогони збірки з різними source-теками (base + theme-overrides) або використовують один конфіг із кількома вихідними файлами. Результат для вебу — два блоки CSS-змінних під :root і [data-theme="dark"]; для iOS — Swift-структура з light/dark значеннями. Логіка перемикання тем при цьому лишається однаковою на всіх платформах, бо джерело — одне.
Де тут Figma
Style Dictionary не читає Figma напряму — йому потрібен JSON. Міст будують плагіном Tokens Studio, який експортує Figma Variables у JSON і пушить у Git. Повний ланцюг виглядає так:
Figma Variables → Tokens Studio → JSON у Git →
Style Dictionary (CI) → CSS + Swift + Kotlin
Дизайнер міняє токен у Figma, пушить — CI-пайплайн (GitHub Actions) запускає збірку й відкриває PR з оновленими файлами для всіх трьох платформ. Дизайнер стає джерелом правди для коду, а не просто малює макет, який хтось потім вручну переносить. Якщо ви ще обираєте між нативними Figma Variables і Tokens Studio — це окрема розмова з нюансами.
Коли Style Dictionary виправданий, а коли ні: якщо у вас лише веб — рідних CSS-змінних вистачить, зайвий build-крок не потрібен. Style Dictionary окупається з другої платформи: щойно з'являються iOS чи Android, ручна синхронізація перетворюється на постійне джерело розбіжностей.
Три помилки, які коштують часу
- Плоский список токенів без ієрархії. Коли всі значення на одному рівні й без посилань — тему не зробити, а зміна кольору перетворюється на масову заміну. Починайте з примітивів і семантики від першого дня.
- Хардкод замість посилань. Якщо семантичні токени містять сирі hex замість
{color.green.500}— ви втратили головну перевагу. Одне значення = одне місце. - Ручний коміт згенерованих файлів.
build/має генеруватися в CI, а не редагуватися руками. Інакше хтось «швиденько підправить» вихід — і джерело з кодом розійдуться знову.
Від нуля до першої збірки за 30 хвилин
- Створіть проєкт:
npm init -yіnpm i -D style-dictionary. - Додайте теку
tokens/з двома-трьома JSON (примітиви + семантика). - Створіть
config.jsonз однією платформоюcss— переконайтеся, що збірка працює. - Запустіть
npx style-dictionary buildі подивіться наbuild/web/variables.css. - Додайте платформу
iosабоandroid— і зберіть знову. - Винесіть збірку в GitHub Action на кожен push у теку токенів.
Дизайн-система, що живе тільки у Figma, — це картинка. Дизайн-система, з якої одним прогоном народжуються CSS, Swift і Kotlin, — це інфраструктура. Style Dictionary — найкоротший шлях від першого до другого.