deploy.json reference
Lock in the build, start, env, and ports.
Drop a deploy.json at the repo root to override auto-detection.
Every field is optional.
Full example
{
"name": "my-app",
"build": "pnpm install && pnpm build",
"start": "pnpm start",
"port": 3000,
"healthCheck": "/api/health",
"env": {
"NODE_ENV": "production"
},
"buildEnv": {
"NODE_VERSION": "20"
},
"rootDir": "./apps/web",
"ignorePaths": ["docs/", "README.md"]
}
Field reference
| Field | Purpose |
|---|---|
name | Display name. Falls back to project name. |
build | Build command. Defaults to detected. |
start | Start command. Defaults to detected. |
port | Port the container listens on. Default: detected from framework. |
healthCheck | HTTP path we hit to confirm container is up. Default: /. |
env | Runtime env vars. Merged with vars set in the dashboard. Dashboard wins on conflict. |
buildEnv | Build-time env vars. Available only during the build. |
rootDir | If your app isn't at the repo root (monorepo), point here. |
ignorePaths | Don't trigger rebuilds when only these change. |
Monorepo example
For a apps/web next.js app in a Turbo monorepo:
{
"rootDir": "./apps/web",
"build": "cd ../.. && pnpm install && pnpm --filter web build",
"start": "node .next/standalone/server.js",
"port": 3000
}
Why use a Dockerfile instead
For complex setups (custom Linux packages, native deps, multi-stage
builds), a Dockerfile gives you total control. We'll build it and
run the result. No deploy.json interaction needed — the Dockerfile
wins.
Environment-specific configs
You can't ship multiple deploy.jsons by branch yet. Use env vars
for environment differences. We're adding per-environment configs
in v2 (multi-service stacks already support this — see
Compose import).