Teardown

Deep Linking

Handle URLs and deep links in your app.

Deep linking allows users to open specific screens in your app via URLs. The navigation library automatically generates deep link configuration from your route structure.

How It Works

The Metro plugin generates a linking.generated.ts file with your app's deep link configuration:

.teardown/
├── linking.generated.ts   # Deep link config
└── ...

This file maps URL paths to your screens automatically.

Setup

1. Configure URL Prefixes

Set your app's URL schemes in the Metro config:

// metro.config.js
const { withTeardownNavigation } = require("@teardown/navigation-metro");

module.exports = withTeardownNavigation(config, {
  prefixes: [
    "myapp://",                    // Custom URL scheme
    "https://myapp.com",           // Universal links
  ],
});

Or in teardown.config.ts:

export default {
  name: "MyApp",
  slug: "myapp",  // Creates "myapp://" prefix automatically
  // ...
};

2. Use the Generated Config

Pass the linking config to your router:

import { createTeardownRouter } from "@teardown/navigation";
import { routeTree } from "../.teardown/routeTree.generated";
import { linking } from "../.teardown/linking.generated";

export const Router = createTeardownRouter({
  routeTree,
  linking,
});

3. Configure Native Apps

iOS

Add URL schemes to your Info.plist or teardown.config.ts:

// teardown.config.ts
export default {
  slug: "myapp",
  ios: {
    bundleIdentifier: "com.example.myapp",
    // URL scheme is derived from slug: myapp://
  },
};

For universal links, configure your associated domains:

export default {
  ios: {
    associatedDomains: ["applinks:myapp.com"],
  },
};

Android

Add intent filters in teardown.config.ts:

export default {
  slug: "myapp",
  android: {
    packageName: "com.example.myapp",
    // URL scheme is derived from slug: myapp://
  },
};

URL to Screen Mapping

Routes are automatically mapped to URL paths:

FileURL
index.tsxmyapp://
settings.tsxmyapp://settings
users/[userId].tsxmyapp://users/123
posts/[postId]/comments.tsxmyapp://posts/42/comments

iOS Simulator

xcrun simctl openurl booted "myapp://users/123"

Android Emulator

adb shell am start -W -a android.intent.action.VIEW -d "myapp://users/123"

React Native CLI

npx uri-scheme open "myapp://users/123" --ios
npx uri-scheme open "myapp://users/123" --android

Handling Initial URL

The router automatically handles the initial URL when the app is opened via a deep link. You can also access it programmatically:

import { Linking } from "react-native";

// Get the URL that opened the app
const url = await Linking.getInitialURL();

// Listen for URL events while app is running
Linking.addEventListener("url", ({ url }) => {
  console.log("Received URL:", url);
});

Custom Linking Config

Override or extend the generated linking config:

import { createTeardownRouter } from "@teardown/navigation";
import { routeTree } from "../.teardown/routeTree.generated";
import { linking as generatedLinking } from "../.teardown/linking.generated";

// Extend with custom configuration
const linking = {
  ...generatedLinking,
  prefixes: [
    ...generatedLinking.prefixes,
    "https://myapp.com",
  ],
  // Add custom path mappings
  config: {
    ...generatedLinking.config,
    screens: {
      ...generatedLinking.config?.screens,
      // Custom screen mapping
      specialRoute: "special/:id",
    },
  },
};

export const Router = createTeardownRouter({
  routeTree,
  linking,
});

For HTTPS links that open your app:

  1. Configure associated domains in teardown.config.ts:
export default {
  ios: {
    associatedDomains: ["applinks:myapp.com"],
  },
};
  1. Host an apple-app-site-association file at: https://myapp.com/.well-known/apple-app-site-association
{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "TEAMID.com.example.myapp",
      "paths": ["*"]
    }]
  }
}

For HTTPS links that open your app on Android:

  1. Configure in teardown.config.ts:
export default {
  android: {
    intentFilters: [{
      action: "VIEW",
      autoVerify: true,
      data: [{
        scheme: "https",
        host: "myapp.com",
        pathPrefix: "/",
      }],
      category: ["BROWSABLE", "DEFAULT"],
    }],
  },
};
  1. Host a Digital Asset Links file at: https://myapp.com/.well-known/assetlinks.json
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.myapp",
    "sha256_cert_fingerprints": ["YOUR_CERT_FINGERPRINT"]
  }
}]

Debugging

Enable verbose logging to debug deep link issues:

// metro.config.js
module.exports = withTeardownNavigation(config, {
  verbose: true,
});

Check the generated linking.generated.ts to verify your routes are mapped correctly.

Next Steps