Node.js

Last updated

Node.js is fully supported by the zip flow.

What to include

  • Your source
  • package.json, with a sensible main or a start script — this is what tells the agent how to run your app
  • package-lock.json if you have one, so the install is reproducible

Exclude node_modules. It's usually the majority of your project's size, it's reinstalled during the build anyway, and including it can push you over the archive size limit for no benefit. Also leave out .env and any local database file.

One package.json per archive. If your repository has several packages, upload one app at a time or use a Dockerfile.

Use the production start command

Generated projects and READMEs usually tell you to run the dev server. That's the wrong thing to deploy — hot reload, file watchers, unoptimised output, and often a localhost bind:

npm run dev     →   npm start

Whatever the command is, the server must bind 0.0.0.0, not localhost. Then add an HTTPS port binding for the port it listens on.

Don't add a process manager

No PM2, no forever, no cluster. The platform already restarts your process when it exits, and a supervisor inside the container hides your app's exit code — which is the most useful diagnostic you have.

cluster in particular is counterproductive here: it forks a worker per reported core, and a container sees the host's cores rather than your allocation, so you get several processes splitting one CPU budget with added overhead. One process is correct.

Storage

Anything you write outside a volume is discarded on the next deploy. Make the path configurable so the same code runs locally and here:

const dataDir = process.env.DATA_DIR || "./data";   // set DATA_DIR=/data on the app

Builds

If your project has a build step, be aware the platform's builder has less memory than your app does — bundlers are the most common thing to exceed it, usually failing part-way with no clear error.

If that happens, cap Node's heap in the build (NODE_OPTIONS=--max-old-space-size=...), or build in CI and push the image instead.

Also remember the build receives no environment variables, so anything inlined at build time — VITE_*, NEXT_PUBLIC_* — will be empty. Those need a CI build. See Configuration.

Frontend frameworks

A framework that produces static files (Vite, Create React App) needs something to serve them and a fallback so refreshing a route doesn't 404. A framework with its own server (Next.js, Nuxt) runs as a normal Node app but has its own build-time configuration rules.

Both are usually happier with a Dockerfile and git push than with a zip upload.