Style Dictionary v5 build that generates platform-specific code from a single source of design tokens (colors, typography, spacings, radii, shapes, borders). Currently emits Kotlin / Jetpack Compose; structured to add Swift / SwiftUI alongside.
npm install
node build.js
Generated output appears under out/<platform>/.
.
├── source/ Figma Tokens Studio export (drop zip contents in as-is)
│ ├── $metadata.json token set order
│ ├── $themes.json theme configurations
│ ├── New Colors Primitives/
│ │ └── Values.json raw palette (zinc.950, blue.500, ...)
│ ├── New Number:String/
│ │ └── Strings/
│ │ └── Values.json font sizes, weights, line heights, Spacer, Radius, Border, Size, Opacity
│ ├── Theme/
│ │ └── Polkadot App Default.json semantic colors (fg.primary -> {Color.zinc.100})
│ └── Typography/
│ ├── Polkadot App Default.json Heading uses Manrope
│ └── Value.json Heading uses Inter
│
├── lib/ Platform-independent analysis
│ ├── utils.js pascal/camel/isReference
│ ├── token-tree.js buildTree, sortedEntries
│ └── typography-analysis.js role/size/weight pairing, skip-log
│
├── platforms/
│ └── compose/ Kotlin / Jetpack Compose emitters
│ ├── kotlin.js ktIdent, hexToComposeColor, FontWeight map
│ ├── colors.js primitives object + abstract palette + concrete palettes
│ ├── typography.js FontFamilies object + abstract Typography + concrete typographies
│ ├── dimensions.js Spacer/Radius/Border (shared generator, config-driven)
│ └── index.js registers SD formatters, runs the pipeline
│
├── build.js Entry point: imports platforms, registers, runs
├── package.json
└── out/ Generated code (gitignored by default; commit if your consumer model needs it)
└── android/
├── colors/
├── typography/
├── spacings/
├── radii/
├── shapes/
└── borders/
- Designer exports tokens from Figma Tokens Studio → produces a zip.
- Extract the zip and replace the contents of
source/with the extracted folder's contents (no renaming — the layout is verbatim). node build.js- Inspect
out/diff and commitsource/.
If Tokens Studio Git sync is set up, step 2 is automatic — Figma writes directly to a repo and you pull instead of unzipping.
Manual copy:
- Run
node build.jsin this repo. - Copy
out/android/contents into the Android project atdesign/src/main/java/io/pcf/polkadotapp/design/configs/. - The generated Kotlin packages match those file paths (
io.pcf.polkadotapp.designsystem.colors.*, etc.) — copy is a direct mirror. - Replace handwritten
Spacings.kt,Typography.kt,FontFamilies.ktwith imports of the generated equivalents; updateTheme.ktto construct and provide them via the existingCompositionLocals.
- Create
platforms/swift/with the same file layout asplatforms/compose/:swift.js— Swift-specific helpers (hex →Color(red: green: blue: opacity:), identifier rules)colors.js,typography.js,dimensions.js— Swift emitters using the same sharedlib/analysisindex.js—register()+run()
- Add
import * as swift from './platforms/swift/index.js'plusswift.register()andawait swift.run()inbuild.js.
The lib/ directory contains all platform-independent logic: token tree building, reference resolution, typography role analysis. Each platform only implements the emission (turning a structured token into a code string).
- Shared analysis, per-platform emission —
lib/knows what tokens are and how they relate;platforms/compose/knows how to write Kotlin. iOS adds an analogous platform without touchinglib/. - Style Dictionary handles reference resolution (
{Color.zinc.950}→#121212) and source-file merging. Each platform registers custom formatters and runs pipelines tailored to its outputs. - DTCG format (
$type,$value) is auto-detected viausesDtcg: true. The Figma Tokens Studio export uses this format natively. - No magic value handling — fractional
Dp, numeric leaves, missing atoms, etc. are emitted faithfully or skipped with a logged reason. Design issues are escalated to the source, not papered over.
The current Figma export has several known issues — see design-tokens-issues.md for the full list to discuss with design.