deep-linking
Universal Links, App Links, and URL scheme configuration.
When & Why to Use This Skill
This Claude skill provides comprehensive guidance and boilerplate configurations for implementing deep linking in mobile applications. It simplifies the complex process of setting up Universal Links for iOS, App Links for Android, and custom URL schemes, ensuring seamless navigation between web content and mobile apps while supporting modern frameworks like Expo Router.
Use Cases
- Configuring custom URL schemes in Expo's app.json to enable basic app-to-app communication and redirection.
- Generating apple-app-site-association (AASA) files to support iOS Universal Links for a seamless web-to-app transition.
- Setting up Android App Links with intent filters and assetlinks.json for secure, verified deep linking without disambiguation dialogs.
- Implementing dynamic routing and parameter handling using Expo Router to map web URLs directly to specific app screens.
- Providing ready-to-use CLI commands for testing deep link triggers on both iOS Simulators and Android Emulators.
| name | deep-linking |
|---|---|
| description | Universal Links, App Links, and URL scheme configuration. |
Deep Linking
URL Schemes
// app.json
{
"expo": {
"scheme": "myapp"
}
}
// Handle myapp://path
import * as Linking from 'expo-linking';
const url = Linking.createURL('path/to/screen', {
queryParams: { id: '123' },
});
// myapp://path/to/screen?id=123
Universal Links (iOS)
// app.json
{
"expo": {
"ios": {
"associatedDomains": ["applinks:example.com"]
}
}
}
// /.well-known/apple-app-site-association
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAM_ID.com.example.app",
"paths": ["/product/*", "/user/*"]
}
]
}
}
App Links (Android)
// app.json
{
"expo": {
"android": {
"intentFilters": [
{
"action": "VIEW",
"autoVerify": true,
"data": [
{
"scheme": "https",
"host": "example.com",
"pathPrefix": "/product"
}
],
"category": ["BROWSABLE", "DEFAULT"]
}
]
}
}
}
// /.well-known/assetlinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["..."]
}
}]
Expo Router
// app/_layout.tsx
export default function Layout() {
return (
<Stack>
<Stack.Screen name="product/[id]" />
</Stack>
);
}
// app/product/[id].tsx
export default function ProductScreen() {
const { id } = useLocalSearchParams();
// https://example.com/product/123 -> id = "123"
}
Testing
# iOS Simulator
xcrun simctl openurl booted "myapp://product/123"
# Android Emulator
adb shell am start -a android.intent.action.VIEW -d "myapp://product/123"