ClaudeExpo2026/07/22 13:15

From Expo Router to Detour: Deferred deep linking the right way

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

claudeja

From Expo Router to Detour: Deferred deep linking the right way の要約

Key Points

  • ポイント1: This is a guest post from Bartek Krasoń - a software engineer from Software Mansion who is currently working on Detour.
  • ポイント2: … If you're building a mobile app with Expo, there's a good chance you're using Expo Router to keep your navigation logic predictable and scalable.
  • ポイント3: You've likely already set up standard deep linking (Universal Links for iOS, App Links for Android) and everything works perfectly for your existing users.

Summary

この記事は 2026-07-22 に公開された「From Expo Router to Detour: Deferred deep linking the right way」の内容を日本語で簡潔にまとめたものです。

Key Points

  • ポイント1: This is a guest post from Bartek Krasoń - a software engineer from Software Mansion who is currently working on Detour.
  • ポイント2: … If you're building a mobile app with Expo, there's a good chance you're using Expo Router to keep your navigation logic predictable and scalable.
  • ポイント3: You've likely already set up standard deep linking (Universal Links for iOS, App Links for Android) and everything works perfectly for your existing users.

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

claudeja

From Expo Router to Detour: Deferred deep linking the right way(原文タイトル)

概要

公開日: 2026-07-22 翻訳生成に失敗したため、原文をそのまま保存しています。

原文

This is a guest post from Bartek Krasoń - a software engineer from Software Mansion who is currently working on Detour. … If you're building a mobile app with Expo, there's a good chance you're using Expo Router to keep your navigation logic predictable and scalable. You've likely already set up standard deep linking (Universal Links for iOS, App Links for Android) and everything works perfectly for your existing users. But what happens when a new user clicks a link to a private invite or a specific product, and they don't have your app yet? What’s happening (and why) Standard deep links (Universal Links on iOS, App Links on Android) work great when the app is already installed. The link opens the app, Expo Router sends them to the right screen. Simple. But the moment a new user passes through the App Store or Google Play, that URL context vanishes. Because iOS and Android don't preserve link data across the store boundary, your app launches completely blind to the original intent that drove the install. This friction is known as the Installation Gap. The fix? Deferred deep linking. The goal is to capture the user's original intent – the exact URL, path, and parameters they tapped, persist it through the installation process, and replay it the moment the app launches for the very first time. The existing option Some platforms have had this solved for years, but they are marketing attribution tools first – for them, deep linking is just a side feature. They hand you a raw URL string in a callback, leaving you to bridge it to your navigation yourself. In an Expo Router app, this means writing fragile glue code to manage lifecycle timing, duplicate navigation events, and race conditions with your auth gates. Because the SDK operates in a completely separate world from your router, you’re stuck building plumbing that shouldn’t have to exist in the first place. How Detour approaches this We built Detour at Software Mansion to solve this problem from the navigation side. Our team has been contributing to the Expo ecosystem since 2017 (Reanimated, Gesture Handler, parts of EAS), and we wanted a deferred deep linking tool that integrates with the router, not around it. The core idea: Detour can resolve links before the first screen renders, using Expo Router's own extension points. The router knows about the intent from the start, so there's no post-mount useEffect race and no manual URL parsing. Here's what that looks like in practice. Intercept the link before the first render Expo Router exposes a +native-intent.tsx file that lets you intercept and transform incoming URLs before routing begins. Detour hooks into this directly: // app/+native-intent.tsx import { createDetourNativeIntentHandler } from "@swmansion/react-native-detour/expo-router"; export const redirectSystemPath = createDetourNativeIntentHandler({ fallbackPath: "/", hosts: [/.godetour.link$/i], }); This acts as pre-routing middleware. When the app launches, Detour checks whether this is a deferred deep link, resolves the original URL, and feeds it to the router before any screen mounts. Handle the auth gate There's a common catch, though: the auth gate. A user taps an invite link, installs the app, and opens it. Detour resolves the original URL. But the user isn't logged in yet, so your auth guard redirects them to /login. The resolved link gets swallowed. DetourProvider solves this by holding the link intent in memory until your app signals the user is ready: // app/_layout.tsx import { DetourProvider, useDetourContext } from "@swmansion/react-native-detour"; export default function RootLayout() { return ( <DetourProvider config={{ appID: "YOUR_APP_ID", apiKey: "YOUR_API_KEY" }}> <AuthProtectedStack /> </DetourProvider> ); } function AuthProtectedStack() { const { link, clearLink, isLinkProcessed } = useDetourContext(); const { isSignedIn } = useAuth(); // Your logic const router = useRouter(); useEffect(() => { if (isLinkProcessed && link && isSignedIn) { clearLin