> ## Documentation Index
> Fetch the complete documentation index at: https://docs.a0.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Deep Links

> Configure URL schemes to enable deep linking into your a0 app

# Deep Links

Deep links allow users to open your app directly from a URL, enabling features like email verification links, social sharing, and custom integrations.

<Info>
  Deep links use URL schemes (like `myapp://`) to open your app and optionally navigate to specific content within it.
</Info>

## Overview

When you configure deep link schemes in your `build.yaml`, a0 automatically:

1. Registers the URL schemes with iOS (Info.plist)
2. Adds intent filters to Android (AndroidManifest.xml)
3. Configures Expo to recognize the schemes at runtime

<Note>
  Your app's bundle ID is automatically added as a scheme, so you always have at least one working deep link scheme without any configuration.
</Note>

## Configuration

Add the `schemes` property to your `.a0/build.yaml` file:

```yaml theme={null}
general:
  runtimeVersion: "exposdk:54.0.0"

schemes:
  - myapp
  - myapp-dev

ios:
  versionName: "1.0.0"

android:
  versionName: "1.0.0"
```

<Warning>
  Schemes must be lowercase and start with a letter. They can only contain letters, digits, plus signs (+), hyphens (-), and dots (.).
</Warning>

## Handling Deep Links

Use the `expo-linking` library to handle incoming deep links in your app.

### Basic Setup

```tsx theme={null}
import * as Linking from 'expo-linking';
import { useEffect } from 'react';

export default function App() {
  useEffect(() => {
    // Handle deep link when app is already open
    const subscription = Linking.addEventListener('url', ({ url }) => {
      handleDeepLink(url);
    });

    // Handle deep link that opened the app
    Linking.getInitialURL().then((url) => {
      if (url) {
        handleDeepLink(url);
      }
    });

    return () => subscription.remove();
  }, []);

  const handleDeepLink = (url: string) => {
    const parsed = Linking.parse(url);
    console.log('Deep link received:', parsed);
    // Navigate based on parsed.path and parsed.queryParams
  };

  return (
    // Your app content
  );
}
```

### Creating Deep Link URLs

Generate URLs that open your app:

```tsx theme={null}
import * as Linking from 'expo-linking';

// Create a URL with your custom scheme
const url = Linking.createURL('profile/123', {
  scheme: 'myapp',
  queryParams: { ref: 'email' }
});
// Result: myapp://profile/123?ref=email
```

### With React Navigation

If you're using React Navigation, configure deep linking in your navigation container:

```tsx theme={null}
import { NavigationContainer } from '@react-navigation/native';

const linking = {
  prefixes: ['myapp://', 'myapp-dev://'],
  config: {
    screens: {
      Home: '',
      Profile: 'profile/:id',
      Settings: 'settings',
    },
  },
};

export default function App() {
  return (
    <NavigationContainer linking={linking}>
      {/* Your navigators */}
    </NavigationContainer>
  );
}
```

## Testing Deep Links

<Tabs>
  <Tab title="iOS Simulator">
    Use the `xcrun` command to test deep links on iOS:

    ```bash theme={null}
    xcrun simctl openurl booted "myapp://profile/123"
    ```
  </Tab>

  <Tab title="Android Emulator">
    Use `adb` to test deep links on Android:

    ```bash theme={null}
    adb shell am start -a android.intent.action.VIEW -d "myapp://profile/123"
    ```
  </Tab>

  <Tab title="Physical Device">
    The easiest way to test on a physical device:

    1. Send yourself a message (email, Slack, etc.) containing the deep link URL
    2. Tap the link to open your app
  </Tab>
</Tabs>

## Common Use Cases

<AccordionGroup>
  <Accordion title="Email verification">
    Send users a verification link that opens your app and marks their email as verified:

    ```tsx theme={null}
    // In your email: myapp://verify?token=abc123

    const handleDeepLink = (url: string) => {
      const { path, queryParams } = Linking.parse(url);
      if (path === 'verify' && queryParams?.token) {
        verifyEmail(queryParams.token);
      }
    };
    ```
  </Accordion>

  <Accordion title="Password reset">
    Allow users to reset their password from an email link:

    ```tsx theme={null}
    // In your email: myapp://reset-password?token=xyz789

    const handleDeepLink = (url: string) => {
      const { path, queryParams } = Linking.parse(url);
      if (path === 'reset-password' && queryParams?.token) {
        navigation.navigate('ResetPassword', { token: queryParams.token });
      }
    };
    ```
  </Accordion>

  <Accordion title="Content sharing">
    Let users share specific content that opens directly in your app:

    ```tsx theme={null}
    // Shared link: myapp://post/456

    const handleDeepLink = (url: string) => {
      const { path } = Linking.parse(url);
      const match = path?.match(/^post\/(\d+)$/);
      if (match) {
        navigation.navigate('Post', { id: match[1] });
      }
    };
    ```
  </Accordion>

  <Accordion title="Referral links">
    Track referrals by including a code in the deep link:

    ```tsx theme={null}
    // Referral link: myapp://signup?ref=friend123

    const handleDeepLink = (url: string) => {
      const { queryParams } = Linking.parse(url);
      if (queryParams?.ref) {
        // Store referral code for attribution
        storeReferralCode(queryParams.ref);
      }
    };
    ```
  </Accordion>
</AccordionGroup>

## Automatic Bundle ID Scheme

Your app's bundle ID (e.g., `dev.a0.apps.myapp`) is automatically registered as a URL scheme. This ensures you always have a unique, collision-free scheme available even without explicit configuration.

<Tip>
  While the bundle ID scheme works, custom schemes like `myapp://` are shorter and more user-friendly for sharing.
</Tip>
