tnl.dev :: docs
vite.
connect Vite to tnl dev from the consolidated tnl package.
The Vite integration is part of @tnldotdev/tnl. It reports Vite's actual post-bind target to
tnl dev while preserving Vite's host and port behavior. During ordinary local development it
exposes generated project metadata without changing network settings; previews and builds remain
inert.
install and initialize
Vite 6.0.9 or newer and Node.js 22.18 or newer are required. Install one package:
npm install --save-dev @tnldotdev/tnl@next
npm exec -- tnl initadd the plugin
Add tnl() to the project's Vite plugins:
import tnl from "@tnldotdev/tnl/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [tnl()],
});tnl() accepts no route options. Keep Vite settings in vite.config.ts; keep the selected team,
named services, hostname, visitor policy, and development commands in
project configuration.
configure a named service
tnl init can create the service entry. The TypeScript form is:
export default {
team: "Acme Engineering",
services: {
web: {
directory: ".",
publish: { target: 5173 },
dev: { command: ["npm", "run", "dev"] },
},
},
};No explicit hostname is needed for normal development. tnl derives it from the Git worktree and the
web service name, after applying command, environment, and project-config precedence.
Start the public workflow with the project-local client:
npm exec -- tnl devIf no saved hosted session is usable, tnl opens browser authentication automatically and resumes
the same command after sign-in. Ordinary npm run dev remains local; the plugin only injects
previously generated project metadata.
how port discovery works
Vite can keep its normal next-port behavior when the preferred port is occupied. The plugin reports
the final post-bind target rather than assuming server.port succeeded, so tnl cannot accidentally
publish another process on the preferred port. During the public workflow, the plugin adds the
assigned hostname to server.allowedHosts while preserving existing server settings. Vite's
default host remains the default; an explicit server.host can independently expose the service on
the LAN without changing tnl route policy.
To require one port for an ad hoc run, pass it to tnl:
tnl dev --port 4173 -- npm run devThe plugin lets Vite report its final listener for that run, then tnl requires the registered port
to match exactly. A fallback port fails with TNL_TARGET_MISMATCH instead of publishing the wrong
local process. Middleware mode is unsupported because there is no listening port to register.
project runtime
Application code reads public project metadata from the optional root export:
import { tnl } from "@tnldotdev/tnl";
tnl?.memberNamespace;
tnl?.services.web.hostname;
tnl?.services.web.url;
tnl?.runningUnderTnlDev;Before tnl dev starts the child, tnl writes .tnl/project.json and .tnl/project.d.ts. Include
.tnl/project.d.ts in the application's TypeScript inputs. It augments tnl.services with exact
service keys and literal member-namespace, hostname, and HTTPS URL values from the selected team and
routes.
During tnl dev, runningUnderTnlDev is true. During ordinary npm run dev, the plugin can read
existing generated metadata and sets it to false without changing Vite's listener. The export is
undefined when metadata is absent and during builds and previews. tnl publish cannot inject
metadata into an already-running application process. No saved authentication or server access token
is exposed.
troubleshooting
- the integration did not connect: confirm the import is exactly
@tnldotdev/tnl/vite, runtnl devrather than the framework command alone, and reruntnl initto report any integration action still needed. - Vite selected another port: omit
--portto allow discovery, or make the configured and forced ports agree. tnl always uses the actual post-bind target. - the public hostname is rejected: preserve the plugin in
vite.config.ts; it adds only the assigned hostname and does not remove existingallowedHostsentries. - the route stays in provisioning: use
tnl statusfor the service state and follow the diagnostic's contextual help URL rather than changing Vite host settings. - visitors are denied: the current-IP policy is working. Add a narrow allow-list entry or use
tnl dev --publicintentionally.
Use development workflow for route reconciliation, ephemeral routes, and aggregate denied visitor warnings.