design-RFC-006 — Cross-language token distribution
Decides how koder_kit (Flutter / Dart) and koder_web_kit (JS) and future native consumers (Kotlin Android, Swift iOS, Rust embedded) receive the canonical Verge tokens. Evaluates copy-on-build vs publish-and-import. Recommendation: copy-on-build via CI workflow for v0; promote to a published koder_design_tokens package per language when consumer count crosses 3.
designRFC006 — Cross-language token distribution
*tatus* v0.1.0 — Draft. Decides distribution mechanics for the per
language token files designgen already emits (#059).
R1 — Problem
tools/design-gen emits per-language token files under dist/tokens/:
tokens.css/tokens.scss— for web stylesheetstokens.json— DTCGaligned, machinereadabletokens.dart— Flutter consumerstokens.kt— Android / Kotlin Multiplatformtokens.swift— iOS / macOS nativetokens.d.ts— TypeScript types
These files are emitted to dist/ at build time but the consumers (engines/sdk/koder_kit, engines/sdk/koder_web_kit, future native SDKs) currently re-declare tokens by hand. Structural drift between spec and implementation.
The token export side is solved (design-gen #059); the distribution side — how do consumers receive the export? — is open.
R2 — Options evaluated
Option A — Copyonbuild (CI workflow copies into each consumer)
Workflow runs after design-gen ships; for each registered consumer, copy the relevant file into the consumer's repo / subdir, open a PR (or push directly to a branch the consumer auto-merges from).
*ros*
- No publication step needed (no pub.dev / npm / Maven Central
account-management).
- Atomic with design-gen release (token bump propagates same hour).
- 100% self
hosted; aligns with `policies/selfhosted-first.kmd`. - Drift impossible — consumer's copy IS the source export.
*ons*
- Consumers can't pick which token version to consume (always latest).
- Each consumer needs a matching CI workflow on their side.
- Doesn't scale gracefully past 5–6 consumers.
Option B — Publishandimport (publish per-language package)
Publish a koder_design_tokens package per language ecosystem:
- pub.dev (Dart)
- npm (TypeScript / JS)
- Maven Central (Kotlin)
- Swift Package Manager (Swift)
Consumers import as a regular dependency, bump version semantically.
*ros*
- Consumers control version (pin to ^0.x for stability).
- Scales to any consumer count (industry-standard import).
- Discoverable by community.
*ons*
- Each ecosystem needs publication credentials + automation
(pub.dev token, npm token, Maven publishing pipeline, SPM repo).
- Latency between code change and consumer adoption (publication +
consumer bumps version).
- Conflicts mildly with
self-hosted-first.kmdG1 if the ecosystemregistries go down (pub.dev / npm / Maven are external infra).
Option C — Hybrid: copyonbuild v0, publish at scale-out
Start with Option A (copyonbuild); promote to Option B per ecosystem once that ecosystem has ≥ 3 consumers (per policies/reuse-first.kmd SDK-extraction threshold).
*ros*
- Defers publication overhead until justified by consumer count.
- Avoids premature standardization.
- Each ecosystem promotes independently when ready.
*ons*
- Two distribution mechanisms coexist during transition periods.
- Some bookkeeping of "which ecosystem is on which mode" needed.
R3 — Decision criteria
| Gate | A (Copy |
B (Publish) | C (Hybrid) |
|---|---|---|---|
| G1 — self |
✅ | ⚠ external registries | ✅ start; ⚠ promotes |
| G2 — reuse-first SDK ≥ 3 consumers gate | starts at 0 | starts at 0 (over-engineered) | ✅ promotes when threshold met |
| G3 — latency | atomic | publication + consumer bump | atomic v0 |
| G4 — consumer control of version | none (always latest) | full | starts none; gains when promoted |
| G5 — community discoverability | none | high | gains when promoted |
R4 — Recommendation
*dopt Option C (hybrid)*with the following thresholds:
| Ecosystem | v0 mode | Promotion trigger |
|---|---|---|
| Dart (Flutter) | copykoder_kit |
≥ 3 Flutter consumers ratified beyond koder_kit |
| TypeScript / JS | copykoder_web_kit |
≥ 3 JS consumers beyond koderwebkit |
| Kotlin / Android | copy |
≥ 3 Android consumers beyond koder_kit |
| Swift / iOS | copy |
≥ 3 iOS consumers beyond koder_kit |
| CSS / SCSS | copy |
≥ 3 standalone CSS consumers |
policies/reuse-first.kmd SDK-extraction threshold (≥ 3 consumers) serves as the natural promotion trigger.
R5 — Implementation tickets (post-ratification)
Subtickets in `tools/designgen (or a new tools/token-bridge`):
tools/token-bridge#001— CI workflow: on every design-gen tag,render token files for each ecosystem.
tools/token-bridge#002—koder_kitcopy worker:dist/tokens/tokens.dart→koder_kit/lib/src/tokens/verge_tokens.dart+ commit withtokens-sync: bump to design-gen vX.Y.Z.tools/token-bridge#003—koder_web_kitcopy worker:dist/tokens/tokens.css+tokens.d.ts→koder_web_kit/src/tokens/+ commit.tools/token-bridge#004— Drift check: per-PR CI in koder_kit /koderwebkit fails if local tokens differ from
dist/tokens/checksum.
When promotion threshold hits for an ecosystem, additional sub-ticket to set up the publication pipeline + migrate consumers.
R6 — Cross-references
- Coordinates with
tools/design-gen#059— emission side is done. - Coordinates with
projects/koder-stack#157(Figma kit) — Figmareads
tokens.jsondirectly via the plugin; orthogonal to this RFC's per-language ecosystem question. - Aligns with
policies/reuse-first.kmd≥ 3 consumers SDK-extractionthreshold.
R7 — Risk mitigation
- *oken rename in Verge breaks consumer* copy
onbuild forces theCI in each consumer to fail at the bump PR — consumer fixes before merge. No silent breakage.
- *I complexity grows* keep the copy worker generic
(
tools/token-bridge) so adding a new consumer is configuration, not new code. - *ock
step releases* designgen tags drive consumer bumps;consumers MAY pin to an older version via revert if a token bump introduces a regression. (Promoted
topublish ecosystems get proper semver pinning out of the box.)
Não-escopo
- Per
locale tokens (i18n) — token names are universal; localeawareformatting (numbers, dates) is a runtime concern, not a token-bundle concern.
- Run
time token livereload — out of v0; token bumps go throughthe consumer's build + release cycle.
- Theming over Verge (Material 3 preset overrides, custom presets) —
handled by
canonicalPresetsin designgen / uistyle.kmd, not by this distribution RFC.