Skip to content

Framework setup

In bare runner mode, routeup resolves or assigns a port and injects it into the child process. Frameworks that read PORT automatically just work. Frameworks that do not, including Vite and Astro, need one line of config.

Variable Value
PORT local port your dev server should listen on
HOST 127.0.0.1
ROUTEUP_LOCAL_URL your stable local HTTPS URL
ROUTEUP_URL public URL when exposed, same as ROUTEUP_LOCAL_URL otherwise
NODE_EXTRA_CA_CERTS path to the routeup CA so fetch and https trust it

These are merged into the existing environment, so your other env vars are preserved.

Vite does not read PORT from the environment by default. Tell it to:

vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
server: {
port: parseInt(process.env.PORT ?? '5173'),
strictPort: true,
},
})

strictPort: true makes Vite fail instead of silently picking a different port if the one routeup assigned happens to be taken, which surfaces the conflict early instead of routing to the wrong process.

Then your routeup config needs no port at all:

routeup.json
{
"name": "example-app",
"command": "pnpm dev"
}

routeup picks a free port, injects it as PORT, and Vite reads it from process.env.PORT.

Astro has the same Vite-based dev server, so the same config applies:

astro.config.mjs
import { defineConfig } from 'astro/config'
export default defineConfig({
server: {
port: parseInt(process.env.PORT ?? '4321'),
host: '127.0.0.1',
strictPort: true,
},
})
routeup.json
{
"name": "example-site",
"command": "pnpm dev"
}

Next.js reads PORT natively. No vite.config needed:

routeup.json
{
"name": "example-next-app",
"command": "pnpm dev"
}

If you previously pinned a port with next dev -p 3000, remove -p 3000 and let routeup assign one.

Nuxt also reads PORT (or NUXT_PORT) from the environment:

routeup.json
{
"name": "example-nuxt-app",
"command": "pnpm dev"
}

These read process.env.PORT when you write your server to do so, which is the standard pattern:

const port = parseInt(process.env.PORT ?? '3000')
app.listen(port)

With that in place, the routeup config is the same minimal form — no port needed.

If you prefer a fixed port, set port in routeup config and pass that same port to your framework’s dev command:

routeup.json
{
"name": "example-app",
"port": 5173,
"command": "pnpm dev --port 5173"
}

routeup will check that port is available before starting and route to it.

The same rules apply when using the routeup block in package.json. Point script at your dev script; routeup injects PORT before running it:

package.json
{
"scripts": {
"dev": "routeup",
"dev:app": "vite"
},
"routeup": {
"name": "example-app",
"script": "dev:app"
}
}