Deploying
Deploy a Node.js app (Express, Fastify, NestJS)
How DployHub detects and deploys Node.js apps: package manager, build and start commands, port detection and the settings you can override.
Updated 3 min read
Any repository with a package.json at its root folder is treated as a Node.js project. DployHub picks the package manager, build command, start command and port for you, builds on node:20-alpine with NODE_ENV=production, and runs the result with zero-downtime releases. This guide explains each detection rule so you know exactly what will happen.
Package manager and install
We read your lockfile to decide how to install dependencies:
pnpm-lock.yamlmeans pnpm.yarn.lockmeans yarn.- Otherwise npm:
npm ci || npm installwhen apackage-lock.jsonexists, elsenpm install.
If your package.json has a build script, we run it as the build command (npm run build, yarn build or pnpm build).
Start command
We look for a way to start your server in this order:
- A
startscript:npm start(oryarn start/pnpm start). - NestJS with a
start:prodscript:npm run start:prod. - Next.js:
npx next start. Nuxt:node .output/server/index.mjs. - Otherwise
nodewith themainfield, or the first ofserver.js,index.js,app.js,src/index.js,src/server.jsthat exists.
If none of these is found the build stops with: We could not tell how to start your app. Add a "start" script to package.json, or set a start command. The fix is a one-line start script:
{
"name": "shop-api",
"scripts": {
"build": "tsc",
"start": "node dist/server.js"
}
}Port detection
We check the start script for PORT=4000, --port 4000 or -p 4000, then the entry file for a literal such as process.env.PORT || 4000 or .listen(4000). If nothing is found we use 3000. We always set the PORT environment variable, so the safest pattern is:
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('ok'));
const port = process.env.PORT || 3000;
app.listen(port, '0.0.0.0', () => console.log('listening on ' + port));Front-end only projects
If the project has a build script but no server framework (Express, Fastify, Koa, Hapi, NestJS, Next.js, Nuxt, Remix, SvelteKit, Astro node adapter or Hono), we treat it as a static front-end and serve the build output. React, Vue, Angular, Vite, Gatsby and Astro sites are covered in Deploy a static site.
Overriding detection
Pick Node.js under How to build it to skip auto-detection, and set any field yourself: build command, start command, port, root folder and health check path. All of these can also be changed later in the app Settings. Store secrets as environment variables, never in the repository.
There is also a quick framework guide at /deploy/nodejs and /deploy/express. If a build fails in a way the logs do not explain, raise a ticket.
Frequently asked questions
Which Node.js version is used?
Detected Node.js apps build and run on node:20-alpine. If you need another version, use your own Dockerfile.
Do you support pnpm and yarn?
Yes. A pnpm-lock.yaml selects pnpm and a yarn.lock selects yarn; otherwise npm is used.
What port should my app listen on?
Read process.env.PORT and listen on 0.0.0.0. We always set PORT to the port configured for the app.
Related articles
- Deploy a Next.js app to productionDeploy a Next.js app on DployHub: automatic build with next build, start with next start, correct port handling, environment variables and staging.
- Build settings: build, start, root folder and moreEvery DployHub build setting explained: build type, build and start commands, port, root folder, Dockerfile path and health check path, with examples.
- Port and health checks for zero-downtime deploysHow DployHub uses your port and health check path to release new versions with zero downtime, what the failure messages mean and how to fix them.
- Set environment variables for staging and liveAdd API keys, database URLs and other settings as environment variables on DployHub, separately for staging and live, and apply them with a redeploy.
- Deploy with your own DockerfileUse your own Dockerfile on DployHub for full control over the runtime: how detection works, the EXPOSE port rule, Dockerfile path and best practices.