KinetixUI Library.
Visit kinetixui.com↗
My role.
Founder — product, design system architecture and engineering direction. Self-initiated and open source; no client brief.
- Product strategy — defining the problem and the “no drift” rule the system is held to
- Design-system and token architecture — one DTCG source, compiled per platform
- UI and component design across React, SwiftUI, Jetpack Compose and Flutter
- Accessibility strategy — contrast audited and gated in CI
- Documentation — a docs site built on the library itself
- Implementation and technical direction — CLI, registry and CI
- One design source of truth for four platforms
- WCAG AA as a release gate, not a guideline
- No dark theme existed in the Figma source
- Components had to be ownable, not a locked dependency
The brief.
Every product I'd shipped that spanned web and native ended up with the same quiet tax: a button re-built by hand in React, then again in Swift, then again in Kotlin, each one drifting a shade further from the Figma file every quarter. Dark mode diverged first, then spacing, then which shade of "primary" a given screen actually used.
I set myself the brief I'd have given a client: one design source, no re-implementation, no drift — and it has to hold up under a real accessibility standard, not just look consistent.
The idea.
KinetixUI compiles a single DTCG token source — extracted straight from the Figma file — through Style Dictionary into CSS custom properties, a typed TypeScript object, and native colour and type sets for SwiftUI, Jetpack Compose and Flutter. Every component in the registry is styled only against that semantic layer, never a hardcoded hex, so a token edit re-skins the button on all four platforms at once.
Installation works like ownership, not dependency: a first-party CLI (npx @kinetixui/cli add button) resolves a component's registry entry and writes the real source into your project — the same model shadcn popularized — rather than locking you to a version behind a black-box import.
One source, four outputs.
Colour ramps, spacing, radius and type all start as DTCG tokens pulled from Figma variables, then run through Style Dictionary once per theme. Light and dark aren't a flip of each other — dark never existed in the source file, so it's synthesized as its own independent palette, checked against the same contrast bar as light.
Copy the code, own the code.
Every component ships a canonical React implementation plus illustrative SwiftUI, Jetpack Compose and Flutter snippets, one keyed map so there's a single source of truth per platform. The CLI and a shadcn-compatible JSON registry both read from it — add button resolves dependencies and writes it straight into your tree.
Charts that re-theme for free.
The chart recipes wrap Recharts and draw every colour from the --chart-1…8 tokens, so a palette change reaches the dashboard along with the buttons. Each cartesian recipe carries keyboard data-point navigation and a screen-reader table alternative, not just a canvas.
Trust the audit, not the vibe.
A script resolves every semantic colour pair, light and dark, and checks it against WCAG AA before anything ships — CI fails the build on a regression instead of catching it in a design review. The docs site is the proof: built entirely on @kinetixui/ui and @kinetixui/tokens, in the same themes it documents.
Key decisions.
-
Compile every platform from one token source
Why The recurring failure was drift — a button re-built per platform, each a shade off the Figma file. A single DTCG source makes “change the token once” literally true.
Trade-off Components may only be styled against the semantic layer — never a hardcoded value — which rules out platform-specific shortcuts.
-
Synthesize dark mode as its own palette
Why Flipping lightness on the light ramp read muddy and failed contrast exactly where focus rings and destructive actions needed it most.
Trade-off More work upfront than mirroring the light theme.
-
Ship components as source you copy, not a dependency you import
Why Customising one button becomes a one-file edit instead of a fork of the library.
Trade-off Once copied, a component is yours to maintain — it no longer updates itself.
-
Enforce four-platform parity in CI, with documented exceptions
Why A parity rule that is only aspirational drifts. A component isn't done until it exists on all four surfaces or is a recorded exception.
Trade-off Some components are deliberately React-only — for example a drag-and-drop board that would need a from-scratch accessible native implementation on each platform.
-
Gate accessibility in the build, not in review
Why A script resolves every semantic colour pair, light and dark, against WCAG AA and fails the build on a regression.
Trade-off The gate is itself code that can be wrong — see the resolver bug under learnings.
The ship.
KinetixUI shipped as three published npm packages (@kinetixui/tokens, @kinetixui/ui, @kinetixui/cli) sharing one version line, released through Changesets on every merge to main; a Gradle package for Jetpack Compose, a SwiftPM package for SwiftUI and a Dart package for Flutter, each compiled and tested per-platform in CI; and kinetixui.com itself — docs, component gallery, colour system, chart gallery and a theme builder — built entirely on the library it documents.
The four-platform rule is enforced, not aspirational: a component isn't considered done until it exists on all four surfaces or is a documented exception, and CI fails the build if the generated token output or registry drifts from source.
What shipped.
A component that used to be re-built by hand in React, then Swift, then Kotlin — drifting a shade further from the Figma file each quarter — is now compiled to all four platforms from one token source.
Checkable: kinetixui.com is built on the library it documents, and the snapshot below is counted from the public repository.
Product snapshot.
Snapshot · September 2026
- Components
- 98 documented in the component manifest
- On all four platforms
- 90 8 are documented exceptions with a stated reason
- Chart recipes
- 36 as listed on the chart gallery
- Packages
- 6 3 on npm — tokens, ui, cli — plus SwiftUI, Compose and Flutter packages
Counted from the KinetixUI repository (component manifest, platform-parity and package files) as of 21 September 2026. These figures move as the project does — the live site is the current source.
What I'd do again.
Synthesize dark mode as its own palette, not a mirror. The source file never had one — flipping lightness on the light ramp read muddy and failed contrast in exactly the places focus rings and destructive actions needed it most. Building an independent dark palette from the start cost more upfront and paid it back every theme since.
Audit the auditor. The contrast-check script that gated every release had a resolver bug silently skipping one token pair — and the docs page cited that same script as proof everything passed. A script you trust for compliance needs its own review, not just a green check mark.
Ownership is the feature, not a footnote. Letting people copy a component's real source in, instead of importing a black box, turned "can you customize this one button" from a fork-the-library problem into a one-file edit.