~/swaraj.dev
Back to all posts
April 19, 20261 min read

Sharing UI Components Across React Native and Next.js with a Monorepo

Leverage a monorepo to write a single TypeScript component that works in both React Native and Next.js, reducing duplication and keeping UI consistent.

monoreporeact nativenext.jstypescript

Insight

A common misconception is that React Native and web UI must be maintained in separate codebases. By using a monorepo (Yarn Workspaces or npm workspaces) and abstracting platform‑specific primitives, you can share most of the component logic and styling. The key is to isolate the parts that differ—View vs div, StyleSheet vs CSS modules—behind a tiny platform shim.

Example

// packages/ui/Button.tsx (shared)
import { Platform } from 'react-native';
import { Pressable, Text, View } from 'react-native';
import styles from './Button.module.css'; // web CSS module

export const Button = ({ title, onPress }: { title: string; onPress: () => void }) => {
  const Component = Platform.OS === 'web' ? 'button' : Pressable;
  return (
    <Component onPress={onPress} className={styles.btn}>
      <Text>{title}</Text>
    </Component>
  );
};

Takeaway

Put shared UI in a workspace package, use Platform.OS or conditional imports to bridge the tiny API gaps, and you’ll ship a unified look with far less duplicated code.