DEV Community

Cover image for The Ultimate Guide to Universal React Applications: Build Once, Run Everywhere
Nina Rao
Nina Rao

Posted on

The Ultimate Guide to Universal React Applications: Build Once, Run Everywhere

React totally changed how I build user interfaces. Before, the web and mobile felt like different worlds. Universal React apps unlocked something special for me. They let me create apps that run everywhere from just one codebase. My apps now feel at home on the web, iOS, and Android. The year is 2025, and building universal apps is smoother, stronger, and honestly, way more fun. Still, I had to make a bunch of careful choices about my stack and project architecture to make it work right.

Transparency notice: This article incorporates AI tools and may reference projects or businesses I'm affiliated with.

If you want to reach people on any device without doing triple the work, you’re in my shoes. I’m going to walk you through the current ways I build universal React apps. I’ll share what has worked, where I’ve stumbled, and how to get the most out of your code while making each platform shine.

Why Universal React Apps?

I remember when developing for web, iOS, and Android meant juggling different projects and tools. Each had its own headaches. Universal React apps changed that for me. With frameworks like React Native and tools like Expo or Next.js, I can now:

  • Use just one JavaScript or TypeScript codebase
  • Share logic, components, and entire design systems across all platforms
  • Enjoy native performance and tap into cool device features
  • Move really fast with hot reload and a toolkit that works everywhere

Going universal isn’t just about shortcuts. It’s about reaching more people, keeping my projects easier to maintain, and just enjoying development more. I can still polish things for each platform where it matters.

Key Approaches to Universal React App Development

Now that I’ve experimented with a bunch of setups, I see that there are three main ways people build universal React applications in 2025. Each has its quirks and strengths. Let me show you what I’ve learned about the top three.

The T3 Turbo Stack: Next.js Meets Expo in a Monorepo

One setup I dove into is the T3 Turbo stack. It weds Next.js for web and Expo for React Native inside a single monorepo. At first, I fumbled through learning the tooling, but I love how much power and flexibility I get.

How it works:

  • Monorepo toolkit: I use pnpm and Turborepo to handle dependencies and builds across projects
  • Project structure: My Next.js and Expo projects sit side by side, with a shared packages folder for APIs, auth, database, and reusable stuff
  • Code sharing: I reuse business logic, data models, and many UI utilities. Design systems stay aligned thanks to Tailwind CSS for web and NativeWind for native. They share similar styling conventions, which I’ve found keeps things looking consistent

Example:

Both my web (nextjs/) and mobile (expo/) projects dip into shared logic from a packages/ directory. For things like authentication or data fetching, I only need to write the code once.

Pros:

  • I get to use the latest and greatest libraries, like trpc or DrizzleORM
  • Mobile feels truly native and the web gets full-featured Next.js power
  • All my deep logic and API stuff lives in one source of truth

Cons:

  • Monorepo setup felt daunting at first
  • Sharing UI code has limits; most visual components have to be tailored for their platform
  • Onboarding took me a while since I had to learn how all these tools fit together

When to use:

This is my pick when I want max flexibility and performance for both web and mobile. If you don’t mind a complex project structure and want the best tools for every platform, this is a heavy hitter.

Tamagui & Unified UI: The Shared-UI Monorepo

If you want the most code sharing possible-even with your UI-go look at Tamagui. I tried it for a design-forward project. Tamagui made my life easier when the goal was to have my app look and behave the same on every device.

How it works:

  • Monorepo structure: A lot like T3 Turbo, but with much more UI shared
  • Central UI package: All screens and components go into one shared packages/ui/ folder
  • Tamagui components: The abstractions mean my interface runs nicely everywhere-web and mobile
  • Routing: Solito makes navigation work across both web and mobile with the same logic

Example:

Both next/ and expo/ projects simply pull the same HomeScreen file. Features and styling stay totally in sync.

Pros:

  • I can write UI once and reuse it everywhere
  • Styles and design systems are unified and adapt to the platform
  • Updating the design is a breeze and branding never goes out of sync

Cons:

  • Committing to Tamagui locks you into its ways of doing things
  • Still needs some monorepo setup knowledge
  • Routing, even though shared, took me a little time to learn

When to use:

This is perfect if you want almost every pixel to be shared. If your team is big on design, or you’re a startup that needs to move fast across devices, Tamagui pays off.

Expo Router: Simple Universal Apps, No Monorepo Needed

Sometimes I want to move even faster and skip the complexities of monorepos or custom compilers. When that's the mood, I reach for Expo’s latest Expo Router. It shocked me how easy it is to go universal from a single React Native project.

How it works:

  • Single project for all platforms: Everything lives in one folder
  • File-based routing: Feels like Next.js with folders for my pages
  • Platform extensions: I can write .web.js and .native.js files to customize per platform
  • Switching logic: I use React Native's Platform module to run code just on iOS, Android, or web
  • API routes: Since Expo Router v3, I can define API endpoints right in my project

Example:

If I want my homepage header to look different on web, I make a HomeHeader.web.js and HomeHeader.native.js. If I need special mobile-only functionality, I use Platform.OS checks to show or hide features.

At this point, picking the right UI components library becomes a challenge all its own. Juggling consistency and custom styling across web, Next.js, and mobile can be tricky-especially if you're moving between Tailwind CSS, NativeWind, and your own styles. One solution that really helped me streamline this process is gluestack. Unlike rigid UI kits, gluestack's modular, copy-paste components let you grab only what you need, style them easily with Tailwind CSS and NativeWind, and use them universally in your React, Next.js, or React Native projects. I found this approach huge for maintaining both flexibility and a consistent look, whether I'm working in a monorepo setup or a simpler Expo Router project. Their open-source components, production tools, and real-world examples-even sample apps and automated component generators-made it easy to focus on features instead of wrestling with UI edge cases.

Pros:

  • It’s the fastest and simplest way I’ve started a universal app
  • Hot reloading works out of the box for every device
  • It’s ideal for my solo projects or when I’m building with a tiny team

Cons:

  • Web support is solid but not as powerful as Next.js for heavy web projects
  • Some advanced features need extra work or hacks
  • For giant "enterprise" needs, it doesn’t have all the integrations of the big monorepo stacks

When to use:

If you crave speed and productivity but still want to use native APIs, go Expo Router. It’s perfect if mobile is the main focus and the web is an extra feature.

Honorable Mention: Capacitor and Ionic

I also had good luck with Capacitor and Ionic when my background was mostly web. Capacitor takes my web app and lets it run as a native app. Ionic swoops in with UI components that look almost native.

Pros:

  • I can turn existing React web apps into mobile ones with minimal changes
  • Most of my code runs everywhere-web, iOS, Android
  • Setup is fast. I could start seeing mobile versions of my app right away

Cons:

  • The app runs inside a WebView, so performance is more web-like
  • The UI may not feel 100% native to hardcore users
  • Deep native integrations are often tricky and sometimes frustrating

For teams wanting max code reuse with a web-first vibe, this route is awesome. If you want to squeeze every drop of native feel and performance, it doesn’t quite match React Native.

Platform Differences: How to Handle Platform Logic

In my experience, building universal apps doesn’t mean you can treat every platform equally. Sometimes, mobile needs one thing and the web needs another. React Native’s Platform module has saved me many times. I also use different file extensions to handle special cases.

  • I check Platform.OS in my code for web, ios, or android to tweak logic
  • When things get messy, I split out files. For example, Component.web.js and Component.native.js. Expo will pick the right one automatically
  • This helps me manage device features, performance quirks, and those tiny UX details each platform needs

Example:

I often download images. On web, I rely on a browser library like dom-to-image and hide that logic from my native app code with Platform.OS === 'web'.

Getting Started: What You'll Need

If you know modern JavaScript, you’re ready. Here’s what helped me get going:

  • I made sure I was comfortable with React and TypeScript
  • I learned the basics of React Native (think View, Text, StyleSheet)
  • I dove into new tooling like Expo CLI and monorepos when needed
  • I always test on real devices or emulators-Expo Go helped a lot here
  • I stay curious. These stacks change fast, and docs are lifesavers

Even when I had never written a mobile app, the transition from React DOM to React Native felt natural to me.

Practical Tips for Building Today

1. Pick a stack that matches your priorities:

When I need heavy SSR and platform control, I stick with Next.js plus Expo (T3). For sharing most of my UI, Tamagui is unbeatable. If I want things to be super simple, Expo Router makes me smile.

2. Use design systems for consistency:

Staying in sync across platforms is key. I lean on Tailwind (web) plus NativeWind (native) or Tamagui for styling harmony.

3. Embrace platform differences where it matters:

Making everything look exactly the same is tempting, but often little differences are what make apps feel truly native.

4. Don’t fear the monorepo:

I was intimidated by monorepos at the start. After I learned how Turborepo or Nx worked, I saw my workflow get a lot smoother, especially as my projects grew.

5. Leverage the vibrant React ecosystem:

Whenever I needed things like device APIs or analytics, the React Native ecosystem usually had a solid, up-to-date library ready for me.

Choosing Your Universal Stack in 2025: A Recipe for Success

I quickly learned there is no single “right” way to build a universal React app. Everything is a trade-off. Here’s how I decide:

  • If I want top-level web and native experiences, I use Next.js + Expo (T3 Turbo)
  • If I crave the most shared code and UI, I go for a monorepo with Tamagui
  • If I just want to move fast and keep it simple, Expo Router wins
  • If my project is web-focused and just needs a native wrapper, Capacitor + Ionic is very handy

No matter which way I go, universal React lets me work quicker and hit every platform with less hassle. The ecosystem is finally mature. The tools are polished. I feel free to dream big and build apps that reach everyone.

FAQ

#### What is a universal React application?

A universal React application is my way to target web, iOS, and Android with one codebase. I use tools like React Native, Expo, or Next.js to share logic and components as much as I can, but still respect what makes each platform feel right.

#### How much code can I really share between web and native?

It depends a bit on the stack I choose and my app’s needs. All my business logic, state handling, and backend stuff is usually reusable. With modern tools like Tamagui, I often share big chunks of my UI too. Still, some platform tweaks are needed to keep things slick and polished everywhere.

#### Is Expo Web production-ready? How does it compare to Next.js for web development?

From hands-on experience, Expo Web is solid for many projects and just keeps getting better. Still, Next.js beats it for things like server-side rendering, SEO, and raw web performance. For web-heavy apps, I use Next.js. For all-in-one development and super easy deployment, Expo Web works really well for me.

#### Do I need to learn native iOS/Android development to build universal apps with React?

Nope. I got pretty far without diving into Swift or Kotlin. Still, basic knowledge about platform guidelines and how to add native modules in React Native does help. As my projects got bigger, understanding some native concepts made debugging and improvements much easier.


So, ready to build your first-or next-universal React app? I am. The tools rock, the docs are finally good, and going cross-platform just keeps getting smoother. Happy coding!

Top comments (0)