Node.js
Deploy Next.js, Nuxt, Express or any Node.js app. We detect your framework and package manager, build it, and start it on port 8080.
Updated 27 Oct 20264 min read
A Node.js app deploys from its package.json. We choose Node.js 22 or 24, install your packages with the manager your lock file names, run your build script if there is one, and start the app. Your app must listen on the port in the PORT variable, which is always 8080.
Versions
| Version | Notes |
|---|---|
| Node.js 24 | What new apps get when the code doesn't ask |
| Node.js 22 | Still supported |
We read the version your code asks for from .nvmrc, .node-version or .tool-versions first, then from the engines field of package.json, and use our default, Node.js 24, when it fits, otherwise the newest version that does. >=20 builds with Node.js 24; ^22 or 22 builds with 22. If the code asks for one we no longer offer, like 20, we build with the nearest newer one, 22, and the plan says why. To pin one, choose it in the app's Set up and run settings, or set "version": "22" in tanzahost.json.
What we detect
| Your code has | We use |
|---|---|
packageManager in package.json, like yarn@4.5.1 | That exact manager and version |
pnpm-lock.yaml | pnpm |
yarn.lock | Yarn |
package-lock.json | npm, with npm ci |
| No lock file | npm, with npm install, and the plan suggests committing one |
Development packages are installed too, because builds need them (Vite, Tailwind CSS, TypeScript). NODE_ENV is production for the build and the app. A build of your assets gets the build's memory, so Vite and Next.js don't run out.
We recognise Next.js, Nuxt, Remix, SvelteKit, Astro, NestJS, Express, Fastify, Koa and Hono, workspaces (pnpm-workspace.yaml, turbo.json, nx.json, with the plan saying which folder is the app), and Prisma, Drizzle and Knex. Then we start the app this way, first match wins:
A
web:line in aProcfile.A
startscript inpackage.json:npm run start(or pnpm's or Yarn's).Next.js without one: its standalone server when
next.configsetsoutput: 'standalone', otherwisenext start -p ${PORT}. Withoutput: 'export', it's served as a static site.Nuxt: its built server,
.output/server/index.mjs, with Node.js.NestJS:
node dist/main.The
mainfile ofpackage.json, or else the first ofserver.js,server.mjs,index.js,app.jsormain.js, with Node.js.
A project with a build script and no way to start, like a React or Vue app made with Vite, is served as a static site.
Databases, caches and email, made for you
The plan reads which database your code uses (pg, mysql2, mongoose, Prisma's or Drizzle's provider) and makes it before your first deploy, with its price first: PostgreSQL and MySQL set DATABASE_URL, MongoDB sets MONGODB_URI. A Redis client (ioredis, redis, BullMQ) gets a cache. Prisma's migrations run before each version goes live (prisma migrate deploy). NEXTAUTH_SECRET, AUTH_SECRET, JWT_SECRET and SESSION_SECRET are made for you when your example file leaves them empty, and NEXTAUTH_URL is filled with your app's address. Keys only you have, like Stripe's, are listed as "Needs your key" and never invented.
Listen on PORT
Visitors reach your app's web process on port 8080, given to it as PORT. Listen on every address, not only localhost:
const express = require("express");
const app = express();
app.get("/", (req, res) => res.send("Hello from duka!"));
app.listen(process.env.PORT || 8080, "0.0.0.0");A new version gets visitors only once it answers its health address ("/" unless you choose another) with a success, within 2 minutes. If your code listens on a fixed port instead, like app.listen(3000), the first deploy finds the port it opened, serves your app from it, and tells you. See Deploying.
Example: Asha's shop API
Asha adds a second app, api, to her project duka, from a GitHub repository with Express, a package-lock.json, and an .nvmrc file that says 22. Its package.json has:
{
"scripts": {
"build": "tsc --noEmit",
"start": "tsx src/server.ts"
},
"dependencies": {
"express": "^5.1.0",
"tsx": "^4.20.0"
}
}We find Express on Node.js 22, run npm ci --include=dev, then npm run build (her type check), then start it with npm run start. It's live on its own free address, like api-duka-k2m9.tanzahost.co. Her shop's database is attached to it too, so DATABASE_URL is already in its variables.
Build variables
Next.js and Vite put some variables into the built files (like NEXT_PUBLIC_… and VITE_…), so builds get your app's variables too. After changing one of those, deploy again to rebuild.
Change what we found
On the app's page, Set up and run shows the language, version, folder, and the install, build and start commands we worked out. Change any of them; an empty field uses what we found. For an app in a folder of a larger repository (a monorepo), set Folder, like apps/api.
Workers
A queue consumer or any long-running script runs as a worker beside the web process, with its own command, like npm run worker. See Workers.