npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-deeplink-manager

v1.0.0

Published

A comprehensive deep linking solution for React Native

Readme

react-native-deeplink-manager

A comprehensive deep linking solution for React Native that handles everything related to deep linking - from parsing URLs to navigation integration.

Features

  • Universal Deep Link Support: Handle both custom schemes (myapp://) and universal/app links (https://myapp.com)
  • Smart Routing: Pattern-based URL matching with path parameters (:id) and query strings
  • Cold & Warm Start Handling: Seamlessly handle links whether your app is closed or running
  • Navigation Adapters: Out-of-the-box support for React Navigation and Expo Router
  • Link Building: Programmatically generate deep links with type safety
  • Auth Guards: Run validation before navigation with beforeNavigate hooks
  • Deferred Deep Links: Store and process links when app isn't ready
  • TypeScript First: Full TypeScript support with excellent type inference

Installation

npm install react-native-deeplink-manager
# or
yarn add react-native-deeplink-manager

Quick Start

With React Navigation

import { useRef, useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import {
  createDeepLinkHandler,
  createReactNavigationAdapter,
  createNavigationRef,
} from 'react-native-deeplink-manager';

const Stack = createNativeStackNavigator();
const navigationRef = createNavigationRef();

function App() {
  useEffect(() => {
    const handler = createDeepLinkHandler({
      config: {
        schemes: ['myapp'],
        prefixes: ['https://myapp.com', 'https://www.myapp.com'],
        routes: [
          { path: '/home', name: 'Home' },
          { path: '/user/:id', name: 'UserProfile' },
          { path: '/posts/:postId', name: 'PostDetail' },
        ],
      },
    });

    const adapter = createReactNavigationAdapter(navigationRef);
    handler.initialize(adapter);

    return () => handler.destroy();
  }, []);

  return (
    <NavigationContainer ref={navigationRef}>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="UserProfile" component={UserProfileScreen} />
        <Stack.Screen name="PostDetail" component={PostDetailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

With Expo Router

import { useEffect } from 'react';
import { useRouter } from 'expo-router';
import {
  createDeepLinkHandler,
  createExpoRouterAdapter,
} from 'react-native-deeplink-manager';

export default function Layout() {
  const router = useRouter();

  useEffect(() => {
    const handler = createDeepLinkHandler({
      config: {
        schemes: ['myapp'],
        prefixes: ['https://myapp.com'],
        routes: [
          { path: '/', name: 'index' },
          { path: '/user/:id', name: 'user' },
          { path: '/posts/:postId', name: 'post' },
        ],
      },
    });

    const adapter = createExpoRouterAdapter(router);
    handler.initialize(adapter);

    return () => handler.destroy();
  }, []);

  return <Slot />;
}

Core Concepts

Route Configuration

Define your app's deep link routes with path patterns:

const routes = [
  {
    path: '/home',
    name: 'Home',
    exact: true, // Optional: exact match only
  },
  {
    path: '/user/:id',
    name: 'UserProfile',
  },
  {
    path: '/posts/:postId/comments/:commentId',
    name: 'CommentDetail',
  },
];

Path Parameters

Use :paramName syntax to capture dynamic segments:

// URL: myapp://myapp.com/user/123
// Route: /user/:id
// Extracted params: { id: '123' }

// URL: myapp://myapp.com/posts/456/comments/789
// Route: /posts/:postId/comments/:commentId
// Extracted params: { postId: '456', commentId: '789' }

Query Parameters

Query parameters are automatically parsed:

// URL: myapp://myapp.com/search?q=react&category=mobile
// Extracted queryParams: { q: 'react', category: 'mobile' }

Auth Guards

Add navigation guards with beforeNavigate:

const routes = [
  {
    path: '/profile',
    name: 'Profile',
    beforeNavigate: async (params) => {
      const isAuthenticated = await checkAuth();
      if (!isAuthenticated) {
        // Navigate to login instead
        return false;
      }
      return true;
    },
  },
];

Advanced Usage

Building Deep Links

Generate deep links programmatically:

import { createDeepLinkBuilder } from 'react-native-deeplink-manager';

const builder = createDeepLinkBuilder('myapp', 'myapp.com');

// Simple path
const homeLink = builder.build('/home');
// Result: myapp://myapp.com/home

// With path params
const userLink = builder.build('/user/:id', { id: '123' });
// Result: myapp://myapp.com/user/123

// With query params
const searchLink = builder.build('/search', undefined, {
  q: 'react native',
  page: 1,
});
// Result: myapp://myapp.com/search?q=react%20native&page=1

// Combined
const link = builder.build(
  '/user/:id/posts/:postId',
  { id: '123', postId: '456' },
  { ref: 'notification' }
);
// Result: myapp://myapp.com/user/123/posts/456?ref=notification

Manual Link Handling

Handle links manually when needed:

const handler = createDeepLinkHandler({ config });
const adapter = createReactNavigationAdapter(navigationRef);
await handler.initialize(adapter);

// Handle a specific URL
await handler.handleLink('myapp://myapp.com/user/123');

Deferred Deep Links

Handle links when your app isn't ready:

const handler = createDeepLinkHandler({ config });

// Store a link for later
handler.setPendingLink('myapp://myapp.com/user/123');

// Later, when ready...
const pendingLink = handler.getPendingLink();
if (pendingLink) {
  await handler.handleLink(pendingLink);
  handler.clearPendingLink();
}

Custom Adapters

Create a custom navigation adapter:

import type { NavigationAdapter, RouteMatch } from 'react-native-deeplink-manager';

const customAdapter: NavigationAdapter = async (match: RouteMatch) => {
  // Your custom navigation logic
  const { route, params, queryParams } = match;

  console.log('Navigating to:', route.name);
  console.log('Params:', params);
  console.log('Query:', queryParams);

  // Implement your navigation
  MyNavigator.navigate(route.name, { ...params, ...queryParams });
};

handler.initialize(customAdapter);

Event Callbacks

Track deep link events:

const handler = createDeepLinkHandler({
  config: {
    schemes: ['myapp'],
    routes: [...],
    onLinkNotMatched: (url) => {
      console.log('No route matched for:', url);
      // Track analytics, show error, etc.
    },
  },
  onColdStart: (url, match) => {
    console.log('App opened from link:', url);
    // Track app opens from links
  },
  onWarmStart: (url, match) => {
    console.log('Link received while app running:', url);
    // Track in-app deep links
  },
});

Working with the Router

Access the router directly for advanced use cases:

const handler = createDeepLinkHandler({ config });
const router = handler.getRouter();

// Add a route dynamically
router.addRoute({
  path: '/new-feature',
  name: 'NewFeature',
});

// Remove a route
router.removeRoute('OldFeature');

// Get all routes
const allRoutes = router.getRoutes();

// Match a URL
const match = router.match('myapp://myapp.com/user/123');
if (match) {
  console.log('Route:', match.route.name);
  console.log('Params:', match.params);
}

// Match and validate
const validMatch = await router.matchAndValidate(url);

Platform Setup

iOS - Universal Links

  1. Add associated domains to your entitlements:
<!-- ios/YourApp/YourApp.entitlements -->
<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:myapp.com</string>
  <string>applinks:www.myapp.com</string>
</array>
  1. Host an apple-app-site-association file on your domain at https://myapp.com/.well-known/apple-app-site-association

Android - App Links

  1. Add intent filters in AndroidManifest.xml:
<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="https" android:host="myapp.com" />
</intent-filter>
  1. Host a assetlinks.json file at https://myapp.com/.well-known/assetlinks.json

Custom URL Schemes

iOS

Add to Info.plist:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string>
    </array>
  </dict>
</array>

Android

Add to AndroidManifest.xml:

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="myapp" />
</intent-filter>

API Reference

createDeepLinkHandler(options: LinkHandlerOptions)

Creates a deep link handler instance.

Options:

  • config.schemes: Array of custom URL schemes
  • config.prefixes: Array of universal link prefixes
  • config.routes: Array of route configurations
  • config.onLinkNotMatched: Callback when no route matches
  • onColdStart: Callback for cold start links
  • onWarmStart: Callback for warm start links

handler.initialize(adapter: NavigationAdapter)

Initialize the handler with a navigation adapter.

handler.destroy()

Clean up listeners and resources.

createReactNavigationAdapter(navigationRef, screenMapping?)

Create an adapter for React Navigation.

createExpoRouterAdapter(router, navigationType?)

Create an adapter for Expo Router.

createDeepLinkBuilder(scheme, host)

Create a link builder instance.

TypeScript Support

The library is written in TypeScript and provides full type definitions:

import type {
  DeepLinkConfig,
  RouteConfig,
  RouteMatch,
  NavigationAdapter,
} from 'react-native-deeplink-manager';

License

MIT

Contributing

Contributions are welcome! Please open an issue or submit a PR.

Author

Oluwaseyi Roy (https://github.com/oluseyi-ged)