spike: Figma token sync — native JSON approach (no DTCG, no Style Dictionary) - #2774
Open
peterliu (peterInTown) wants to merge 1 commit into
Open
spike: Figma token sync — native JSON approach (no DTCG, no Style Dictionary)#2774peterliu (peterInTown) wants to merge 1 commit into
peterliu (peterInTown) wants to merge 1 commit into
Conversation
Replaces the DTCG/Style Dictionary approach from the original spike with a
simpler pipeline: fetch.ts calls the Figma Variables API and writes directly
to the existing bpk-foundations-android JSON format, allowing the existing
buildSrc Kotlin pipeline (KotlinPoet formatters, Gradle tasks) to run
completely unchanged.
Pipeline:
npm run tokens:fetch
→ fetch.ts: Figma Variables API → base.raw.android.json
(same format as @skyscanner/bpk-foundations-android)
→ existing buildSrc Kotlin pipeline generates all token files
Tokens covered: semantic colors, spacing, radii, borders, typography
(font sizes, line heights, letter spacings, weights), elevation, animations.
No DTCG. No Style Dictionary. No changes to buildSrc. Node.js is only
needed for the fetch step, not for the token generation.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Introduces a simplified token-sync pipeline that fetches design tokens from the Figma Variables API and writes them directly into the existing bpk-foundations-android JSON format (no DTCG / Style Dictionary), keeping the current Kotlin/Gradle token generation flow unchanged.
Changes:
- Adds
token-sync/src/fetch.tsto fetch/transform Figma Variables intobase.raw.android.json. - Adds a
token-syncNode workspace (package.json) to run the fetch step viatsx. - Adds the generated
token-sync/tokens/base.raw.android.jsonin the expected foundations format.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| token-sync/src/fetch.ts | Implements Figma Variables API fetch + transformation into bpk-foundations-android JSON. |
| token-sync/package.json | Adds Node scripts/deps to run the token fetch step. |
| token-sync/tokens/base.raw.android.json | Adds generated output JSON consumed by the existing Kotlin pipeline. |
Files not reviewed (1)
- token-sync/package-lock.json: Generated file
Comment on lines
+113
to
+121
| const targetRaw = target.valuesByMode[primitivesModeId] ?? | ||
| target.valuesByMode[Object.keys(target.valuesByMode)[0]]; | ||
| if (!targetRaw || isFigmaAlias(targetRaw)) { | ||
| // Two-level alias — resolve further | ||
| if (isFigmaAlias(targetRaw)) { | ||
| return resolveValue(targetRaw, variables, primitivesModeId); | ||
| } | ||
| return null; | ||
| } |
Comment on lines
+179
to
+191
| // Category mapping: Figma top-level group → bpk-foundations category + prop type | ||
| const PRIMITIVES_CATEGORY_MAP: Record<string, { category: string; type: BpkProp['type'] }> = { | ||
| 'Spacing': { category: 'spacings', type: 'size' }, | ||
| 'Radius': { category: 'radii', type: 'size' }, | ||
| 'Border': { category: 'borders', type: 'size' }, | ||
| 'Heights': { category: 'spacings', type: 'size' }, | ||
| 'Modal': { category: 'spacings', type: 'size' }, | ||
| 'Type/Size': { category: 'typesettings', type: 'font-size' }, | ||
| 'Type/Line-height': { category: 'typesettings', type: 'size' }, | ||
| 'Type/Letter-spacing': { category: 'letter-spacings', type: 'letter-spacing' }, | ||
| 'Type/Weight': { category: 'font-weights', type: 'string' }, | ||
| 'Type/Family': { category: 'typesettings', type: 'font' }, | ||
| }; |
Comment on lines
+316
to
+327
| // For letter-spacing, convert from px (Figma) to em ratio | ||
| // Figma stores letter-spacing in px; foundations uses em (relative to font size) | ||
| // We map tight/loose values directly | ||
| let value = light.value; | ||
| if (mapped.type === 'letter-spacing') { | ||
| const numVal = parseFloat(value); | ||
| if (!isNaN(numVal)) { | ||
| // Convert px offset to em: divide by a reference size of 16 | ||
| const emVal = Math.round((numVal / 16) * 100) / 100; | ||
| value = String(emVal === 0 ? 0 : emVal); | ||
| } | ||
| } |
Comment on lines
+347
to
+351
| const output: BpkFoundationsJson = { | ||
| aliases, | ||
| props, | ||
| propKeys: Object.keys(props), | ||
| }; |
Comment on lines
+1
to
+14
| { | ||
| "name": "backpack-android-token-sync", | ||
| "version": "0.0.0", | ||
| "private": true, | ||
| "type": "module", | ||
| "scripts": { | ||
| "tokens:fetch": "tsx src/fetch.ts" | ||
| }, | ||
| "devDependencies": { | ||
| "dotenv": "^16.4.7", | ||
| "tsx": "^4.19.2", | ||
| "typescript": "^5.7.3" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fetch.tscalls the Figma Variables API and writes directly to the existingbpk-foundations-androidJSON formatbuildSrcKotlin pipeline (KotlinPoet formatters, all Gradle tasks) runs completely unchangedPipeline:
Token coverage vs old bpk-foundations-android:
Higher counts reflect tokens added to Figma since the package was last published.
Context
See PoC doc and implementation approaches decision for background on why this approach was explored over the original DTCG spike.
Test plan
cd token-sync && npm install && npm run tokens:fetch— verifytoken-sync/tokens/base.raw.android.jsonis written./gradlew generateTokens— verifyBUILD SUCCESSFULand all token files regeneratedBpkColors.kt,BpkSpacing.kt,BpkFontSize.kthave expected valuesNot yet done (next steps)
BpkButtonColors.ktetc.)🤖 Generated with Claude Code