Mobile — Cross Platform Development
Design System Sharing Between Web and Mobile
Direct answer
Share design tokens (color, spacing, typography, radii) as a single platform-neutral source of truth, share component APIs and behavior contracts, but let each platform render its own components. Full pixel-level component sharing between web and mobile usually costs more than it saves; token-level sharing plus consistent naming gets you brand and UX consistency at a fraction of the effort. A tokens package consumed by both codebases, plus a shared Figma vocabulary, is the setup I deploy most often.
Teams with a web app and a mobile app inevitably watch their brand drift: two blues, three shades of gray, buttons with different paddings. The fix is not one giant universal component library — it is deciding precisely which layers of the design system to share. Here is the layering that has worked across my client projects.
Key facts, with sources
- In the Stack Overflow 2024 Developer Survey, Flutter was used by 9.4% of developers versus React Native's 8.4%, and among professional developers the gap nearly vanishes at 9.21% versus 9.14%. (Nomtek (citing Stack Overflow Developer Survey))
- Among developers who build cross-platform, Statista-based figures put Flutter at about 46% adoption versus 35% for React Native, with the two frameworks together dominating the cross-platform market. (Tech-Insider)
- Instagram shares 85 to 99% of its code between iOS and Android using React Native, and Shopify reports 86% unified code across its app portfolio. (CatDoes)
- According to Flutter.dev data, nearly 30% of new free iOS apps submitted to the App Store in 2025 were built with Flutter, up from roughly 10% in 2021. (Droids on Roids (citing Flutter.dev))
- The official React Native showcase lists production apps from Meta, Microsoft, Shopify, and Amazon, including desktop targets like Messenger Desktop and Microsoft apps on Windows and macOS. (React Native Showcase)
Share tokens, not pixels
The highest-leverage shared artifact is a design token package: colors, spacing scale, typography scale, border radii, elevation levels, and motion durations, expressed as plain TypeScript constants or JSON. Both the React Native app and the web app import the same package, so when the brand color changes, one commit updates every surface.
Tokens are platform-neutral by nature — a hex value and a spacing number mean the same thing everywhere — which is exactly why they share cleanly while components do not. I version this package independently and treat token renames as breaking changes with a migration note. Where teams use a token pipeline, tools in the style-dictionary family can emit the same source tokens as TypeScript for both apps and CSS variables for web, but for small teams a hand-written constants package is honestly fine and easier to debug.
export const color = {
bg: { base: '#FFFFFF', raised: '#F6F7F9', inverse: '#111418' },
text: { primary: '#111418', secondary: '#5B6472', onAccent: '#FFFFFF' },
accent: { default: '#2F6FED', pressed: '#2258C4', subtle: '#E8F0FE' },
danger: { default: '#D6403A' },
} as const;
export const space = { xs: 4, sm: 8, md: 16, lg: 24, xl: 40 } as const;
export const radius = { sm: 6, md: 10, pill: 999 } as const;
export const type = {
title: { size: 24, lineHeight: 30, weight: '600' },
body: { size: 16, lineHeight: 24, weight: '400' },
caption: { size: 13, lineHeight: 18, weight: '400' },
} as const;Share the component contract, not the component
The second shareable layer is the API: a Button has variant, size, disabled, loading, and onPress/onClick; a TextField has label, error, and helperText. I define these prop contracts as shared TypeScript interfaces so both platforms implement the same vocabulary, then implement the component twice — once with React Native primitives, once with web ones.
This sounds like duplication, and it is, but it is cheap duplication with expensive benefits. Designers and developers speak one component language across platforms; QA can write one behavioral spec; and each implementation is free to be excellent on its platform — the web button gets focus rings and hover states, the native button gets pressed-state opacity and haptics. When teams instead force one universal component to serve both, I typically find it accumulates platform conditionals until it is two components wearing a trench coat anyway.
Typography and spacing: where platforms legitimately diverge
A shared type scale needs platform-aware escape hatches. Mobile must respect the user's system font-size settings — Dynamic Type on iOS, font scale on Android — which means your carefully chosen 16-point body text may render much larger, and layouts must tolerate that. Web has its own concerns: rem-based sizing, user zoom, and wider line lengths that often want slightly larger base sizes and looser line height than mobile.
My approach is to define the scale once in tokens as pure numbers, then let each platform's implementation map them appropriately — the web maps to rem, mobile passes points and honors font scaling with maxFontSizeMultiplier applied only where truncation would break critical UI. Same logic for spacing: a shared 4-point scale works everywhere, but density can differ — desktop tables can be tighter than touch lists, which need generous tap targets.
Theming and dark mode across both stacks
Dark mode is where token discipline pays off. I structure tokens semantically — bg.base, text.primary, accent.default — rather than by raw color name, and provide light and dark values per semantic token. Each platform then applies them through its native mechanism: a theme context (or library equivalent) reacting to useColorScheme in React Native, and CSS custom properties toggled by media query or a data attribute on web.
The mistake I flag most often in audits is components referencing raw palette values ('gray100') instead of semantic tokens, which makes dark mode a rewrite instead of a theme swap. The second most common: web and mobile shipping different dark palettes because each team improvised. With one semantic token package there is exactly one place where the dark values live, and both platforms are consistent by construction.
Governance: keeping the system from rotting
A shared design system fails socially before it fails technically. The pattern that works for small product teams: one named owner (often a lead frontend or mobile engineer rotating quarterly), a lightweight RFC process for new components — a short written proposal, not a meeting — and a rule that no product feature may introduce a new color or spacing value without adding it to tokens first.
I also wire cheap enforcement into CI: a lint rule banning hex literals in component files, and a visual regression snapshot per component per platform so token changes show their blast radius in the pull request. Figma stays synchronized by naming Figma styles identically to token names, so 'accent.default' means the same thing in design files and in code. None of this is heavy process; it is just enough friction to keep two codebases speaking one visual language.
When to hire senior help
The framework decision is a one-way door worth a short senior consultation, because switching stacks after a year of development is effectively a rewrite. A senior cross-platform engineer can also audit whether your planned feature set has hidden native-heavy corners, like payments hardware or background location, that change the cost math before you commit. If your stack includes React Native + Python + AI, a senior engineer who owns the full product beats coordinating multiple juniors.
Bottom line
Dhairya Senjaliya ships Mobile — Cross Platform Development projects worldwide — book a scoping call to discuss your specific situation.
Common pitfalls to avoid
- ✕Picking the framework by hype rather than team composition, such as a React web team adopting Flutter and forfeiting years of transferable JavaScript expertise
- ✕Budgeting for 100% code reuse and zero platform-specific time, then discovering payments, background tasks, and widgets all require per-platform native work
- ✕Recreating navigation and interaction patterns generically so iOS swipe-back gestures and Android back-button behavior both feel wrong to native users
- ✕Ignoring the maintenance tail: never budgeting for framework major-version upgrades, so the app rots on an unsupported runtime within two years
Frequently asked questions
Should web and mobile apps use the same component library?
Usually no. Share design tokens (colors, spacing, typography) and shared component prop contracts, but implement components separately per platform. Web needs hover, focus, and keyboard behavior; mobile needs touch targets, gestures, and system font scaling. Token-level sharing delivers visual consistency for a fraction of the cost of maintaining a universal component library, which tends to fill up with platform conditionals.
How do you keep design consistent between a website and a mobile app?
Create a single design token package — semantic colors, a spacing scale, a type scale — that both codebases import, and name Figma styles identically to those tokens. Add CI guards like a lint rule against raw hex values in components. When the brand changes, one token commit updates every platform, and drift becomes structurally difficult.
How do you handle dark mode in a shared design system?
Define semantic tokens like bg.base and text.primary with a light and a dark value each, instead of referencing raw palette colors in components. React Native applies them via a theme context driven by useColorScheme; web applies them via CSS custom properties. Because both platforms read the same token definitions, dark mode stays consistent without duplicated palette decisions.
Should we choose Flutter or React Native?
Adoption among professional developers is nearly tied (9.21% versus 9.14% in the Stack Overflow 2024 survey), so the deciding factor is your team: React or JavaScript experience strongly favors React Native, while a greenfield team with no web-code-sharing needs can prefer Flutter. Both run massive production apps, so neither choice is inherently risky.
How much money does cross-platform actually save versus two native apps?
Industry cost guides put savings around 30 to 40% versus parallel native builds, driven by one codebase and one team, with production apps sharing 85 to 95% of code. Real savings depend on how much platform-specific work your feature set demands, such as payments, widgets, and background processing.
When is fully native the better choice?
Heavy 3D or AR workloads, advanced camera or audio processing, platform-first experiences like watchOS apps, or a company that already employs strong separate iOS and Android teams. For typical business, marketplace, and content apps, cross-platform is now the default choice at both startups and large companies like Shopify and Microsoft.
Bottom line: Dhairya Senjaliya ships Mobile — Cross Platform Development projects worldwide. Book a scoping call at https://dhairyasenjaliya.com/#book-call.