tnl.dev :: docs
frameworks.
Connect your app to tnl dev.
choose an integration
tnl dev needs to know which local HTTP listener to publish. tnl init wires up recognized projects or prints the action needed for custom files. Pick the integration for your app:
| App | Connection to tnl dev |
|---|---|
| Vite | Add the tnl() plugin. |
| Next.js | Wrap the config in withTnl(). |
| Node or Bun HTTP server | Use tnl.port and register the server. |
| Other app | Use a fixed tnl dev --port. |
api servers
On Node or Bun, tnl.port is 0 under tnl dev so the OS selects a free port; outside tnl it uses the usual runtime port or 3000. Register the actual bound HTTP server with await tnl.register(server). For example, with Node:
import { createServer } from "node:http";
import { tnl } from "@tnldotdev/tnl";
const server = createServer((_request, response) => response.end("hello"));
server.listen(tnl.port, "127.0.0.1");
await tnl.register(server);With Bun:
import { tnl } from "@tnldotdev/tnl";
const server = Bun.serve({
hostname: "127.0.0.1",
port: tnl.port,
fetch: () => new Response("hello"),
});
await tnl.register(server);Keep your existing server framework: register the server returned by Express's app.listen(tnl.port) or Hono's Node serve({ fetch: app.fetch, port: tnl.port }); for Fastify, await app.listen({ port: tnl.port }), then register app.server. For Bun with Hono, pass app.fetch to Bun.serve. If tnl init cannot safely change a custom entrypoint, make these edits yourself. The target must be local HTTP, not HTTPS or a remote host. See the development workflow.
use a service url in your app
When your project configuration defines web and api, tnl generates browser-safe metadata for their worktree-specific public URLs. Read the API URL from the frontend or server:
import { tnl } from "@tnldotdev/tnl";
const apiURL = tnl.services?.api?.url;tnl dev updates metadata for configured projects; run tnl config generate to generate it without starting a tunnel. Include .tnl/project.d.ts in TypeScript for typed service names and ignore .tnl/ in Git. The URL may exist before the API service is running. The metadata contains no access token; your app still handles authentication. See project metadata and security.