One component API for web, iOS, and Android unifies OTF's SDK design system
The hard thing about design systems isn’t the Figma file. It’s shipping the same component API, look, and feel to both web and mobile, so your codebase doesn’t fork the moment you want a button to work everywhere. Everyone claims "cross-platform," but look under the hood: props, theming, and even component names diverge. OTF’s approach is boringly strict — we force from @otfdashkit/ui (web) and from @otfdashkit/ui-native (mobile) to share not just a name, but a prop signature and visual tokens. The win: you swap a theme or change a prop, and your design intent lands the same way in browsers and on iOS/Android. The punchline: no more copy-pasting a look, no more chasing two sets of transient design-systems.
Let’s unpack how we built this, what it looks like in practice, and why fighting the cross-platform churn at the component and token level is the durability move.
One prop interface: the make-or-break constraint
Radix and Tamagui are as far apart as component libraries get. Radix lives for the DOM and React, Tamagui targets React Native primitives, ships its style objects to both native and web. Most shops treat this split as fatal. They maintain parallel Button implementations:
// web/Button.tsx
export function Button(props: { color?: string; onClick?: () => void }) {
// ...renders <button> or <div role="button">
}
// native/Button.tsx
export function Button(props: { color?: string; onPress?: () => void }) {
// ...renders <TouchableOpacity>
}This looks harmless until you realize every prop, event, and modifier is different. onClick vs. onPress, className vs. style, focus rings, active states, and accessibility all drift.
OTF cuts this off at the root. Every component in @otfdashkit/ui and @otfdashkit/ui-native shares the same name, same prop signature, and effect:
/* Shared API: works in both /ui and /ui-native */
<Button
size="lg"
variant="ghost"
icon={<Check />}
onPress={() => { /* navigate */ }}
/>The contract: any component used in the docs renders and behaves the same on all platforms, or it doesn’t ship.
Takeaway: Prop drift is the death of cross-platform. Merging interface is worth more than feature-drifted "parity."
Design tokens: one set, platform-native output
Most design systems punt on tokens: "We’ll handoff the Figma variables and restyle later." This always means two sets of tokens, two inconsistent palettes, two color modes, and hundreds of bugs.
@otfdashkit/tokens is a design-token compiler. You write one set of variables:
// tokens/otf.tokens.ts
export const tokens = {
color: {
primary: "#1e293b",
background: "#f8fafc",
border: "#64748b",
accent: "#818cf8",
},
radii: {
sm: 4,
md: 8,
lg: 16,
},
// ...typography, spacing
}On web, this compiles to CSS variables (using style-dictionary under the hood), shipped in a CSS file:
:root {
--color-primary: #1e293b;
--color-background: #f8fafc;
--color-border: #64748b;
--color-accent: #818cf8;
--radii-sm: 4px;
--radii-md: 8px;
--radii-lg: 16px;
/* ... */
}On native, tokens become JS objects (or themeable constants) consumed by Tamagui’s theme system:
// tokens/otf-theme.ts
export const otfTheme = {
colorPrimary: "#1e293b",
colorBackground: "#f8fafc",
colorBorder: "#64748b",
colorAccent: "#818cf8",
radiiSm: 4,
radiiMd: 8,
radiiLg: 16,
// ...
}Win: Switch a theme, and it flips perfectly on both web and native. No divergence in color, no guesswork mapping corner radii.
11 production screens. Login, database, payments — all wired.
The SaaS Dashboard Kit ships everything already connected. Nothing to set up. Live demo at saas.otf-kit.dev.
Visual identity enforced at the code level
The promise: is visually identical on every platform. This means:
- Same exact shape, spacing, radius.
- Same color palette, font, and icon scale.
- Same interaction affordances (active, disabled, focus state).
Enforcement is not hand-wavy. OTF ships a 24-item design checklist that runs before any component update merges. If the web and native screenshots don’t match, the code can’t ship.
Contrast: Traditional two-stack shops end up rewriting UI for every marketing push, every new color mode, every accessibility review. OTF removes that dead work.
Closing: design shouldn’t get rebuilt for every platform
If you’re tired of living in two worlds—one for web, one for mobile—but don’t buy "write once, shoddily everywhere," try the OTF method: shared tokens, strict prop contracts, local themes, zero second-guessing what your button looks like. Engineers get velocity and a codebase that endures. Designers see their work land as intended. The rest is churn you never need to debug again.
Ship with a single source of visual truth—across every screen.
Originally published at otf-kit.dev — full-stack kits your AI coding agent can actually ship to production. See the kits →
Ship the product, not the setup.
- 11 production screens — auth, billing, team, analytics, settings
- Real database, payments, and login — all wired on day 1
- AI configs pre-tuned so your agent extends instead of regenerates