<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[How Instagram, WhatsApp, Uber & Netflix Would Be Built Today Using Expo Router]]></title><description><![CDATA[How Instagram, WhatsApp, Uber & Netflix Would Be Built Today Using Expo Router]]></description><link>https://build-instagram-wth-expo-router.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/69f59683ec32cba9e5b95900/28756c29-573e-49b8-bb97-a9e539c84cf5.png</url><title>How Instagram, WhatsApp, Uber &amp; Netflix Would Be Built Today Using Expo Router</title><link>https://build-instagram-wth-expo-router.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 22 Jun 2026 23:30:33 GMT</lastBuildDate><atom:link href="https://build-instagram-wth-expo-router.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How Instagram, WhatsApp, Uber & Netflix Would Be Built Today Using Expo Router]]></title><description><![CDATA[Most developers do not struggle with building screens.
They struggle with what happens after the app grows.
A login screen is easy. A scalable authentication system is not.
A chat UI is easy. A realti]]></description><link>https://build-instagram-wth-expo-router.hashnode.dev/how-instagram-whatsapp-uber-netflix-would-be-built-today-using-expo-router</link><guid isPermaLink="true">https://build-instagram-wth-expo-router.hashnode.dev/how-instagram-whatsapp-uber-netflix-would-be-built-today-using-expo-router</guid><category><![CDATA[React Native]]></category><category><![CDATA[Expo]]></category><category><![CDATA[expo-router]]></category><dc:creator><![CDATA[Pushkar Shukla]]></dc:creator><pubDate>Fri, 22 May 2026 20:28:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69f59683ec32cba9e5b95900/63b336b9-344c-433d-b813-fc4e334b3552.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most developers do not struggle with building screens.</p>
<p>They struggle with what happens <em>after</em> the app grows.</p>
<p>A login screen is easy. A scalable authentication system is not.</p>
<p>A chat UI is easy. A realtime messaging system that survives reconnects, offline states, and thousands of updates per minute is not.</p>
<p>A feed page is easy. A production-grade content pipeline with caching, pagination, media optimization, and feature isolation is not.</p>
<p>That is the difference between building an app and engineering a product.</p>
<p>And in 2026, if companies like Instagram, WhatsApp, Uber, or Netflix were starting from scratch using React Native, the most important conversation would not be about UI. It would be about <strong>how the codebase is organized</strong>.</p>
<p>More specifically:</p>
<ul>
<li><p>How features are separated</p>
</li>
<li><p>How navigation scales without becoming a mess</p>
</li>
<li><p>How real-time systems are structured</p>
</li>
<li><p>How state is managed across layers</p>
</li>
<li><p>How startup performance is kept fast</p>
</li>
<li><p>How a team of 20 engineers can work without constantly stepping on each other This is exactly where <a href="https://docs.expo.dev/router/introduction/">Expo Router</a> becomes interesting. Not because it magically solves any of this, but because it pushes developers toward thinking about these things from day one.</p>
</li>
</ul>
<hr />
<h2>The Problem With "Tutorial-Style" Codebases</h2>
<p>Most tutorial apps look something like this:</p>
<pre><code class="language-plaintext">src/
  screens/
  components/
  services/
  utils/
</code></pre>
<p>Clean enough for a side project. But the moment the app becomes real, it starts breaking down.</p>
<p>Suddenly hundreds of components are piled into the same folders, API calls are scattered inside screens, features start bleeding into each other, and onboarding a new developer becomes a two-hour orientation. Nobody knows where anything belongs anymore.</p>
<p>The problem is not React Native. The problem is that the folder layout no longer reflects the product being built.</p>
<p>Production apps are not organized by "what type of file is this." They are organized by features, user flows, domains, and team ownership. That requires a completely different way of thinking.</p>
<hr />
<h2>The Mindset Shift That Separates Junior and Senior Developers</h2>
<p>This transition catches a lot of people off guard early in their careers.</p>
<p><strong>Early-career thinking</strong> sounds like:</p>
<blockquote>
<p>"Just make it work." / "We'll clean this up later." / "It's only one screen."</p>
</blockquote>
<p><strong>Production thinking</strong> sounds like:</p>
<blockquote>
<p>"Where does this feature live six months from now?" / "Can someone new to the project understand this in ten minutes?" / "How do we stop the codebase from drifting into chaos?"</p>
</blockquote>
<p>Once you start asking those questions, project organization stops being an afterthought and becomes one of the most important decisions you make.</p>
<hr />
<h2>Why Apps Like Instagram Are Not Really "Apps" Anymore</h2>
<p>At a certain scale, these products stop being apps and start being ecosystems. Several independent systems running under one roof.</p>
<p><strong>Instagram</strong> has feeds, stories, reels, messaging, notifications, media uploads, and creator tools. Each of those could be its own product.</p>
<p><strong>Uber</strong> has maps, live location tracking, payments, realtime ride status, driver-side flows, and trip history. Half of that is closer to infrastructure than UI.</p>
<p><strong>Netflix</strong> has streaming, a recommendation engine, offline downloads, playback controls, watch history, and multi-profile support. Performance engineering is more critical here than screen design.</p>
<p>At that size, a clean folder layout is not just nice to have. It is how the engineering team stays sane.</p>
<hr />
<h2>What Expo Router Actually Changes</h2>
<p>People often describe Expo Router as "file-based navigation." That is technically accurate but misses the real point.</p>
<p>The bigger idea is this:</p>
<blockquote>
<p><strong>Your folder layout becomes your product map.</strong></p>
</blockquote>
<p>Instead of wiring every navigator, screen, and flow together by hand, the routing falls out naturally from how you organize your files.</p>
<pre><code class="language-plaintext">app/
  _layout.tsx
  (auth)/
    login.tsx
    signup.tsx
  (tabs)/
    home.tsx
    search.tsx
    notifications.tsx
    profile.tsx
</code></pre>
<p>Without reading a single config file, any developer joining the project already knows which routes are public, which live inside the main app, and how the tab layout is grouped. That kind of immediate legibility is worth a lot when the team grows.</p>
<hr />
<h2>A Realistic Folder Setup for a Production App</h2>
<p>A well-organized React Native app keeps routing, business logic, networking, state, and UI components in clearly separate places:</p>
<pre><code class="language-plaintext">app/
  _layout.tsx
 
  (auth)/
    login.tsx
    signup.tsx
    forgot-password.tsx
 
  (main)/
    _layout.tsx
    home.tsx
    search.tsx
    notifications.tsx
    profile.tsx
 
  messages/
    [chatId].tsx
 
src/
  features/
    auth/
    feed/
    messaging/
    notifications/
    uploads/
    profile/
 
  components/
  services/
  store/
  hooks/
  constants/
  utils/
</code></pre>
<p>Each directory has a single job:</p>
<table>
<thead>
<tr>
<th>Directory</th>
<th>What it does</th>
</tr>
</thead>
<tbody><tr>
<td><code>app/</code></td>
<td>Routing only</td>
</tr>
<tr>
<td><code>features/</code></td>
<td>Business domain logic</td>
</tr>
<tr>
<td><code>services/</code></td>
<td>Networking and API calls</td>
</tr>
<tr>
<td><code>store/</code></td>
<td>Global state</td>
</tr>
<tr>
<td><code>components/</code></td>
<td>Shared UI</td>
</tr>
</tbody></table>
<p>Mixing these up is where most codebases start to rot.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69f59683ec32cba9e5b95900/dbccd9a9-4cc3-414c-aa9d-07b42f7cd25b.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Why Feature-Based Organization Actually Scales</h2>
<p>The most common mistake growing apps make is grouping files by technical category instead of product responsibility.</p>
<p>When every button, hook, and service for the "feed" feature lives inside a single <code>features/feed/</code> folder rather than scattered across <code>components/</code>, <code>hooks/</code>, and <code>screens/</code>, something clicks. Changes to the feed stay inside the feed. Deleting a feature is as simple as deleting a folder. Ownership becomes obvious.</p>
<pre><code class="language-plaintext">features/
  feed/
  reels/
  stories/
  messaging/
  payments/
  rides/
  player/
</code></pre>
<p>Each domain owns its own screens, hooks, state, services, and helpers. That is how large engineering teams stay productive without needing a meeting every time someone wants to change a button.</p>
<hr />
<h2>How Navigation Fits Into All of This</h2>
<p>In a small app, navigation is an afterthought. In a production codebase, it is part of the system design.</p>
<p>Real apps deal with public routes, protected routes, nested tab layouts, modal flows, onboarding sequences, role-based access, deep links, and dynamic paths. That is a lot to wire up manually.</p>
<p>Expo Router handles most of this through the folder layout itself:</p>
<pre><code class="language-plaintext">app/
  (auth)/
  (tabs)/
  (dashboard)/
  (settings)/
  modal/
</code></pre>
<p>Each group acts as a navigation zone with its own behavior and layout. As the app expands, the routing stays readable because it mirrors the product, not a hand-written config tree.</p>
<hr />
<h2>Getting Authentication Right From the Start</h2>
<p>Auth is one of the first things that turns ugly in a growing app. Production-level auth usually involves login, signup, OTP verification, session restoration, token refresh, protected routes, role-based access control, and onboarding state tracking.</p>
<p>The cleanest way to handle it is full separation:</p>
<pre><code class="language-plaintext">app/
  (auth)/      ← unauthenticated users land here
  (main)/      ← authenticated users land here
</code></pre>
<p>Authenticated? Go to <code>(main)</code>. Not authenticated? Stay in <code>(auth)</code>. That single boundary replaces a web of conditional checks scattered across the codebase.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69f59683ec32cba9e5b95900/15790720-fab4-4cd7-babe-826e1c15e333.png" alt="" style="display:block;margin:0 auto" />

<p>Expo Router's redirect-based flows make this natural to implement without fighting the navigation system.</p>
<hr />
<h2>State Has More Than One Category</h2>
<p>One of the subtler mistakes in React Native codebases is treating every piece of state the same way. At any real scale, there are at least three distinct types that need different tools:</p>
<p><strong>Server state</strong> covers data fetched from an API: feeds, chat messages, ride details, recommendations. React Query or SWR handles this well, with built-in caching, background refetching, and synchronization.</p>
<p><strong>Client state</strong> is local UI behavior: which modal is open, which tab is selected, what filters are active. Zustand or React Context is usually enough here.</p>
<p><strong>Persistent state</strong> is anything that needs to survive an app restart: auth tokens, user preferences, cached content, offline drafts. MMKV or AsyncStorage handles this layer.</p>
<p>Keeping these three separate prevents the classic situation where a UI toggle causes a full re-render of the entire app.</p>
<hr />
<h2>The API Layer Should Not Live Inside Your Screens</h2>
<p>This one trips up almost every developer at some point. API calls placed directly inside screen components feel convenient early on and become a nightmare later.</p>
<p>A dedicated services layer fixes this:</p>
<pre><code class="language-plaintext">services/
  apiClient.ts
  authService.ts
  feedService.ts
  chatService.ts
  paymentService.ts
</code></pre>
<p>Screens handle rendering. Services handle communication with the outside world. That boundary makes testing easier, error handling consistent, and developer onboarding significantly faster.</p>
<hr />
<h2>Realtime Systems Are a Different Animal Entirely</h2>
<p>Normal apps are mostly request-response. A user taps something, a request goes out, data comes back, the screen updates.</p>
<p>Realtime apps are fundamentally different. The data changes constantly, whether the user does anything or not. That gap in complexity is where WhatsApp and Uber become genuinely interesting engineering problems.</p>
<hr />
<h2>How WhatsApp Would Be Built Today</h2>
<p>WhatsApp is not a messaging app. It is a delivery guarantee system that happens to have a chat interface.</p>
<p>The real engineering challenge is not rendering bubbles on a screen. It is ensuring that every message gets delivered exactly once, in order, even across network drops, app restarts, and device switches.</p>
<p>A feature breakdown might look like:</p>
<pre><code class="language-plaintext">features/
  chat/
  presence/
  delivery/
  media/
  calls/
</code></pre>
<p>Each domain owns a specific guarantee. The chat layer handles rendering. The delivery layer tracks message state. The presence layer manages online indicators. None of them should know too much about the others.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69f59683ec32cba9e5b95900/7b710add-3fc7-493b-9838-fbdac4785227.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>How Instagram Would Be Built Today</h2>
<p>Instagram is genuinely several products running as one. Feed, Reels, Stories, messaging, and creator tools each have their own data models, caching needs, and performance requirements.</p>
<pre><code class="language-plaintext">features/
  feed/
  reels/
  stories/
  uploads/
  messaging/
  notifications/
</code></pre>
<p>The hard part is not the UI. It is the content pipeline underneath it. Images need to load before the user gets there. Videos need to buffer without blocking the scroll. Uploads need to survive a bad connection. Getting smooth scrolling on a media-heavy feed is a nontrivial infrastructure problem.</p>
<hr />
<h2>How Uber Would Be Built Today</h2>
<p>Uber is, at its core, a location synchronization problem with a payment system attached.</p>
<pre><code class="language-plaintext">features/
  maps/
  rides/
  booking/
  tracking/
  payments/
</code></pre>
<p>Every feature in that list needs to stay in sync with every other feature in real time. The map updates when the driver moves. The ETA updates when traffic changes. The booking state updates when the driver accepts. Getting all of that consistent without race conditions or stale state is the real engineering challenge, not the UI.</p>
<hr />
<h2>How Netflix Would Be Built Today</h2>
<p>Netflix sits in a different category. It is not a messaging or logistics problem. It is a performance problem.</p>
<pre><code class="language-plaintext">features/
  browse/
  player/
  recommendations/
  downloads/
  profiles/
</code></pre>
<p>The central question is: how fast can the user get to watching something? That drives every technical decision. Startup time gets optimized obsessively. The recommendation engine runs ahead of the user. Downloads are pre-fetched intelligently. Playback begins before the full video is loaded. The UI almost becomes secondary to the infrastructure that makes it feel instant.</p>
<hr />
<h2>Offline Support Is Not a Bonus Feature Anymore</h2>
<p>Users do not stay connected. They go through tunnels, into buildings with bad signal, and onto planes. Apps that assume a reliable connection will eventually embarrass you.</p>
<p>Proper offline support needs local persistence, optimistic UI updates, background sync when connectivity returns, retry queues for failed requests, and smart cache invalidation. This matters for all four apps we have been discussing. WhatsApp messages, Uber trip states, Netflix downloads, Instagram uploads: all of them need to behave gracefully when the network disappears.</p>
<p>Building this in after the fact is painful. It is much easier when the codebase is organized well from the beginning.</p>
<hr />
<h2>Startup Performance Is Worth Taking Seriously Early</h2>
<p>A lot of apps do too much at launch and wonder why they feel slow. The fix is usually just being intentional about what runs at startup and what gets deferred.</p>
<p>The essentials at launch:</p>
<ol>
<li><p>Restore auth session</p>
</li>
<li><p>Initialize navigation</p>
</li>
<li><p>Hydrate critical cache</p>
</li>
<li><p>Render the first screen Everything else can wait. Analytics initialization, non-critical API calls, media preloading, heavy library setup: all of this can happen after the first screen is visible. A clean codebase makes these tradeoffs easy to reason about because each piece of work lives in a known place.</p>
</li>
</ol>
<hr />
<h2>Shared Layouts Prevent a Lot of Duplication</h2>
<p>One of the genuinely underrated features of Expo Router is how <code>_layout.tsx</code> files work. You define a shell once and every route inside that folder inherits it automatically.</p>
<p>Tab bars, headers, authentication wrappers, dashboard chrome: instead of rebuilding these wrappers in every navigator, they become a single file that every child route uses. When something needs to change, you change it once.</p>
<p>That consistency matters a lot when ten developers are working on different parts of the same app simultaneously.</p>
<hr />
<h2>Every Architecture Decision Is a Tradeoff</h2>
<p>Here is something most technical writing glosses over: no company picks an approach because it looks good in a blog post. They pick it because it solves a specific problem they have, and they accept what they give up in return.</p>
<p>Speed versus long-term maintainability. Flexibility versus consistency. Simple now versus scalable later.</p>
<p>Expo Router provides sensible defaults that push teams in a healthy direction. But defaults are not decisions. Teams still need to think carefully about state ownership, caching strategies, feature boundaries, and how they handle the things that do not fit neatly into the standard patterns.</p>
<p>Good codebase design is not about removing complexity. It is about putting complexity in predictable places so it stays manageable.</p>
<hr />
<h2>Wrapping Up</h2>
<p>If you were building Instagram, WhatsApp, Uber, or Netflix today from scratch using React Native, the visual design would be the easy part. The hard part would be creating a codebase that can absorb two years of growth without becoming impossible to work in.</p>
<p>That means features that own their own logic, routing that reflects the product instead of a config file, realtime systems with clear boundaries, state that is managed at the right layer, and startup behavior that does not embarrass you.</p>
<p>Expo Router does not hand you any of that automatically. But it creates an environment where all of it is easier to achieve, because the folder layout and routing conventions nudge you toward the right decisions before the codebase gets big enough to make bad ones painful.</p>
<p>That is worth more than it sounds.</p>
]]></content:encoded></item></channel></rss>