Skip to content

In the app and CI

Runtime reporter

The tiny in-app reporter that powers the live match view of rndl interactive. Dev-only, and a guaranteed no-op in production builds.

@deeplink-devtools/runtime hooks your app's Linking events and navigation state and streams { url, matchedRoute, params } to the CLI over a localhost dev transport, so rndl interactive can show exactly what your app matched against what you fired.

Install

npm install --save-dev @deeplink-devtools/runtime

react and react-native are peer dependencies; expo-router is an optional peer, only needed for the Expo Router entry point.

Usage

Pick the entry point for your router:

// Expo Router: app/_layout.tsx
import { useDeepLinkReporter } from '@deeplink-devtools/runtime/expo-router';
useDeepLinkReporter();
 
// React Navigation: next to your NavigationContainer
import { useDeepLinkReporter } from '@deeplink-devtools/runtime/react-navigation';
useDeepLinkReporter({ navigationRef });

The React Navigation hook takes the container ref you already have from createNavigationContainerRef() or useNavigationContainerRef(); the type is structural, so the package has no dependency on React Navigation itself.

Both hooks accept transport options:

OptionDefaultDescription
port7635Port the CLI listens on; match rndl interactive --port <n>.
hostlocalhostHost the CLI runs on. localhost reaches an iOS simulator directly and Android through the automatic adb reverse tunnel.

Reporting is fire-and-forget: events sent while the CLI is unreachable are buffered briefly and flushed on connect, and every failure path is silent. The reporter never throws and never logs.

The production guarantee

The reporter is dev-only and a guaranteed no-op in production. The implementation sits behind React Native's __DEV__ flag as a lazy require, so Metro constant-folds the flag in release builds and strips the entire implementation (and its imports) from the bundle. A CI assertion on the toolkit's own pipeline holds the production cost of importing all three entry points under 1KB.

You can leave the hook mounted in _layout.tsx permanently; release users ship an inert stub.

Custom routers: createReporter

If you are integrating a router the ready-made hooks do not cover, the main entry exports the low-level client:

import { createReporter } from '@deeplink-devtools/runtime';
 
const reporter = createReporter({
  router: 'my-router',   // integration name announced to the CLI
  appName: 'My App',     // optional; shown in the CLI
  platform: 'ios',       // optional; detected from React Native when omitted
  port: 7635,            // optional transport overrides
});
 
reporter.report({ url, matchedRoute, params, ts: Date.now() });
reporter.close();

createReporter returns { report, close } and follows the same rules as the hooks: silent failures, brief buffering while disconnected, and an inert stub in production builds.