NexosNexos

Dev Preview Mode

Dev mode turns a preview environment into a long-lived hot-reload dev server instead of a compiled production image. The first push to a branch cold-starts it; every push after that just syncs your source into the running container and the framework’s file watcher reloads — so the push→preview loop drops from minutes to seconds.

When to use it. Tight iteration loops — especially AI agents that push to a branch over and over. Each change is a fast hot reload, not a full image build. When you’re ready to merge, a real production build runs so you still validate the thing you actually ship.

How it works

  1. The first deploy to a branch clones the repo into a persistent checkout on the node, starts a container from a framework base image (e.g. node:20) with your source bind-mounted, runs the install step once, and launches the framework dev server (next dev, vite, flask --debug, …).
  2. Every later push git fetchs and resets the checkout in place. Because the source is bind-mounted, the dev server’s watcher picks the change up and hot-reloads — no rebuild, no new container.
  3. The container is only restarted when a lockfile (package-lock.json, requirements.txt, go.sum, …) changes, which re-runs the install step. The dependency cache (e.g. node_modules) lives in a volume that survives restarts.

Choosing the mode

Set a project’s preview mode policy in project settings, in nexos.yaml, or via the API / MCP. Three options:

  • Production (default) — every deploy compiles the production Dockerfile. Highest fidelity, slowest feedback.
  • Draft-based — draft PRs run a hot-reload dev server; marking the PR ready for review flips the environment to a compiled production build (and converting back to draft flips it back to dev). The best default for branch-per-change iteration.
  • Always dev — every environment runs the dev server. Fastest loop; not production parity.

In nexos.yaml:

preview:
  mode: draft-based   # prod | dev | draft-based

Multi-service projects

Each service decides its own path. A long-running service hot-reloads when it declares a dev_command; a service without one (say a Go API with no watch story) still compiles, even inside a dev environment — you’ll see Compiling non-dev service <name> in the logs. Multi-service projects have no per-service framework detection, so give every service you want hot-reloaded a dev_command in nexos.yaml:

containers:
  - name: web
    port: 3000
    dev_command: npm run dev -- -p $PORT -H 0.0.0.0
  - name: api
    port: 4000
    dev_command: npm run start:dev
  - name: migrate
    type: job
    command: npx prisma migrate deploy
    dev_watch: ["prisma/**"]   # re-run only when migrations change

dev_image and dev_install are optional — they fall back to the project’s detected-framework defaults (e.g. node:20 + npm install). Set them per service only when a service needs a different base image or install step.

Database migrations

Migration jobs (type: job) don’t hot-reload — they run a command and exit. In dev mode a job re-runs on a sync only when one of its dev_watch paths changed between commits (defaulting to the service’s build context). So editing a component reloads instantly without touching the database, but adding a migration re-applies it against the live database automatically.

Trade-offs

  • Not production parity. Dev servers behave differently from a production build (unminified, source maps, dev-only code paths). Preview URLs in dev mode are clearly badged DEV in the dashboard — don’t treat them as a release artifact.
  • Resource profile. Dev mode removes the per-push build spike but keeps a warm container running, so the cost shifts from build minutes to runtime. Lean on auto-pause to stop idle dev environments; runtime billing is settled at pause so idle time isn’t charged.
Operator note. Dev mode is gated by the platform-wide DEV_MODE_ENABLED flag. When it is off, every project runs the production build regardless of its policy. Self-hosters enable it once their node agents support dev runtimes.