Create a reproducible npm project, define lifecycle scripts, load configuration with the built-in environment-file support, and distinguish runtime settings from secrets.
What you will build
This tutorial produces a working, verifiable result rather than a command list. Read each command before running it, keep configuration in version control without secrets, and record the versions used for repeatable deployment.
1. Prepare the project
mkdir node-project && cd node-project
npm init -y
npm pkg set type=module
npm pkg set engines.node='>=24 <25'
npm pkg set scripts.start='node src/server.js'
npm pkg set scripts.dev='node --watch src/server.js'
mkdir src
printf 'PORT=3000nAPP_ENV=developmentn' > .env
printf '.envnnode_modules/n*.logn' > .gitignore
Run preparation commands as an unprivileged application user unless a command explicitly requires sudo. A clean working tree and lockfile make rollback much easier.
2. Implement the solution
// src/server.js
const port = Number.parseInt(process.env.PORT ?? '3000', 10);
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error('Invalid PORT');
console.log({ port, environment: process.env.APP_ENV ?? 'production' });
Save the example in the filename indicated by its comment or surrounding instructions. Treat it as a minimal baseline: production applications should separate transport, business logic, persistence, and configuration into testable modules.
3. Verify end to end
node --env-file=.env src/server.js
npm start
npm install --package-lock-only
npm ci
git status --short
Verification should cover both process state and a real request or data operation. A process that is merely running is not necessarily ready to serve traffic.
4. Troubleshooting and production notes
npm ci requires a package-lock.json synchronized with package.json. Keep real secrets outside Git and inject them at runtime. Validate environment values at startup because every process.env value is a string or undefined.
Production checklist
- The supported Node.js LTS version and dependency lockfile are recorded.
- Configuration is validated at startup and secrets are stored outside source control.
- Input limits, authentication, authorization, timeouts, and error boundaries are explicit.
- Logs identify a request without exposing credentials or personal data.
- Health checks, graceful termination, resource limits, backup, and rollback have been tested.
Reference: official topic documentation. For production version selection, use a supported LTS line from the Node.js release schedule.