This handbook takes a Node.js project from an empty folder to a running deployment: creating package.json, managing dependencies safely, structuring code, testing with the built-in test runner, and choosing where to run it. It targets current Node.js long-term-support releases and modern npm, and drops the tools and habits that older tutorials still teach.
Install a current LTS release of Node.js, run npm init -y, set "type": "module", and commit package-lock.json but never node_modules or .env. Use node --test for tests, node --watch in development, and npm ci for clean installs. Read the port from process.env.PORT, keep secrets in environment variables, and deploy to a platform that runs the same Node.js major version you developed on.
1. Install Node.js and pick a version
Use an LTS (long-term support) release for anything you'll deploy. In September 2026, Node.js 24 is the active LTS line and Node.js 22 is in maintenance; Node.js 20 and older no longer receive security fixes. Always check the schedule on nodejs.org.
A version manager such as fnm or nvm lets each project use its own version. Installation for Windows, macOS and Linux is covered in installing Node.js and npm on your local machine. Check the result:
node --version
npm --versionPin the version for your project so everyone (and your server) uses the same one:
node --version > .nvmrcFor an editor, Visual Studio Code and WebStorm both have strong Node.js support, including debugging and ESLint integration.
2. Start a project
mkdir my-api && cd my-api
npm init -y
npm pkg set type=modulenpm init -y creates package.json with default values; edit the name, description and licence afterwards. Setting "type": "module" lets you use modern import and export syntax in .js files.
The fields that matter most:
| Field | What it does |
|---|---|
| name, version | Identify the package; required only if you publish it |
| type | module for ES modules, commonjs (the default) for require |
| scripts | Named commands such as start, dev and test |
| dependencies | Packages your app needs to run |
| devDependencies | Packages needed only for development and testing |
| engines | The Node.js versions your app supports, for example >=22 |
3. Manage dependencies safely
npm install express # runtime dependency
npm install -D eslint # development-only dependency
npm uninstall express # remove a package
npm outdated # see what has newer versions
npm update # update within the ranges in package.jsonVersion ranges follow semantic versioning: ^5.1.0 accepts any 5.x release, ~5.1.0 accepts only 5.1.x patches. The exact versions actually installed are recorded in package-lock.json. Commit it, and use npm ci on servers and in CI; it installs exactly what the lock file says and fails if the two files disagree.
Supply-chain attacks through compromised npm packages are real, so keep dependencies few and reviewed:
- Run
npm auditregularly and fix what it reports. - Don't install packages you haven't checked, and be wary of names that look like popular packages with a typo.
- Install scripts can run code on your machine;
npm install --ignore-scriptsavoids that for packages that don't need them.
4. Structure the project
my-api/
├── src/
│ ├── routes/
│ ├── services/
│ └── server.js
├── test/
├── .env.example
├── .gitignore
├── package.json
└── package-lock.jsonA minimal server in src/server.js:
import express from 'express';
const app = express();
app.use(express.json());
app.get('/health', (req, res) => res.json({ ok: true }));
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on ${port}`));Add scripts to package.json:
{
"scripts": {
"start": "node src/server.js",
"dev": "node --watch --env-file=.env src/server.js",
"test": "node --test",
"lint": "eslint ."
}
}node --watch restarts on file changes, so nodemon is no longer needed, and --env-file loads a .env file without the dotenv package.
5. Version control
git init
printf "node_modules/\n.env\ndist/\n.DS_Store\n" > .gitignore
git add .
git commit -m "Initial commit"Never commit .env or any file with passwords or API keys. Commit a .env.example that lists the variable names with dummy values instead.
6. Test with the built-in runner
Node.js includes a stable test runner and assertion library, so small and medium projects don't need Mocha or Jest:
// test/math.test.js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { add } from '../src/math.js';
test('adds two numbers', () => {
assert.equal(add(2, 3), 5);
});Run npm test. Add ESLint for code style and common mistakes, and Prettier if you want automatic formatting.
7. TypeScript and build steps
Modern Node.js no longer needs Babel to run current JavaScript. For TypeScript you have two options:
- Run it directly. Recent Node.js releases can run
.tsfiles that use only erasable type syntax, stripping the types at load time. Check the documentation for your Node.js version for what is supported. - Compile it. Install
typescriptas a dev dependency, runnpx tsc --init, add"build": "tsc"to your scripts, and run the compiled JavaScript fromdist/in production.
Front-end bundles (React, Vue and similar) are built with their own tools, such as Vite, and the output is served as static files.
8. Publish a package to npm (optional)
Most apps are never published. If you're sharing a library:
- Prepare package.json.Set a unique
name, aversion,exportsormain, alicense, and afileslist so only what users need is included. - Secure your npm accountwith two-factor authentication.
- Check the contentswith
npm pack --dry-run. - Publishwith
npm publish(add--access publicfor a scoped package like@you/pkg). From CI, prefer npm's trusted publishing or a short-lived granular token over a long-lived token. - Release updates with `npm version patchminor | major
, then publish again. Usenpm deprecate` rather than unpublishing a version others depend on.
For monorepos, npm workspaces ("workspaces": ["packages/*"]) link local packages together and install them in one step.
9. Deploy to production
Whatever you deploy to, the same rules apply:
- Install with
npm ci --omit=devand setNODE_ENV=production. - Read the port from
process.env.PORT, and on container platforms bind to0.0.0.0. - Keep secrets in environment variables, never in the repository.
- Run the same Node.js major version as in development.
- Keep the process running with the platform's manager, or with PM2 or systemd on your own server.
Where to run it on Domain India
| Option | Best for | What to know |
|---|---|---|
| App Platform | Most Node.js apps and APIs | Node.js is detected automatically from package.json; deploy with Deploy Now or a deploy token from CI; no SSH access |
| Shared hosting (cPanel, DirectAdmin) | Small apps next to a website | Runs through the panel's Node.js tool behind Apache; build locally, and it isn't for background workers |
| VPS | Full control, custom services, databases | Self-managed with root access; you install Node.js, PM2 or systemd, and a reverse proxy |
Guides: getting started with the App Platform, deploying a Node.js app on shared hosting, and PM2 process management for a VPS. App Platform plans are ₹100, ₹250 and ₹500 a month (Domain India list prices on 23 September 2026, excluding 18% GST).
- 512 MB RAM per app
- 1 vCPU
- 5 GB NVMe SSD
- PostgreSQL Database
10. Troubleshooting common problems
npm cifails because the lock file is out of sync: runnpm installlocally, commit the updatedpackage-lock.json, and try again.- Peer dependency conflicts: update the packages involved to compatible versions. Use
--legacy-peer-depsonly as a temporary workaround. EACCESerrors on global installs: don't usesudo npm; use a version manager so Node.js lives in your home folder.- "Cannot use import statement outside a module": add
"type": "module"topackage.jsonor rename the file to.mjs. - Deprecated package warnings: check whether you depend on it directly (
npm ls package-name) and replace or update it.
Which Node.js version should I use for a new project?
Use the active LTS release, which is Node.js 24 in September 2026. Check nodejs.org for the current schedule, and run the same major version in production.
Should I commit package-lock.json?
Yes. It records the exact versions installed, so every machine and server gets the same dependencies. Commit it and use npm ci for clean installs.
Should I commit node_modules?
No. Add node_modules to .gitignore. It is rebuilt from package.json and package-lock.json with npm ci.
Do I still need nodemon and dotenv?
Not for most projects. node --watch restarts your app on file changes, and node --env-file loads a .env file, both built into current Node.js releases.
What is the difference between dependencies and devDependencies?
Dependencies are needed to run your app. devDependencies, such as linters and test tools, are needed only during development and are skipped by npm ci --omit=dev.
Can I run a Node.js app on Domain India shared hosting?
Yes, small apps run through the Node.js tool in cPanel or DirectAdmin, behind Apache. For larger apps, background workers or anything needing more control, use the App Platform or a VPS.
Does the Domain India App Platform detect Node.js apps automatically?
Yes. Node.js apps are detected from package.json. Add a start script, listen on the PORT environment variable and bind to 0.0.0.0. Other languages need a Dockerfile.
Ready to ship your app? See App Platform plans, read getting started with the App Platform, or choose a VPS if you want to manage the server yourself.
Node.js detected automatically, with PostgreSQL, free SSL and custom domains included.
See App Platform plans