How to Share Code Across iOS, Android, and Web with React Native In 2025

In 2025, are your business applications truly reaching every user, everywhere? The demand for consistent, high-quality experiences across iOS, Android, and the Web has never been higher. With a 2025 report estimating that applications with both web and mobile experiences will generate 70% of all global software revenue, a unified code base is no longer just an option—it’s a strategic imperative.

Why a Unified Codebase is a Smart Business Strategy for 2025

In 2025, businesses need to provide a consistent, high-quality experience on iOS, Android, and the Web. The old idea of “write once, run anywhere” is now a key business strategy.

React Native has grown beyond being just a mobile framework. It is now a top platform for building apps for all three major platforms from a single codebase. This guide explains why this approach is important and how to do it with modern tools.

The Business Benefits of a Single Codebase

Using a universal framework like React Native provides clear business advantages that directly affect a company’s bottom line.

  • Lower Costs and More Efficient Teams: Instead of having separate teams for iOS, Android, and the Web, a company can have one focused team of React Native developers. This unified model can reduce development costs by up to 40% in 2025. It saves money by reducing duplicated work and making it easier to hire from the large pool of JavaScript and React developers.
  • Faster Time-to-Market: With a single codebase, new features can be built and released on all platforms at the same time. Some teams share between 85% and 99% of their code for complex features. This means a new feature can be built once and shipped to all users much faster than with separate, platform-specific development.
  • Consistent Brand and User Experience: A single codebase is the best way to ensure your app looks and feels the same on every device. By sharing UI components and business logic, you create a consistent experience that strengthens your brand identity and is easy for users to navigate.
  • Simpler Long-Term Maintenance: The “fix once, deploy everywhere” approach makes maintenance much easier. A bug fix is made once in the shared code and is fixed on all platforms at the same time. This reduces the risk of platform-specific bugs and keeps the entire app ecosystem up-to-date.

The business case for this approach is clear. A 2025 report estimates that applications with both web and mobile experiences will generate 70% of all global software revenue. This shows that a universal app strategy is not just about saving money; it’s about driving sales and growing your market share.

The Core Technology Stack: Expo and React Native for Web

Building a universal app with React Native is made possible by two key technologies working together: React Native for Web provides the ability to run your mobile app in a browser, and the Expo framework provides the tools to build and manage it all.

React Native for Web: The Bridge to the Browser

React Native for Web is an open-source library that translates your React Native code so it can run in a web browser. 

It works by taking the basic React Native components and mapping them to standard HTML tags. For example:

  • A <View> becomes a <div>
  • A <Text> becomes a <span>
  • An <Image> becomes an <img>

This allows you to reuse most of the UI and business logic from your iOS and Android mobile apps for your web application, saving a huge amount of development time.

Expo: The De Facto Standard Framework for 2025

While React Native for Web handles the translation to the browser, the Expo framework is what you use to manage the entire development, build, and deployment process.

Expo has grown into a powerful, production-ready framework. It is now the only native framework officially recommended by Meta’s React Native team. This shows its stability and makes it the standard choice for new projects in 2025.

Why Expo is Essential for Universal Apps

Expo makes building universal apps practical and efficient. Here’s why:

  • Zero-Configuration Setup: Expo handles all the complex setup for native mobile development. A developer can start building a universal app right away without ever needing to open Xcode or Android Studio.
  • Comprehensive SDK: Expo provides an SDK with over 100 ready-to-use libraries that give your app cross-platform access to native device features like the camera, notifications, and location services.
  • Expo Application Services (EAS): EAS is a set of cloud services that automates the entire process of building and releasing your app. This includes cloud-based builds (EAS Build), automatic submissions to the app stores (EAS Submit), and Over-the-Air (OTA) updates that let you send small bug fixes to users instantly without needing a new app store release.

Architectural Blueprint: How to Structure a Universal Application

To build and maintain a universal application effectively, you need a smart architectural approach. The industry-standard way to do this is with a monorepo.

The Monorepo Strategy: A Single Source of Truth

The best way to build a universal application is with a monorepo. A monorepo is a single code repository that holds the code for multiple projects—in this case, your mobile app and your web app. This makes it much easier to share code and manage dependencies between them. 

A common and effective monorepo structure looks like this:

/

├── apps/

│   ├── mobile/      # The Expo React Native app (iOS & Android)

│   └── web/         # The Next.js web app

├── packages/

│   ├── ui/          # Shared UI components (Button, Card, etc.)

│   └── shared/      # Shared business logic, hooks, and API services

├── package.json     # Root file defining the workspaces

└── tsconfig.json    # Root TypeScript configuration

  • The apps/ folder holds the platform-specific code for your mobile and web applications.
  • The packages/ folder holds all the code that is shared between the mobile and web apps, like UI components and business logic.

This clear separation makes the codebase easy to manage.

Navigating the Dependency Dilemma

The biggest technical challenge with a React Native monorepo is managing dependency conflicts.

The Problem: React Native and Expo need to use a specific version of React to be stable on mobile. At the same time, your web framework (like Next.js) often works best with the latest version of React. This can create major problems, often called “dependency hell.”

The Solution for 2025: The best way to solve this is to use a modern package manager that can handle these conflicts. pnpm is the top choice because it allows different apps in the same monorepo to use different versions of the same package without causing issues.

The newest versions of the Expo SDK (52 and later) have been updated to work better with monorepos that use tools like pnpm. This makes it the most stable and recommended setup.

How to Share Code Across iOS, Android, and Web with React Native: A 2025 Tutorial

Building your app with a single codebase is one of the smartest business decisions you can make in 2025. The old method of managing separate teams and code for iOS, Android, and the web is simply too slow and expensive.

With a modern framework like React Native, you can write your code once and deploy it on every platform. This guide will show you how, but let’s first cover why this is so important.

The Three Core Advantages

1. Massive Savings

You only need one team and one codebase. This unified approach can cut development costs by up to 40% and dramatically speeds up your launch time, as new features roll out everywhere at once.

2. Perfect Consistency

A shared codebase is the best way to guarantee your app looks, feels, and works identically on a phone, tablet, or desktop. This creates a seamless experience for your users and strengthens your brand.

3. Simplified Maintenance

When you find a bug, you fix it once. The solution is then deployed everywhere. This drastically reduces your long-term maintenance costs and keeps your app stable across all platforms.

Given that apps available on both web and mobile are projected to generate 70% of all software revenue, this is more than a technical choice—it’s a critical business strategy.

Why a Unified Codebase is a Smart Business Strategy for 2025

In 2025, businesses need to provide a consistent, high-quality experience on iOS, Android, and the Web. The old idea of “write once, run anywhere” is now a key business strategy.

React Native has grown beyond being just a mobile framework. It is now a top platform for building apps for all three major platforms from a single codebase. This guide explains why this approach is important and how to do it with modern tools.

The Business Benefits of a Single Codebase

Using a universal framework like React Native provides clear business advantages that directly affect a company’s bottom line.

  • Lower Costs and More Efficient Teams: Instead of having separate teams for iOS, Android, and the Web, a company can have one focused team of React Native developers. This unified model can reduce development costs by up to 40% in 2025. It saves money by reducing duplicated work and making it easier to hire from the large pool of JavaScript and React developers.
  • Faster Time-to-Market: With a single codebase, new features can be built and released on all platforms at the same time. Some teams share between 85% and 99% of their code for complex features. This means a new feature can be built once and shipped to all users much faster than with separate, platform-specific development.
  • Consistent Brand and User Experience: A single codebase is the best way to ensure your app looks and feels the same on every device. By sharing UI components and business logic, you create a consistent experience that strengthens your brand identity and is easy for users to navigate.
  • Simpler Long-Term Maintenance: The “fix once, deploy everywhere” approach makes maintenance much easier. A bug fix is made once in the shared code and is fixed on all platforms at the same time. This reduces the risk of platform-specific bugs and keeps the entire app ecosystem up-to-date.

The business case for this approach is clear. A 2025 report estimates that applications with both web and mobile experiences will generate 70% of all global software revenue. This shows that a universal app strategy is not just about saving money; it’s about driving sales and growing your market share.

The “How”: Architecting Your Universal Project

To build an application that shares code across web and mobile, you’ll need a monorepo. Think of this as a single, organized “home” for all your project’s code.

Step 1: Set Up the Monorepo Structure

The standard architecture is clean and logical. You’ll have two main folders at the root of your project: apps and packages.

  • apps/: This folder holds the code for each specific platform. You’ll typically have one folder for your Expo (iOS and Android) mobile app and another for your Next.js web app.
  • packages/: This is where the magic of code sharing happens. It contains all the reusable code, such as your UI library (buttons, forms, etc.) and shared logic (API functions, hooks, and types).

Step 2: Use pnpm to Handle Dependencies

A classic challenge in monorepos is that different apps need different versions of the same package. For example, your Expo mobile app requires a specific version of React to be stable, while your Next.js web app might use a newer one. This creates a conflict.

The solution in 2025 is to use pnpm as your package manager. 

pnpm is specifically designed to solve this problem. It installs packages in a way that allows each app in your monorepo to use its own required version without interfering with the others. It’s the stable, officially supported approach for modern universal React Native development.

The “How”: Building Your Shared Codebase

Excellent, your project is now structured to share code. Here’s how you build the reusable parts that will power all your applications.

Step 3: Build a Universal UI Kit

The core of your project is a library of universal UI components that you’ll create in your packages/ui folder.

You build these components using standard React Native elements. For example, using the <Pressable> component allows you to create a universal button that works perfectly as a native element on iOS and Android and as a standard HTML element on the web. The key principle is build it once, use it everywhere.

Step 4: Handle Platform-Specific Code

Inevitably, some code will need to be different for web and mobile. React Native gives you two clean options for this:

  1. For Small Adjustments: Use the Platform.OS module to add simple, inline logic. This is perfect for minor style changes, like adding extra padding only on iOS (Platform.OS === ‘ios’).
  2. For Major Differences: Use platform-specific file extensions. You can create different versions of a file (e.g., MyComponent.ios.js, MyComponent.android.js, MyComponent.web.js). The correct file will be automatically used on each platform when you import it.

Step 5: Share Your App’s Logic and Data

Sharing code goes beyond just the UI. You should also centralize your app’s “brain”—the business logic, state, and data fetching—in your packages/shared folder.

  • State Management: A modern, lightweight library like Zustand is ideal for universal apps. It lets you create a shared store (e.g., for managing user login status) that works seamlessly across all platforms without any extra configuration.
  • Data Fetching: The combination of Axios (for API requests) and TanStack Query (for managing server data) is the industry standard. You can create a shared, custom hook to fetch data (e.g., useUserData). This hook can then be used in any component on any platform to handle loading, caching, and errors automatically.

Putting It All Together: The Universal App in Action

You’ve built the shared foundation. Now, it’s time to put it all together and see your universal app in action.

Step 6: Initialize and Run Your Apps

Getting your apps up and running is fast and simple using the officially recommended Expo framework.

  1. Create Your Project: You can scaffold a complete, pre-configured universal project with a single command: npx create-expo-app@latest –template. This new project is already set up for iOS, Android, and web, and includes Expo Router for universal navigation.
  2. Start the Dev Server: In your project folder, run npx expo start. This launches a central development server. From its dashboard, you can press a key to instantly open your app in an iOS simulator, an Android emulator, or your web browser.

Step 7: Use Your Shared Code

This is the final step where the power of this architecture becomes clear. You can now go into your app screens (e.g., in apps/mobile/ or apps/web/) and import the code you built in your packages/ directory.

You’ll import your shared components (like a button) and universal hooks (like useUserData) and use them to build your features. The best part is that the code is nearly identical for both mobile and web. You write it once, and it just works everywhere.

Implementation Guide: Key Patterns for Universal Code

This guide provides practical patterns and techniques for building the shared parts of a universal application that runs on iOS, Android, and the Web.

Pattern 1: Universal Navigation with Expo Router

For universal apps, Expo Router is the standard tool for handling navigation. 

It uses a simple file-based system. This means the folder and file structure in your app/ directory automatically creates the app’s routes.

  • app/index.tsx becomes the home page (/).
  • app/profile.tsx becomes the /profile page.
  • app/settings/notifications.tsx becomes the /settings/notifications page.

To move between screens, you use the universal <Link> component. On the web, it creates a normal <a> tag, which is good for SEO. On mobile, it triggers a native screen transition. This makes navigation work the same way everywhere.

Pattern 2: Crafting Universal Components

The main goal of a universal app is to create a library of UI components that can be shared between the mobile and web apps.

Here is an example of a simple, universal <Button> component that works on all platforms.

TypeScript

// in packages/ui/Button.tsx

import React from ‘react’;

import { Pressable, Text, StyleSheet } from ‘react-native’;

export const Button = ({ title, onPress }) => {

  return (

    <Pressable

      onPress={onPress}

      style={({ pressed }) => [

        styles.button,

        pressed && styles.buttonPressed

      ]}

      accessibilityRole=”button” // This renders as a <button> on the web

    >

      <Text style={styles.text}>{title}</Text>

    </Pressable>

  );

};

// Styles are created once and work on all platforms

const styles = StyleSheet.create({

  button: {

    backgroundColor: ‘#007AFF’,

    paddingVertical: 12,

    paddingHorizontal: 24,

    borderRadius: 8,

    alignItems: ‘center’,

  },

  buttonPressed: {

    opacity: 0.8,

  },

  text: {

    color: ‘#FFFFFF’,

    fontSize: 16,

    fontWeight: ‘bold’,

  },

});

This component can be imported and used in both your mobile and web apps to create a button that looks and works the same everywhere.

Pattern 3: Handling Platform-Specific Code

Sometimes, you will need to write different code for different platforms. There are two main ways to do this.

  1. The Platform Module: For small, inline changes, you can use Platform.OS inside your code to check which platform is running (‘ios’, ‘android’, or ‘web’) and apply logic accordingly.
  2. JavaScript

import { Platform, StyleSheet } from ‘react-native’;

const styles = StyleSheet.create({

  paddingTop: Platform.OS === ‘ios’ ? 20 : 0 // Add padding only on iOS

});

  1. Platform-Specific File Extensions: For bigger differences, you can create separate files for each platform. The build tool will automatically pick the right one.
    • MyComponent.ios.js (for iOS only)
    • MyComponent.android.js (for Android only)
    • MyComponent.web.js (for Web only)
    • MyComponent.native.js (for both iOS and Android)

Pattern 4: Universal State Management and Data Fetching

You also need consistent ways to manage your application’s data across all three platforms.

  • Client-Side State: For managing data inside the app (like a user’s settings or the state of the UI), Zustand is a popular and simple solution. It’s lightweight and helps prevent unnecessary re-renders, which keeps your app fast.
  • Server-Side State: For fetching data from a server or API, the standard approach is to use Axios (for making the HTTP requests) and TanStack Query (for managing the server data, including caching, loading, and error states). This combination works perfectly on all platforms.

The Final Result

By following this guide, you have successfully built a true universal application. This structure maximizes code reuse, speeds up development, and ensures you can deliver a consistent, high-quality experience to your users on every platform.

Building from a single codebase fundamentally changes your development process.

It directly leads to lower costs and a faster time-to-market. Your app also maintains a consistent look, feel, and user experience on every device. While it may not be the best choice for performance-heavy applications like 3D gaming, it’s the ideal solution for the vast majority of projects today, including e-commerce stores, social media platforms, and internal business tools.

Adopting a universal app strategy is a key business decision for staying competitive and efficient in 2025.

Categories: Mobile App
jaden: Jaden Mills is a tech and IT writer for Vinova, with 8 years of experience in the field under his belt. Specializing in trend analyses and case studies, he has a knack for translating the latest IT and tech developments into easy-to-understand articles. His writing helps readers keep pace with the ever-evolving digital landscape. Globally and regionally. Contact our awesome writer for anything at jaden@vinova.com.sg !