tnl.dev :: docs

next.js.

Run a Next.js app through tnl with its actual port.

wrap the next.js config

Wrap your existing Next.js config with withTnl. tnl init can add the wrapper to a new config or point you to an existing config that needs editing:

next.config.ts
import { withTnl } from "@tnldotdev/tnl/next";
 
export default withTnl({ reactStrictMode: true });

Keep your other Next.js settings inside the wrapper. withTnl() also accepts a config factory. Use Next.js 16.3.4 or newer; put tunnel settings in project configuration, not in withTnl().

start next.js with tnl

Set the project's dev.command to ["next", "dev"] (and include any Next.js flags you need), then run the service with tnl dev. You may set package.json's dev script to tnl dev afterward. Do not set dev.command to pnpm dev or npm run dev in that case; it would start tnl again. If your project has multiple services, pass the service name.

The wrapper adds the public hostname to Next.js development origins and reports the port Next.js actually bound, including a fallback when 3000 is taken. If you pass tnl dev --port 3000, Next.js must use that exact port. Live reload works through the public URL.

use service urls

Read project service URL metadata from a server or client component:

app/page.tsx
"use client";
 
import { tnl } from "@tnldotdev/tnl";
 
export default function Page() {
  return <p>API: {tnl.services?.api?.url ?? "not configured"}</p>;
}

The wrapper supplies browser-safe metadata during development without changing production builds. The API service has its own tunnel; start it separately if the page needs to call it. See multiple services.