Skip to main content

Command Palette

Search for a command to run...

How Instagram, WhatsApp, Uber & Netflix Would Be Built Today Using Expo Router

Updated
8 min read
A
my work defines me

When building a simple mobile application, a flat file structure and a few global state variables are usually enough to get by. However, when cloning or engineering systems at the scale of Instagram, WhatsApp, Uber, or Netflix, basic file organization quickly breaks down.

This guide provides a comprehensive blueprint for architectural thinking in modern, large-scale React Native applications using Expo Router. Instead of focus on trivial UI styling, it explores how to engineer highly maintainable, feature-isolated, and production-optimised mobile systems.

Topics to Cover in This Blog

  • Modern Large-Scale App Architecture vs. Small-App Thinking

  • Feature-Based Separation in Production Environments

  • Scalable Navigation Architecture with Expo Router

  • Authentication Flow Architecture and Route Interception

  • State Management, Networking, and API Handling Layers

  • Engineering Realtime Systems: Messaging and Live Tracking (WhatsApp & Uber)

  • Offline-First Support, High-Throughput Caching, and Media Delivery (Instagram & Netflix)

  • App Startup Optimization and Production Performance Considerations

  • Production-Grade Folder Layout Blueprint

  • Architectural Trade-offs and Scale-Driven Decisions


Modern Large-Scale App Architecture vs. Small-App Thinking

Small-app thinking relies on organizing directories by technical type: throwing all components into components/, all screens into screens/, and all hooks into hooks/. In a large enterprise app, this creates a tightly coupled dependency nightmare.

Architecture matters in React Native because the JavaScript runtime bridges directly to native platform threads. If your architecture requires evaluating massive, monolithic chunks of code on boot, performance plummets. Large-scale architecture forces code isolation, ensuring that changes to the messaging module cannot introduce bugs into the payment or media streaming pipelines.


Feature-Based Separation in Production Environments

To scale an engineering team across dozens of developers, you must adopt Feature-Based Separation. Each core business domain operates as an independent mini-application (or "feature module").

Instead of scattering code across the repository, a feature like Instagram’s feed or Uber's ride execution lives entirely within its own domain folder. It contains its own isolated components, state slices, hooks, and business logic. The rest of the application interacts with this feature only through a strictly defined public API surface, clean boundaries, and explicit routing endpoints.


Scalable Navigation Architecture with Expo Router

Expo Router simplifies large-scale navigation by mapping the file directory directly to the UI view tree. It enables complex, nested layouts without centralizing configuration bloat.

Shared Layouts & Route Groups

Using Route Groups folders wrapped in parentheses like (feed) or (maps)allows distinct teams to construct entirely independent native stack or tab structures. These groups do not contaminate the deep-linking URL path space.

Nested _layout.tsx files allow you to construct deep navigational hierarchies. For example, Netflix can wrap its browsing experience in a global tab layout, while nesting specialized stack layouts for deeply linked movie detail pages or profile switchers.


Authentication Flow Architecture and Route Interception

In massive applications, authentication goes far beyond a simple login toggle. It involves multi-factor tokens, device fingerprinting, and account switching.

Expo Router handles this via top-down layout interception. A root-level layout component wraps the application context and monitors the authentication state engine. When an unauthenticated interaction attempts to resolve an internal route, the root layout halts rendering and executes a client-side redirect. This setup isolates public authentication layers completely from internal product logic.


State Management, Networking, and API Handling Layers

Production architectures separate client UI state from server-side data cache layers.

+-------------------------------------------------------------+
|                        UI Layer                             |
+-------------------------------------------------------------+
                               |
                               v
+-------------------------------------------------------------+
|                  State Management Layer                     |
|  - Client State (Zustand)   - Server Cache (TanStack Query)  |
+-------------------------------------------------------------+
                               |
                               v
+-------------------------------------------------------------+
|                   Networking/API Layer                      |
|  - Axios/Fetch Client       - Interceptors & Refresh Tokens |
+-------------------------------------------------------------+
  • Client State: Lightweight tools like Zustand or Redux Toolkit manage transient UI state (e.g., active filters, interactive map overlays, modal states).

  • Server Cache: Data fetching, revalidation, and pagination are delegated to tools like TanStack Query or RTK Query.

  • API Isolation: Network clients implement robust interceptor layers to handle automatic token refreshing, edge-case error mappings, and request retries without cluttering individual components.


Engineering Realtime Systems: Messaging and Live Tracking (WhatsApp & Uber)

Building systems like WhatsApp or Uber requires managing continuous, bidirectional network pipelines.

  • WhatsApp (Realtime Messaging): The app uses a persistent WebSocket connection orchestrated via a background service. Incoming messages immediately append to a fast, local key-value store (like MMKV or SQLite) before notifying the UI layer. This setup ensures messages display instantly, even during poor network conditions.

  • Uber (Live Location Tracking): Uber relies on native foreground and background location tracking modules. Coordinates stream over WebSockets or high-frequency gRPC streams to synchronization backends. Expo Router hooks into this by deep-linking driver states directly into the mapping viewport context, ensuring the navigation structure stays aligned with the current trip status.


Offline-First Support, High-Throughput Caching, and Media Delivery (Instagram & Netflix)

Media-heavy platforms cannot afford to block user interactions with network roundtrips.

  • Instagram (Feed Processing & Local Storage): Instagram operates on an offline-first database framework like WatermelonDB or a highly optimized SQLite implementation. The application speculatively prefetches media feeds, saving data and compressed images locally before the user scrolls to them.

  • Netflix (Adaptive Streaming Content Delivery): Netflix balances video playback with UI performance. While the JavaScript layer uses Expo Router to navigate content catalogs smoothly, the underlying video player relies on highly optimized native modules. These components stream video over adaptive protocols (like HLS or DASH), utilising separate hardware-accelerated memory pipelines to keep the UI entirely fluid.


App Startup Optimization and Production Performance Considerations

As an application scales to include hundreds of distinct routes, your initial bundle size inevitably expands. This can slow down app startup times if it isn't properly managed.

Key Optimisation Tactics:

  • Hermes Bytecode Precompilation: Ensure the Hermes engine is fully enabled to execute precompiled JavaScript bytecode directly, cutting down initialization time.

  • Dynamic Route Evaluation: Expo Router evaluates route files dynamically as you navigate to them. Avoid importing heavy feature modules at the root layout level to prevent slowing down the initial app boot.

  • Asset Preloading & Inline Require Statements: Defer loading heavy utility libraries until the exact moment they are needed by using inline require() statements instead of global root imports.


Production-Grade Folder Layout Blueprint

Below is an enterprise-ready project structure. It combines Expo Router’s file-based routing layout with a highly modular, feature-separated architecture:

├── app/                           # EXPO ROUTER CORE: Strict Route Mappings
│   ├── _layout.tsx                # Global Providers Initialization (Theme, Query, Auth)
│   ├── index.tsx                  # Root Gateway Switch / Splash Coordinator
│   ├── (auth)/                    # Isolated Authentication View Flow
│   │   ├── _layout.tsx            # Auth Native Stack Container
│   │   └── login.tsx              # Route: /login
│   ├── (main)/                    # Core Authorized Product Matrix
│   │   ├── _layout.tsx            # Core UI Structure Container (Bottom Tabs)
│   │   ├── feed/                  # Instagram-Style Sub-Module Layouts
│   │   │   ├── index.tsx          # Route: /feed
│   │   │   └── [postId].tsx       # Route: /feed/:postId
│   │   └── messages/              # WhatsApp-Style Sub-Module Layouts
│   │       ├── index.tsx          # Route: /messages
│   │       └── [chatId].tsx       # Route: /messages/:chatId
│   └── (service)/                 # Uber/Netflix Service Domain Layouts
│       ├── tracker.tsx            # Route: /tracker (Live Map Overlay)
│       └── player.tsx             # Route: /player (Media Canvas Viewport)
│
├── src/                           # ARCHITECTURE CORE: Framework-Agnostic Blocks
│   ├── components/                # Shared Cross-Application Design System (Buttons, Inputs)
│   ├── core/                      # Global Network Configurations & Low-Level Drivers
│   │   ├── api/                   # Base Client Interceptors and Transports
│   │   └── storage/               # High-Speed Key-Value Synced DB Wrappers (MMKV)
│   └── features/                  # FEATURE DOMAINS: Isolated Business Logic Blocks
│       ├── feed/                  # Feed Domain Logic Encapsulation
│       │   ├── hooks/             # Feature-Specific Queries (useFeedCache, usePostAction)
│       │   ├── components/        # Feature-Specific Components (PostCard, ReactionBar)
│       │   └── state/             # Local Domain State (Zustand Feed Configs)
│       └── chat/                  # Chat Domain Logic Encapsulation
│           ├── hooks/             # WebSocket Listeners & DB Persisters
│           └── components/        # Specialized Renderers (MessageBubble, InputBar)

Architectural Trade-offs and Scale-Driven Decisions

When engineering at scale, every architectural pattern comes with a trade-off. There is no single "perfect" design:

  • Monorepo Complexity vs. Micro-Reporitories: Splitting large applications into yarn/pnpm monorepo workspaces allows distinct teams to work independently on separate features. However, managing shared internal dependencies can introduce toolchain overhead.

  • The Abstraction Tax: Expo Router significantly cuts down navigation boilerplate and simplifies deep-linking. The trade-off is that you delegate low-level control to an automated framework. If your application requires highly unusual, non-standard screen transitions or dynamic, runtime-generated navigation paths, you may need to drop down and write custom native extensions.


Conclusion

Conclusion: Engineering Beyond the Blueprint

Rebuilding applications like Instagram, WhatsApp, Uber, or Netflix with modern tools requires looking past basic UI templates. It demands a highly disciplined approach to project architecture.

By combining Expo Router’s file-based navigation with a robust, feature-isolated domain structure, you eliminate the single points of failure that cause large software projects to slow down. This architectural pattern keeps your feature modules decoupled, keeps your developer workflows independent, and keeps your network caches separate from the user interface.

As you build out your application structure, prioritize maintainability and clear boundaries over quick shortcuts. Treat your file directory as a strict blueprint for your application's architecture, and engineer your system to handle scaling challenges before they become production performance bottlenecks.