Have you ever wanted to try Node.js, only to get stuck at the installation step? Setting up your environment can feel like a big hurdle at first, but once you know the steps, it goes more smoothly than you might expect. This guide walks you through everything from installing Node.js to putting it into practice, one step at a time.
What Is Node.js? The Basics You Need to Know
Node.js is a runtime environment that lets you run JavaScript outside of the browser. JavaScript was originally a language that ran in the browser, but Node.js brought it to the server side as well.
When I first heard about it, I was skeptical — "You can write server-side code in JavaScript?" But once I actually tried it, I was surprised by how comfortable it was to use the same language for both frontend and backend. With npm's rich package ecosystem, you can build everything from small utility scripts to full-scale web applications.
If server-side development sounds intimidating, Node.js is one of the best ways to lower that barrier.
Why Developers Choose Node.js
There are several technical reasons why Node.js has earned such wide adoption around the world.
First, there's non-blocking I/O. In traditional server-side languages, the server often had to wait while performing tasks like reading files or querying a database, leaving other requests unhandled. Node.js makes efficient use of that wait time, allowing it to handle a large number of requests concurrently. It's especially well-suited for services like chat apps and real-time notifications that maintain many simultaneous connections.
Second, the npm ecosystem is enormous. npm hosts over two million packages covering everything from authentication and database connections to image processing and email delivery. You rarely need to build common functionality from scratch, which dramatically speeds up development.
Third, the low learning curve is a real advantage. If you've already picked up JavaScript alongside HTML and CSS, you don't need to learn an entirely new language. Being able to carry over the syntax and patterns you already know from frontend work is a bigger benefit than it might sound.
LTS vs. Current: What's the Difference?
When you visit the official Node.js website, you'll see two versions: LTS (Long Term Support) and Current. Understanding the difference will save you from confusion when choosing a version.
LTS prioritizes stability and receives security updates for 30 months after release. It's the right choice for production environments and long-term projects. Even-numbered major versions (18, 20, 22, etc.) are designated as LTS.
Current is the bleeding-edge version with the latest features. It includes support for newer JavaScript syntax and performance improvements, but APIs may change. It's a good fit if you want to experiment with new features or work on short-term projects.
If you're new to Node.js, go with LTS without hesitation. It's stable, and most online tutorials and documentation are written with LTS in mind.
Installing Node.js: Step-by-Step by OS
Let's get Node.js installed. Here's how to do it on Windows, Mac, and Linux.
Using the Official Installer
The simplest approach is to download an installer from the official Node.js website. The homepage presents two options: "LTS (Recommended)" and "Current (Latest)." For beginners, LTS is the way to go — it's stable and supported for the long term.
Windows users download a .msi file; Mac users download a .pkg file. Just run the installer and follow the on-screen instructions.
Windows:
- Download the LTS
.msifile from the official website - Double-click the downloaded file to launch the installer
- Click "Next" and agree to the license terms
- The default install location is fine unless you have a specific reason to change it
- If you see a "Tools for Native Modules" checkbox, checking it will automatically install tools needed to build native C++ modules — handy to have down the road
- Click "Install" and wait for it to finish
Mac:
- Download the LTS
.pkgfile from the official website - Open the downloaded file to launch the installer
- Follow the prompts and click "Continue" until the installation is complete
On Mac, you can also install Node.js via Homebrew with brew install node. If you already use Homebrew regularly, that's a convenient option. That said, if you're planning to use a version manager (covered below), starting with nvm or fnm from the get-go will save you some hassle later.
Linux:
Steps vary by distribution. For Ubuntu and Debian, the recommended approach is to use the NodeSource repository maintained by the Node.js team.
# Add the NodeSource repository and install Node.js LTS (Ubuntu/Debian)
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejsWhile Node.js is available in the default distribution repositories, the version there is often outdated. Using NodeSource gives you a more up-to-date and reliable installation.
Using a Version Manager (Recommended)
In real-world development, you'll often need to switch between different versions of Node.js depending on the project. That's where version managers come in.
For Mac and Linux, nvm is a great choice. For Windows, consider nvm-windows or fnm. Here's how to install Node.js using nvm:
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
# Restart your terminal, then install Node.js
nvm install --lts
nvm use --ltsLooking back, I started out with just the official installer. But once I started juggling multiple projects, version conflicts became a real headache — which pushed me to switch to nvm. Starting with a version manager from day one could save you that trouble.
With nvm installed, switching versions is a single command:
# Install a specific version
nvm install 20
# Switch to a version
nvm use 20
# List installed versions
nvm ls
# Set the default version
nvm alias default 20You can also place a .nvmrc file in your project's root directory so everyone on the team uses the same version automatically.
# Create a .nvmrc file recording the current version
node -v > .nvmrc
# Use the version specified in .nvmrc
nvm useIn team projects, you'll occasionally run into "it works on my machine but not on yours" problems. A .nvmrc file is a quiet but reliable safeguard against that kind of issue.
A Note for Windows Users: Consider fnm
fnm (Fast Node Manager) is another solid option for Windows. It's built in Rust, so it's very fast, and it supports Windows, Mac, and Linux. Here's how to get started in PowerShell:
# Install fnm using winget
winget install Schniz.fnm
# Add fnm initialization to your PowerShell profile
fnm env --use-on-cd | Out-String | Invoke-Expression
# Install Node.js
fnm install --lts
fnm use --ltsfnm also supports .nvmrc files, so it plays well with teammates who use nvm.
Verifying the Installation and Common Troubleshooting
Once installation is complete, run the following in your terminal (or Command Prompt):
node -v
npm -vIf version numbers appear, you're all set. If you see "command not found," there's likely a PATH configuration issue. Try restarting your terminal, or check that Node.js is correctly added to your PATH environment variable.
This is a surprisingly common stumbling block — especially on Windows, where it's easy to forget to open a fresh terminal window after installing. It's a small thing, but easy to overlook when you're just getting started.
Common Issues and How to Fix Them
Here are some of the most frequent problems you might run into right after installing Node.js. I've personally encountered a few of these, so hopefully this saves you some time.
"node: command not found"
This is the most common issue. The cause is almost always either a stale terminal session or an incorrectly configured PATH.
- Close and reopen your terminal first
- If you're using nvm, check that the nvm initialization script has been added to
~/.bashrcor~/.zshrc - On Windows, verify that Node.js's install directory is included in your system PATH environment variable
npm permission errors (Mac/Linux)
When running npm install -g to install a package globally, you might hit an EACCES error. It's tempting to just prepend sudo, but that's a bad idea — it can scramble file ownership and cause more problems down the line.
If you installed Node.js via nvm, global installs won't cause permission errors. This is one of the reasons a version manager is the recommended approach.
An older version of Node.js is being used instead
If you previously installed Node.js with the official installer, it may still be on your system and taking precedence over the version you installed with nvm. Use which node (Mac/Linux) or where node (Windows) to see which Node.js binary is actually being called. If an older version is showing up, uninstall the official installer version and let nvm manage Node.js going forward.
Installation errors behind a corporate proxy
If you're on a corporate network, you may need to configure npm to use a proxy:
npm config set proxy http://proxy.example.com:8080
npm config set https-proxy http://proxy.example.com:8080I once spent half a day puzzling over npm errors while helping a client on-site, only to discover it was a proxy issue all along. If you're working on a corporate network, this is worth checking early.
Practice: Build Your First Node.js App
With your environment ready, let's build a simple application. Start by creating a project folder and initializing it:
mkdir my-first-app && cd my-first-app
npm init -yRunning npm init -y generates a package.json file — the configuration file for your project, storing information like the project name, version, and dependencies. Think of it as the identity card of your Node.js project.
Next, create a file called app.js and write the following:
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('Hello, welcome to the world of Node.js!');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});Run it with node app.js, then open http://localhost:3000 in your browser. Seeing a web server come to life in just a few lines of code is genuinely exciting the first time.
Understanding the Code
Let's walk through what each part of that code is doing:
require('http')— loads Node.js's built-in HTTP module; no external packages neededhttp.createServer()— creates an HTTP server; the callback function runs every time a request comes inreq— contains the incoming request data, including the URL and HTTP methodres— the object used to build and send the responseres.writeHead(200, ...)— sets the HTTP status code (200 = success) and response headersres.end(...)— sends the response body and closes the connectionserver.listen(3000)— starts listening for requests on port 3000
It might look a little unfamiliar at first, but the structure is simple: "when a request comes in, send something back." Once this pattern clicks, everything else becomes much easier to follow.
Stopping the Server
To stop the running server, press Ctrl + C in your terminal. This trips up a lot of people when they first run Node.js, so it's worth knowing. If you close the terminal without stopping the server, the process may continue running in the background. In that case, use lsof -i :3000 (Mac/Linux) to find the process, then kill it with the kill command.
Going Further: Adding Express
In real-world development, frameworks are the norm. Let's add Express, the most popular Node.js framework:
npm install expressconst express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Running with Express!');
});
app.listen(3000, () => {
console.log('Running at http://localhost:3000');
});Express makes routing and middleware management much more manageable. There are other options like Fastify and Hono, and the right choice depends on your project's requirements. But for a first step, Express has the largest community and the most documentation — a solid, low-risk starting point.
Adding Routes in Express
One of Express's strengths is how cleanly you can define different behavior for different URLs. Here's a slightly expanded example:
const express = require('express');
const app = express();
// Middleware to parse JSON request bodies
app.use(express.json());
app.get('/', (req, res) => {
res.send('Home page');
});
app.get('/about', (req, res) => {
res.send('About this app');
});
app.get('/users/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`);
});
app.post('/api/messages', (req, res) => {
const { text } = req.body;
res.json({ received: text, timestamp: new Date().toISOString() });
});
app.listen(3000, () => {
console.log('Running at http://localhost:3000');
});The /users/:id syntax lets you capture part of the URL as a parameter — visiting /users/1 will put 1 into req.params.id. This kind of flexible routing is part of why Express has remained popular for so long.
Registering Scripts in package.json
Instead of typing node app.js every time, you can register scripts in package.json:
{
"scripts": {
"start": "node app.js",
"dev": "node --watch app.js"
}
}Use npm start to run your app, or npm run dev to run it in development mode with automatic restarts when files change. The --watch flag is a built-in feature available since Node.js 18 — no more manual restarts while you're working. Previously, you needed an external package like nodemon for this, so it's a welcome addition to the core runtime.
Key Things to Know for Real Node.js Development
Now that you've got the basics down, here are a few things worth understanding before you dive deeper into development.
Managing npm Packages
Working with npm packages is a daily part of Node.js development. Here are the essential commands:
# Install a package (added to dependencies)
npm install <package-name>
# Install a development package (added to devDependencies)
npm install --save-dev <package-name>
# Install globally
npm install -g <package-name>
# List installed packages (top level only)
npm ls --depth=0
# Update packages
npm update
# Check for security vulnerabilities
npm auditThe difference between dependencies and devDependencies can be confusing at first. Simply put: dependencies are packages needed in production (like Express), while devDependencies are only needed during development (like test runners and linters). Keeping them separate ensures you don't ship unnecessary packages to production.
node_modules and package-lock.json
Running npm install creates a node_modules folder containing all your installed packages. This folder can get very large, so it should be excluded from version control. Add the following to your .gitignore:
node_modules/
On the other hand, package-lock.json should be committed to git. This file records the exact versions of every installed package, ensuring that all team members get identical package versions when they run npm install.
Staying Security-Aware
npm's vast ecosystem is one of Node.js's biggest strengths, but using third-party packages means security is something to keep in mind. Make it a habit to run npm audit regularly to check for known vulnerabilities. Before installing a package you're unfamiliar with, check its download count and maintenance status on the npm website. Widely-used packages tend to receive faster security fixes when vulnerabilities are discovered.
Wrapping Up: Enjoy the World of Node.js
This guide covered everything from installing Node.js to building a simple application. Looking back, once you push through the initial environment setup, your understanding grows quickly as you get your hands dirty with actual code.
To summarize the key steps:
- Understand the basics — Node.js is a JavaScript runtime for the server side; always start with the LTS version
- Install via a version manager — nvm or fnm makes switching between project versions effortless
- Verify your installation — run
node -vandnpm -v; if something's wrong, check your PATH - Build something — start with a simple HTTP server, then step up to Express
- Learn package management — understand what
package.jsonandnode_modulesare for
Node.js is an excellent entry point for frontend developers venturing into backend development, and a great tool for backend engineers who want to prototype quickly. Use the steps in this guide as your starting point, and enjoy expanding what you can build.
If you run into issues with your setup or development, feel free to reach out — our team of technical professionals may be able to help. Contact aduce here.
