Skip to content

routeup.json

routeup.json works for any project and gives routeup a default route, targets, and optional command. Node projects may instead embed the same routing settings in package.json; when both exist, routeup.json wins.

routeup.json
{
"$schema": "https://raw.githubusercontent.com/mukul-mehta/routeup/main/routeup.schema.json",
"name": "example-app",
"port": 8080
}

With this present, run:

terminal
routeup serve

The configured name and port are used directly when no explicit name is passed. An explicit name is always literal, so routeup serve api serves route api.

$schema JSON Schema URL for editor validation and completion
name optional default route name
port the local port to proxy to (optional when using command)
command the shell command to run in script-runner mode
port_env_var additional environment variable that receives the assigned port
targets optional list of path-routed targets for one-origin frontend + API setups
expose optional public exposure settings, including paths
capture optional request/response capture settings for routeup inspect

The repository’s routeup.schema.json provides editor completion and catches unknown or invalid fields before routeup runs.

The name field is a literal default used only when no positional name or ROUTEUP_NAME is supplied. If it is omitted too, routeup uses the working-directory basename. See Name resolution.

When command is set and you run bare routeup, routeup starts your dev server and manages its lifetime. It assigns a free port, injects it as PORT, and routes to it automatically; you do not need to set port explicitly:

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

Frameworks that read PORT from the environment (Next.js, Nuxt, Express) work with no further changes. Vite and Astro need one line of config to forward process.env.PORT to server.port. See the Framework setup guide for per-framework instructions.

If a process expects another variable, port_env_var receives the same assigned port in addition to PORT:

routeup.json
{
"name": "webhook-consumer",
"command": "go run ./cmd/dev",
"port_env_var": "WEBHOOK_CONSUMER_PORT"
}

Use targets when one hostname should proxy different path prefixes to different local ports:

routeup.json
{
"name": "example-app",
"targets": [
{ "path": "/", "port": 5173 },
{ "path": "/api", "port": 9080 }
]
}

This keeps the browser on one origin, for example https://example-app.localhost/api/users, while routeup sends /api/* to the API port.

Set expose.enabled when bare routeup or routeup serve should expose the route without an explicit --expose flag:

routeup.json
{
"name": "example-app",
"port": 8080,
"expose": {
"enabled": true
}
}

By default, --expose opens every path on the route. Limit public exposure with expose.paths:

routeup.json
{
"name": "example-app",
"port": 8080,
"expose": {
"paths": ["/api/webhooks/*"]
}
}

The route still works locally at every path, but only matching paths are reachable through the public URL. Other public requests receive an intentionally ambiguous 404 response: path does not exist or is not exposed.

routeup can retain request and response data so you can inspect it later with routeup inspect <request-id>. Capture is off by default because retained data may contain secrets.

routeup.json
{
"name": "example-app",
"port": 8080,
"capture": {
"request": true,
"response": true,
"redact_headers": ["authorization", "cookie"]
}
}
Field Description
request Retain incoming request headers and body
response Retain upstream response headers and body
redact_headers Headers to omit from capture (case-insensitive); they are still forwarded to the upstream

Each captured message is bounded to 256 KiB. If a body exceeds that, routeup inspect shows a retained prefix and marks the capture as partial.

Get the request id from routeup logs, then inspect it:

terminal
routeup logs example-app --limit 1
terminal
TIME ROUTE SOURCE STATUS ID METHOD DURATION PATH
12:41:03 example-app public 200 req_Ap7kQ3mN8vR2xLzC POST 38ms /api/webhooks/github
terminal
routeup inspect req_Ap7kQ3mN8vR2xLzC

routeup looks for config in the current working directory only: there is no walk-up to parent directories. If both routeup.json and a package.json routeup block exist in the same directory, routeup.json wins.

Per-language manifests beyond package.json (such as pyproject.toml or Cargo.toml) are not read; non-JS projects use routeup.json directly.

Run routeup config to see the discovered source and resolved route, targets, runner, exposure, capture, server, and token state.