Deploy
Deploying Routa is compiling to dist/ and running routa start. The one setting that
almost always needs changing is the host: Routa binds to 127.0.0.1 by default, which is
correct for local development and wrong inside a container.
Before You Start
Section titled “Before You Start”- A project that passes
routa check. - Node.js 24 or later in the runtime environment.
- Knowing whether your platform assigns a port through
PORT.
-
Build. Validation runs first, so a contract error stops the deploy before it produces an artifact.
Terminal window npm run buildTerminal window pnpm run buildTerminal window yarn run buildTerminal window bun run build -
Bind to all interfaces. Set
HOSTin the environment rather than insrc/routa.ts, so local development keeps its safe default.Terminal window HOST=0.0.0.0 npm run startTerminal window HOST=0.0.0.0 pnpm run startTerminal window HOST=0.0.0.0 yarn run startTerminal window HOST=0.0.0.0 bun run start -
Accept a platform-assigned port when your host provides one.
Leave
PORTunset so the platform can inject its assigned value. For example, if the platform suppliesPORT=8080, start with only the host override:Terminal window HOST=0.0.0.0 npm run startTerminal window HOST=0.0.0.0 pnpm run startTerminal window HOST=0.0.0.0 yarn run startTerminal window HOST=0.0.0.0 bun run start
Verify
Section titled “Verify”The start log confirms the bound address:
[2026-01-01T00:00:00.000Z] INFO api.started Routa API started. {"host":"0.0.0.0","port":8080,"routes":4}What the Runtime Image Needs
Section titled “What the Runtime Image Needs”routa start reads compiled JavaScript from dist/, but it still validates the route
graph from source before starting. Keep all four in the image:
| Path | Why |
|---|---|
src/ |
Route validation reads the TypeScript source |
.routa/ |
Route metadata and the baseline used by validation |
dist/ |
The JavaScript that actually runs |
node_modules/ |
Production dependencies, including @routa-ts/cli |
This is also why generated apps keep @routa-ts/cli in dependencies rather than
devDependencies.
Container Shape
Section titled “Container Shape”Use a build stage to install every dependency and run the build, then copy source, metadata, output, and production dependencies into the runtime stage:
FROM node:24-slim AS buildWORKDIR /appCOPY . .RUN npm ci && npm run build
FROM node:24-slimWORKDIR /appENV HOST=0.0.0.0COPY --from=build /app/package.json ./package.jsonCOPY --from=build /app/src ./srcCOPY --from=build /app/.routa ./.routaCOPY --from=build /app/dist ./distRUN npm ci --omit=devCMD ["npm", "run", "start"]Configuration Precedence
Section titled “Configuration Precedence”Environment variables win over src/routa.ts, which wins over Routa’s defaults:
| Setting | Environment | Config | Default |
|---|---|---|---|
| Host | HOST |
host |
127.0.0.1 |
| Port | PORT |
port |
3000 |
Troubleshooting
Section titled “Troubleshooting”| Problem | Fix |
|---|---|
| Health checks fail although the container is running | The server bound to 127.0.0.1. Set HOST=0.0.0.0. |
Missing compiled runtime output for … Run routa build first. |
dist/ was not copied into the runtime stage, or the build stage was skipped. |
Compiled runtime output for … is stale. |
Source files were copied after the build. Copy src/ and dist/ from the same stage. |
ROUTA_PROJECT_REQUIRED at startup |
src/ or src/routa.ts is missing from the image. Validation needs the source. |