messageCross Icon
Cross Icon
Mobile App Development

How to Implement Deep Linking in React Native with Expo Router

How to Implement Deep Linking in React Native with Expo Router
How to Implement Deep Linking in React Native with Expo Router

Have you ever tapped a link in an email or a push notification and landed directly inside an app screen? That’s deep linking, and it’s one of the most underrated superpowers you can give your React Native app.

With the latest Expo Router, setting up deep linking is ridiculously easy, no more wrestling with linking.ts or complex configs. In this guide, we’ll go from zero to hero, building a working deep link setup that you can test on both iOS and Android. Leveraging AI tools like those used by experts at Zignuts can further streamline your app development and marketing workflows.

Why Deep Linking Matters

Deep linking isn’t just a “nice-to-have.” It powers real-world features like:

  • OAuth callbacks (e.g., Auth0 or Google Sign-In redirecting back to your app)
  • Push notifications that open a specific screen
  • Marketing links inside emails and SMS
  • Cross-app navigation (another app opening yours with data)

Think of it as giving your app an address system, so it always knows where to take users when a link is clicked.

Step 1: Create a New Expo Project

If you don’t have a project yet, start fresh:

Code

npx create-expo-app@latest my-deep-linking-app
cd my-deep-linking-app

And enable routing in app/_layout.tsx:

Code

import { Stack } from "expo-router";

export default function RootLayout() {
  return <Stack />;
}

Step 2: Add a Custom URL Scheme

Your app needs its own unique scheme (like deeplinkr://). Open app.json and add this inside expo:

Code

{
  "expo": {
    ...
    "scheme": "deeplinkr" // Your custom scheme
  }
}

Now your app can recognise deeplinkr://... links.

Step 3: Define Routes with Expo Router

Here’s the magic: Expo Router automatically maps your file structure into deep links. Let’s create a few screens inside the app/ folder:

Code

app/
 ├─ index.tsx             → deeplinkr://
 ├─ profile/[id].tsx      → deeplinkr://profile/:id
 ├─ orders/[orderId].tsx  → deeplinkr://orders/:orderId
 └─ _not-found.tsx        → fallback for bad links

app/index.tsx

Code

import { Text, View, Button } from "react-native";
import { Link } from "expo-router";

export default function Home() {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text style={{ fontSize: 18 }}>Welcome Home</Text>
      <Link href="/profile/42" asChild>
        <Button title="Go to Profile 42" />
      </Link>
    </View>
  );
}

app/profile/[id].tsx

Code

import { useLocalSearchParams } from "expo-router";
import { Text, View } from "react-native";

export default function Profile() {
  const { id } = useLocalSearchParams<{ id: string }>();

  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text style={{ fontSize: 18 }}>Profile ID: {id}</Text>
    </View>
  );
}

app/orders/[orderId].tsx

Code

import { useLocalSearchParams } from "expo-router";
import { Text, View } from "react-native";

export default function Orders() {
  const { orderId } = useLocalSearchParams<{ orderId: string }>();

  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text style={{ fontSize: 18 }}>Order ID: {orderId}</Text>
    </View>
  );
}

app/_not-found.tsx

Code

import { Text, View } from "react-native";

export default function NotFound() {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <Text style={{ fontSize: 18, color: "red" }}>Page not found</Text>
    </View>
  );
}

That’s it - routes are ready! 

Step 4: Run the App (Standalone Build for Deep Linking)

Heads up: If you’re running the app inside Expo Go, deep linking won’t work. Expo Go only supports exp:// links, not your custom scheme like deeplinkr://.

To test properly, you’ll need to create a native build of your app. Luckily, you don’t need to use EAS for this - you can run it directly with the React Native CLI.

4.1 Prebuild the Native Project

Since Expo Router runs in the managed workflow, first generate the native iOS/Android projects:

Code

npx expo prebuild

This creates ios/ and android/ folders inside your project.

4.2 Run on iOS Simulator

Make sure you have Xcode installed, then run:

Code

npx react-native run-ios

This will:

  • Build the iOS project
  • Launch the app in your simulator
  • Register your custom scheme (deeplinkr://)

Now you can test deep links with:

Code

xcrun simctl openurl booted "deeplinkr://profile/42"

4.3 Run on Android Emulator

Make sure you have Android Studio installed with an emulator running, then run:

Code

npx react-native run-android

After it installs, test deep links with the following command:

Code

adb shell am start -W -a android.intent.action.VIEW -d "deeplinkr://orders/123" com.mydeeplinkingapp

4.4 Still want Expo Go for development?

No worries - you can continue using Expo Go for most development, and only switch to native builds when you need to test deep linking or features that require custom native code.

Step 5: Test Deep Links (Real World)

Once your app is installed via a native build (not Expo Go), you can test deep links just like your users will.

Option 1: Command-line Testing

5.1 On iOS Simulator

Code

xcrun simctl openurl booted "deeplinkr://profile/42"

5.2 On Android Emulator

Code

adb shell am start -W -a android.intent.action.VIEW -d "deeplinkr://orders/123" com.mydeeplinkingapp

Option 2: Real-World Copy & Click

  1. Copy one of your deep links, e.g.:
    • deeplinkr://profile/42
    • deeplinkr://orders/123
  2. Paste it into Notes, Safari/Chrome, Slack, or an email draft inside the simulator/emulator.
  3. Tap on the link.
    • If your app is open, it will navigate directly to the screen.
    • If your app is in the background, it will resume and navigate.
    • If your app is closed, it will launch fresh and navigate to the screen.

Option 3: Invalid Links

  1. Try something like:
    • deeplinkr://foo/bar
  2. Paste it into Notes, Safari/Chrome, Slack, or an email draft inside the simulator/emulator.
  3. Tap on the link.
    • If your app is open, it will navigate directly to the screen.
    • If your app is in the background, it will resume and navigate.
    • If your app is closed, it will launch fresh and navigate to the screen.

Important Limitations of Custom URL Schemes

Custom schemes like deeplinkr:// only work when the app is already installed on the device.

  • If your app is installed → the deep link opens directly in your app.
  • If your app is not installed → nothing happens (the system doesn’t redirect users to the App Store or Play Store).

If you want links that also redirect to the store when the app is not installed, you’ll need to set up Universal Links (iOS) or App Links (Android)  or use a deferred deep linking service like Supalink, Dub, or Freezed Links.

Final Thoughts

Deep linking with Expo Router is refreshingly simple compared to older setups.
All you need is:

  1. Define a scheme in app.json.
  2. Create screens in the app/ directory.
  3. Test links with npx uri-scheme open.

No boilerplate linking.ts. No headaches. Just clean, intuitive file-based routing.

So the next time you need:

  • Push notifications that deep link into screens
  • OAuth redirect handling (e.g., Auth0, Google, etc.)
  • Smart links from emails or SMS

…you’re already set up!

Zignuts leverages cutting-edge AI-powered marketing and development expertise to empower projects like this for seamless integration, rapid deployment, and efficient solutions tailored to your business needs. Their experience in AI-driven app development and marketing strategy ensures that your digital products not only perform well but also engage users effectively. Let’s Discuss More.

card user img
Twitter iconLinked icon

A problem solver with a passion for building robust, scalable web solutions that push the boundaries of technology and deliver impactful results

Book a FREE Consultation

No strings attached, just valuable insights for your project

Valid number
Please complete the reCAPTCHA verification.
Claim My Spot!
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
download ready
Thank You
Your submission has been received.
We will be in touch and contact you soon!
View All Blogs