Skip to main content
@reticlehq/next gives a Next.js app the same data-reticle-source stamping the Vite plugin does, without asking it to migrate off SWC to Babel. Install it if your app is Next.js; on Vite use @reticlehq/vite-plugin instead. Unlike the Vite plugin it does not inject connect(), so you still call that yourself. Apache 2.0. CommonJS, no build step. Depends on @babel/core and @reticlehq/babel-plugin. Peer dependency: next >= 13.

Why it exists

Next users are on SWC. Telling them to switch to Babel for a dev tool would be a rude trade, and it would slow down every build they run. This adds a dev-only pre-loader for .jsx, .tsx and .js files that contain JSX, and leaves the rest of the pipeline alone.

Install and use

This package is CommonJS on purpose. next.config.js is loaded by Node before any ESM transform, so an ESM-only helper would fail at the least helpful possible moment.

Exports

.

Returns the config unchanged when NODE_ENV === 'production', unless RETICLE_DEV=1 is set (for NODE_ENV=production next dev). sourceMapping: false skips the loader rules, for an app that renders through a non-DOM React reconciler. Otherwise it merges in: Daemon discovery reads RETICLE_STATE_DIR (default ~/.reticle). Pairing tokens use RETICLE_PAIRING_TOKEN_DIR independently. The generated ReticleDev component reads NEXT_PUBLIC_RETICLE_URL; restart the dev server after changing these settings. readPairingToken(), discoverDaemonUrl() and knowsAllowedDevOrigins() are also exported at runtime. They are not declared in index.d.ts, so TypeScript will not see them.

./loader

An async webpack loader. It skips anything that is not .jsx, .tsx or a .js file containing JSX, and anything under node_modules. It lazily imports @reticlehq/babel-plugin and runs babel.transformAsync with configFile: false, babelrc: false, retainLines, and source maps on.
The loader never fails the build. Any error falls back to the original source, because a dev-only source stamp is not worth breaking someone’s next dev over.

What it does not do

It does not inject connect(). On Next you call it once, in a client component that your root layout renders. reticle init writes this component for you at app/reticle-dev.tsx (or src/app/reticle-dev.tsx). To write it by hand:
NEXT_PUBLIC_RETICLE_TOKEN is empty when the daemon has not yet written ~/.reticle/pairing-token. Start the daemon, then restart next dev.

Framework by framework

What each supported stack needs, and what it gets for free.
Last modified on October 25, 2026