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:
| File | URL |
|---|---|
index.tsx | myapp:// |
settings.tsx | myapp://settings |
users/[userId].tsx | myapp://users/123 |
posts/[postId]/comments.tsx | myapp://posts/42/comments |
Testing Deep Links
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" --androidHandling 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,
});Universal Links (iOS)
For HTTPS links that open your app:
- Configure associated domains in
teardown.config.ts:
export default {
ios: {
associatedDomains: ["applinks:myapp.com"],
},
};- Host an
apple-app-site-associationfile at:https://myapp.com/.well-known/apple-app-site-association
{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAMID.com.example.myapp",
"paths": ["*"]
}]
}
}App Links (Android)
For HTTPS links that open your app on Android:
- Configure in
teardown.config.ts:
export default {
android: {
intentFilters: [{
action: "VIEW",
autoVerify: true,
data: [{
scheme: "https",
host: "myapp.com",
pathPrefix: "/",
}],
category: ["BROWSABLE", "DEFAULT"],
}],
},
};- 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
- API Reference - Full API documentation