CoDuck Docs

#coduck.json reference

coduck.json is the source of truth for how CoDuck builds and runs your project. coduck create-existing writes it; you can edit it by hand. It is re-read on every deploy — change a command, coduck push, coduck deploy, and the new command runs. (Earlier behavior baked config at create-time; that is no longer the case.)

jsonc
{
  "projectId": "ff0c35e6-…",     // set by create-existing; don't change
  "name": "my-app",
  "dir": "./",                    // source root to push + run (see "Monorepos")
  "runtime": "node20",           // node20 | node22 | static
  "install": "npm ci",           // optional — default: npm install --include=dev
  "build": "npm run build",      // optional — default: npm run build
  "preStart": "npm run migrate", // optional — runs after build, before start
  "start": "node server.js",     // optional — default: npm start
  "port": 3000,                  // informational; bind process.env.PORT (see below)
  "instanceSize": "small"        // small | medium | large
}
{
  "projectId": "ff0c35e6-…",     // set by create-existing; don't change
  "name": "my-app",
  "dir": "./",                    // source root to push + run (see "Monorepos")
  "runtime": "node20",           // node20 | node22 | static
  "install": "npm ci",           // optional — default: npm install --include=dev
  "build": "npm run build",      // optional — default: npm run build
  "preStart": "npm run migrate", // optional — runs after build, before start
  "start": "node server.js",     // optional — default: npm start
  "port": 3000,                  // informational; bind process.env.PORT (see below)
  "instanceSize": "small"        // small | medium | large
}

#How each field drives the deploy

A deploy runs these steps in order, in your container:

  1. install — your install, else npm install --include=dev --no-audit --no-fund. (Dev deps are installed by default because build tools like Tailwind/PostCSS live there. If you override with npm ci, note NODE_ENV=production is set, so add --include=dev yourself if your build needs dev deps.)
  2. prisma generate — only if prisma/schema.prisma exists and declares models. Skipped otherwise.
  3. build — your build, else npm run build.
  4. schema bootstrap — if prisma/schema.prisma declares models and you have no preStart, CoDuck runs prisma db push. If you set preStart, CoDuck does not auto-push — you own schema setup (see Database).
  5. preStart — your preStart (e.g. prisma migrate deploy, drizzle-kit push, node scripts/migrate.js). The right place for migrations.
  6. start — your start, else npm start.

Skip a step by setting it to "" (empty string). E.g. a static/no-build app: "build": "".

#Ports — bind process.env.PORT

CoDuck assigns the port and injects it as PORT. Your app must listen on process.env.PORT, not a hardcoded value. The port field in coduck.json is informational only — if your app hardcodes 3000 but CoDuck health-checks the assigned port, the deploy fails with "responding on :3000 but health-checking : — bind process.env.PORT".

#Instance size

instanceSize (or coduck deploy --size) selects container resources. The CLI flag wins; otherwise coduck.json is used; default small.

SizeMemoryCPUPlan required
small1.5 GB1.0any paid plan
medium2.5 GB2.0Pro or Studio
large4 GB3.0Studio

A request above your plan is clamped down (and the deploy tells you). The Node build-heap ceiling auto-scales to ~80% of the tier, so heavy client builds (three.js, remotion, recharts) that OOM on small usually succeed on large.

#Monorepos / subdirectory source

dir can point at a subdirectory (e.g. "./web") while coduck.json stays at the repo root. The CLI uploads the repo-root coduck.json (and root .gitignore/.coduckignore) alongside the subtree so the server still sees your config. This requires @coduckai/cli ≥ 0.1.11 — older CLIs pushing a subdir silently omitted coduck.json, so declared commands were ignored. Run coduck --version and upgrade if needed.

One CoDuck project = one container. For a separate frontend + backend, wrap them in a single start (e.g. concurrently) or create two projects.

#Reserved environment variables

CoDuck injects these into every container and rejects them on write (setting them has no effect — platform values win). The live, authoritative list is coduck env reserved.

Key / patternWhat it is
DATABASE_URLPooled Postgres connection string (see Database).
DIRECT_URLDirect (non-pooled) Postgres URL for migrations/prisma db push.
PORTThe port to listen on. Bind process.env.PORT.
NODE_ENVSet to production in the container.
HOMEContainer home dir.
CODUCK_*All CoDuck-managed keys (CODUCK_API_KEY, CODUCK_AUTH_KEY, CODUCK_PROJECT_ID, CODUCK_API_URL, CODUCK_STORAGE_DIR, …).
NEXT_PUBLIC_CODUCK_*Browser-exposed CoDuck values (project id, auth/api URLs, subdomain).

Stripe keys (STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY) are injected only when you connect Stripe — until then you may set them yourself.

coduck env import .env skips reserved/invalid keys with a warning and imports the rest, so a .env containing DATABASE_URL won't abort the whole import.

#Next