We already know what Node.js is and why it suits a platform like Escena Viva. Now let's install it. This might look like a formality — download an installer and click next, next, next — but the way you install Node.js shapes the rest of your life as a developer: what happens when one client demands version 22 tomorrow and another version 24, when your team has to reproduce your environment exactly, or when you run into the classic permissions error while installing a global tool.
In this lesson we will install Node.js the right way (with a version manager), verify that everything works, configure the editor and create the initial structure of the escena-viva/ folder, which will be with us until the end of the course.
Contents
- The three ways to install Node.js
- Installing with nvm on Linux and macOS
- Installing on Windows: nvm-windows and fnm
- Verification: what gets installed alongside Node
- Choosing a version for a real project: LTS vs Current
- The project's
.nvmrcfile - Configuring the editor and the terminal
- Creating the Escena Viva project folder
- Permissions: why you must never use
sudo npm install -g
- The Three Ways to Install Node.js
| Method | How it works | Advantages | Drawbacks | Recommended? |
|---|---|---|---|---|
| Official installer (nodejs.org) | You download a .msi, .pkg or binary and install it system-wide |
Very simple; gets you testing in 2 minutes | One version at a time; installs into system directories (a source of permission problems); updating means reinstalling | Only for a quick trial |
System package manager (apt, dnf, brew, winget, choco) |
Node is installed like any other system program | Integrated with system updates | Distributions tend to lag behind on versions; sometimes they package npm separately; switching versions is painful | Acceptable on managed servers, not on your development machine |
| Version manager (nvm, fnm, Volta, nvm-windows) | Installs several Node versions in your home folder and switches between them | Several versions side by side; instant switching; no sudo; per-project version via .nvmrc |
One extra initial setup step | Yes. This is the option we use in this lesson. |
The underlying reason to prefer a version manager is simple: real projects have different life cycles. Escena Viva's legacy API may be on Node 22 while the new organizer dashboard is being built on Node 24. Without a version manager, that forces you to uninstall and reinstall constantly.
A comparison of the most common managers:
| Manager | Platforms | Language | Speed | Note |
|---|---|---|---|---|
| nvm | Linux, macOS, WSL | shell script | Medium | The most widespread; the de facto standard |
| nvm-windows | Windows | Go | Medium | A different project from nvm, with similar but not identical commands |
| fnm | Linux, macOS, Windows | Rust | Very high | Compatible with .nvmrc; an excellent modern alternative |
| Volta | Linux, macOS, Windows | Rust | High | Pins the version in package.json and applies it automatically |
In this course we will use nvm as our reference (and fnm or nvm-windows on Windows), because .nvmrc is a file all of them understand.
- Installing with nvm on Linux and macOS
Step 1: install nvm
# Download and install nvm into your home folder (~/.nvm)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bashThe script adds a few lines to your shell configuration file (~/.bashrc, ~/.zshrc or ~/.profile) that load nvm whenever you open a terminal. Close the terminal and open it again, or reload it:
# Reload the shell configuration without closing the terminal
source ~/.bashrc # if you use bash
source ~/.zshrc # if you use zshCheck that nvm responds:
If it prints nothing, the script has not been loaded. Check that the nvm lines are in the configuration file your terminal actually reads (on macOS with zsh that is
~/.zshrc).
Step 2: install the latest LTS version
nvm downloads the binary, places it in ~/.nvm/versions/node/ and activates it in the current session.
Sample output:
-> v24.5.0 default -> lts/* (-> v24.5.0) node -> stable (-> v24.5.0) lts/* -> lts/krypton (-> v24.5.0)
Step 3: set the default version
Without this step, every new terminal will open with no version active.
Step 4: switch between versions
nvm install 22 # Also install the 22 line (LTS in maintenance)
nvm use 22 # Activate it in this terminal
node -v # v22.x.y
nvm use --lts # Go back to the active LTS
node -v # v24.x.ySummary of nvm commands:
| Command | What it does |
|---|---|
nvm install --lts |
Installs the latest LTS version |
nvm install 24.5.0 |
Installs an exact version |
nvm use 24 |
Activates the most recent installed 24, only in this terminal |
nvm use |
Reads .nvmrc from the current directory and activates that version |
nvm ls |
Lists the installed versions |
nvm ls-remote --lts |
Lists the LTS versions available to download |
nvm alias default 'lts/*' |
Sets the default version for new terminals |
nvm uninstall 20 |
Removes a version you no longer need |
nvm current |
Shows the active version |
- Installing on Windows: nvm-windows and fnm
On Windows, the Linux nvm does not work (it is a shell script). You have two good options.
Option A: nvm-windows
Download nvm-setup.exe from the coreybutler/nvm-windows project and run it. Then, in PowerShell as administrator the first time (nvm-windows creates a symbolic link in C:\Program Files\nodejs):
Differences from Linux nvm that are worth knowing:
- It does not support
nvm alias default; the active version is global, not per terminal. nvm usedoes not read.nvmrcautomatically.- It requires administrator permissions to switch.
Option B: fnm (recommended if you are starting from scratch)
fnm works the same on Windows, Linux and macOS, it is very fast, and it does read .nvmrc.
# With winget (included in modern Windows)
winget install Schniz.fnm
# Install the latest LTS and activate it
fnm install --lts
fnm use --lts
fnm default lts-latestTo have fnm switch versions automatically when you enter a folder containing .nvmrc, add this to your PowerShell profile (notepad $PROFILE):
Option C: WSL
If you develop for Linux servers, the most faithful experience is to use WSL 2 (Windows Subsystem for Linux) and install nvm inside it following section 2. It avoids a lot of trouble with paths, permissions and line endings.
Warning: do not mix installations. If you already had Node installed through the official installer or through Chocolatey, uninstall it first before using a version manager. Two installations competing in the
PATHproduce baffling errors ("I have 24 butnode -vsays 18").
- Verification: What Gets Installed Alongside Node
Open a new terminal and run:
If all three answer, the installation is correct. Here is what you got:
| Tool | What it is | Example usage |
|---|---|---|
| node | The interpreter: runs .js files and opens the REPL |
node src/catalog.js |
| npm | Package manager: installs dependencies and runs scripts | npm install express |
| npx | Runs a package without installing it permanently | npx cowsay hello |
| corepack | A manager of managers: enables yarn or pnpm at the version the project asks for |
corepack enable pnpm |
About corepack: it ships with Node but comes disabled. Its purpose is that, if a project declares it uses [email protected], you do not have to install it by hand. You enable it like this:
In this course we will use npm, which is what Node brings by default. The details of npm and package.json are the subject of Module 5; here we only check that it exists.
One more useful check: running code straight from the terminal.
- Choosing a Version for a Real Project: LTS vs Current
Let's recall the rule we saw in the previous lesson and turn it into a concrete decision:
| Situation | Recommended version | Reason |
|---|---|---|
| New project headed for production | Latest Active LTS | Stability, library support and hosting provider support |
| Legacy project in production | The LTS it already uses, with a migration plan | Never mix a version change with a functional change |
| Trying out a new language feature | Current, in a separate folder | Never in the main project |
| A course or self-study | Latest Active LTS | It is what you will find at work |
For Escena Viva we choose the 24.x (Active LTS) line. And, very importantly, we write it down in the repository so it does not depend on anyone's memory.
- The Project's
.nvmrc File
.nvmrc File.nvmrc is a plain text file at the root of the project containing a single line: the Node version the project needs. nvm, fnm, Volta and most continuous integration systems understand it.
Resulting content:
It is also valid — and more flexible — to write it by hand with just the major line, so you get patch updates without touching the file:
or simply:
From now on, anyone cloning the Escena Viva repository only has to run:
A highly recommended trick: configure your shell to run
nvm useautomatically when you enter a folder containing.nvmrc. Withfnmthe--use-on-cdline we saw earlier is enough; with nvm, the official documentation includes acdfunction for bash and zsh that does the same thing.
- Configuring the Editor and the Terminal
Visual Studio Code
VS Code is the most common editor in the Node ecosystem, and it works with no configuration at all. These extensions make a real difference:
| Extension | What it is for |
|---|---|
| ESLint | Catches errors and bad habits as you type |
| Prettier | Formats the code automatically on save |
| npm Intellisense | Autocompletes module names in require/import statements |
| DotENV | Adds syntax coloring to .env files (we will use them in Module 11) |
| REST Client or Thunder Client | Test your HTTP endpoints without leaving the editor (Modules 4 and 6) |
| Error Lens | Shows the error on the line itself, not just in the panel |
| MongoDB for VS Code | Useful from Module 7 onwards |
Recommended settings for the project. Create escena-viva/.vscode/settings.json:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.eol": "\n",
"files.trimTrailingWhitespace": true,
"javascript.preferences.quoteStyle": "single",
"terminal.integrated.defaultProfile.windows": "PowerShell"
}"files.eol": "\n" deserves an explanation: it forces Unix-style line endings. If you work on Windows and deploy on Linux (the usual case), this avoids absurd differences in version control and broken scripts.
Running code from the editor
You have three ways to run a script from VS Code:
- Integrated terminal (
Ctrl+`): typenode src/catalog.js. This is the approach we will use throughout the course. - The "Run" button: with a
.jsfile open,F5launches Node's built-in debugger. launch.json: a reusable configuration. We will look at it in detail in Debugging Node.js Applications.
The terminal
Practical recommendations:
- Linux/macOS: bash or zsh, either is fine. Add automatic version switching with
.nvmrc. - Windows: use Windows Terminal with PowerShell 7, or WSL directly. Avoid
cmd.exe. - Learn two shortcuts you will use every day:
Ctrl+Cto stop a running process (a server, for instance) and the up arrow to repeat the previous command.
- Creating the Escena Viva Project Folder
Let's create the project skeleton. Choose a working folder (~/projects, for example) and run:
# Create the initial Escena Viva structure
mkdir -p escena-viva/src
mkdir -p escena-viva/data
mkdir -p escena-viva/reports
cd escena-vivaOn Windows with PowerShell:
New-Item -ItemType Directory -Path escena-viva\src, escena-viva\data, escena-viva\reports -Force
Set-Location escena-vivaWe pin the project's Node version and start version control:
# The project's Node version
node -v > .nvmrc
# git repository (optional but highly recommended)
git initWe also create a minimal .gitignore. Even though we will not install dependencies yet, better safe than sorry:
Resulting structure:
escena-viva/ ├── .gitignore # What does not get pushed to the repository ├── .nvmrc # The project's Node version ├── data/ # Data files (events.json, sales.csv) ├── reports/ # Output generated by the program └── src/ # JavaScript source code
Check that everything is in place:
About
package.json: when you runnpm init -yyou will get apackage.jsonfile describing the project and its dependencies. We do not need it yet: the first programs in the course run with nothing but what Node ships with. We will study it in depth in Module 5.
- Permissions: Why You Must Never Use
sudo npm install -g
sudo npm install -gThis is the most common configuration mistake among beginners, and it deserves a section of its own.
The symptom
You install Node with the official installer or with apt. Node ends up in /usr/local or /usr, which belongs to root. You try to install a global tool:
npm error code EACCES npm error syscall mkdir npm error path /usr/lib/node_modules/nodemon npm error errno -13 npm error Error: EACCES: permission denied
The instinctive reaction is to prefix it with sudo. Don't.
Why it is a bad idea
| Problem | Consequence |
|---|---|
| You run third-party scripts as root | A malicious or compromised package gets total control of your machine; many packages run postinstall scripts |
| Root-owned files end up in your cache | Later EACCES errors even during normal installs, and a corrupted ~/.npm cache |
| You mix system and user scopes | Updating or uninstalling becomes unpredictable |
The correct solution
Use a version manager. With nvm or fnm, Node and its global packages live in your home folder (~/.nvm/versions/node/v24.5.0/lib/node_modules), where you already have permissions. The EACCES error simply stops existing:
If for some reason you must keep a system-wide installation, the official alternative is to change the global prefix to your home folder:
# Create your own folder for global packages
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
# Add it to the PATH (in ~/.bashrc or ~/.zshrc)
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrcIf you have already made the mess and have root-owned files in your cache, this is the repair:
Golden rule: on your development machine,
npmshould never needsudo. If it does, the problem is in how you installed Node, not in npm.
Common Mistakes and Tips
Mistake 1: command not found: nvm after installing it.
The nvm script is loaded from the shell's configuration file. If you use zsh but the installer wrote to ~/.bashrc, it will not be loaded. Open the right file and check that it contains the export NVM_DIR=... lines and the source of nvm.sh. Then open a new terminal.
Mistake 2: node -v reports a different version from the one you just activated.
There are almost always two installations competing. Diagnose it with:
If /usr/bin/node appears before the ~/.nvm path, uninstall the system version.
Mistake 3: new terminals have no Node at all.
nvm alias default 'lts/*' is missing.
Mistake 4: nvm use says it cannot find .nvmrc.
You are in a directory that is not the project root. nvm use looks for .nvmrc in the current directory and its parents, not in sibling subfolders.
Mistake 5: installing Node from the system package manager on Ubuntu and ending up with an ancient version.
The repositories of stable distributions usually lag a long way behind. Always check with node -v which version actually landed.
Tip 1: pin the version on the server too. .nvmrc is not just for local use; CI systems and many PaaS platforms read it (Module 11).
Tip 2: document the start-up. Even though we have no README yet, write down somewhere the three commands needed to work on the project: nvm use, npm install, npm start. Your future self will thank you.
Tip 3: do not hoard versions. Run nvm ls from time to time and uninstall the ones no project uses any more; each takes up tens of megabytes.
Exercises
Exercise 1: a verified installation
- Install Node.js with nvm (or fnm/nvm-windows if you are on Windows).
- Install two versions: the latest LTS and the 22 line.
- Set the LTS as the default version.
- Write the commands you would use to check, from scratch in a new terminal, that everything is fine: the Node version, the npm version, the npx version, and the list of installed versions.
Exercise 2: the Escena Viva skeleton
Create the escena-viva/ folder with:
- The subfolders
src/,data/andreports/. - An
.nvmrcfile with the LTS version you installed. - A
.gitignoreexcludingnode_modules/,.envand.logfiles.
Then write the sequence of commands a newly arrived colleague would run to get set up on the project with the right Node version, and check that nvm use (or fnm use) responds by reading the .nvmrc.
Exercise 3: diagnosing a broken environment
A colleague on the Escena Viva team writes to you: "I installed nvm and ran nvm install --lts, but when I open a new terminal node -v tells me v18.19.0. On top of that, if I try npm install -g nodemon I get EACCES and it only works with sudo."
- What is the most likely diagnosis?
- Which command would you ask them to run to confirm it?
- Write out the steps of the fix.
Solutions
Solution 1
# 1 and 2. Installing two versions
nvm install --lts # Installs the latest LTS (24.x)
nvm install 22 # Installs the latest 22.x
# 3. Default version
nvm alias default 'lts/*'
# 4. Verification in a NEW terminal
node -v # v24.x.y -> must be the LTS, not 22
npm -v # 11.x.y
npx -v # 11.x.y
nvm ls # Must list v22.x.y and v24.x.y, with default -> lts/*An extra check that switching works:
Solution 2
# Create the structure
mkdir -p escena-viva/src escena-viva/data escena-viva/reports
cd escena-viva
# Pin the project version
node -v > .nvmrc
cat .nvmrc # v24.5.0
# git ignores
printf 'node_modules/\n.env\n*.log\n' > .gitignore
git initSequence for the newly arrived colleague:
git clone <repository-url> escena-viva
cd escena-viva
nvm install # Installs the .nvmrc version if they do not have it
nvm use # Activates it in this terminal
node -v # Must match the contents of .nvmrcNote: nvm use fails if the .nvmrc version is not installed; hence the nvm install beforehand (with no arguments, it also reads .nvmrc).
Solution 3
-
Diagnosis: there is a previous Node installation (from the official installer or from the system package manager) in a system directory, and it comes before nvm in the
PATH. That installation belongs toroot, which explains both the unexpected version (v18) and theEACCESerror when installing global packages. -
Confirmation command:
which -a node
# Expected output, with the system one first:
# /usr/bin/node
# /home/user/.nvm/versions/node/v24.5.0/bin/nodenpm config get prefix also helps: if it returns /usr or /usr/local, that confirms the diagnosis.
- The fix:
# a) Uninstall the system version (example on Debian/Ubuntu)
sudo apt remove --purge nodejs npm
sudo apt autoremove
# b) Repair the npm cache if sudo was ever used
sudo chown -R $(whoami) ~/.npm
# c) Open a NEW terminal and verify
which -a node # Only the path under ~/.nvm should appear
node -v # The LTS installed with nvm
npm install -g nodemon # Now it works WITHOUT sudoIf company policy prevents them from uninstalling the system version, the alternative is to make sure the nvm line in ~/.bashrc runs at the end of the file, so that its path comes first in the PATH.
Conclusion
You now have a professional development environment. We have seen that there are three ways to install Node.js and why a version manager (nvm, fnm or nvm-windows) is the only one that copes well with the reality of working on several projects: it lets you install several versions, switch between them instantly and — no small detail — it eliminates at the root the permission problems that lead to the bad practice of sudo npm install -g.
You have installed the latest Active LTS, checked that node, npm, npx and corepack respond, configured the editor with the extensions you will use throughout the course, and created the escena-viva/ folder with its src/, data/ and reports/ directories, a .gitignore and an .nvmrc that documents the project version for the whole team.
The folder exists but it is empty. In the next lesson, Your First Node.js Program, we will write src/catalog.js: Escena Viva's first real program, which defines the event catalog for the Teatro Almendra, the Sala Bóveda and the Auditorio Ribera, prints it nicely formatted to the console, and learns to receive arguments from the command line.
Node.js Course: From Beginner to Advanced
Module 1: Introduction to Node.js
- What Is Node.js?
- Installing and Setting Up the Environment
- Your First Node.js Program
- The Node.js REPL
- Modern JavaScript for Node.js
- The Course Project: the Escena Viva Platform
Module 2: Core Concepts
- Node.js Architecture
- The Event Loop
- Callbacks and Asynchronous Programming
- Promises and async/await
- Events and EventEmitter
- CommonJS Modules and require()
- ES Modules and Interoperability
Module 3: File System and I/O
- Reading and Writing Files
- The fs Module in Depth
- Cross-Platform Paths with the path Module
- Working with Streams
- Transform Streams and pipeline
- Buffers and Binary Data
Module 4: HTTP and Web Servers
- Creating a Simple HTTP Server
- Handling Requests and Responses
- Manual Routing
- Serving Static Files
- Receiving Data: Request Bodies and JSON
- Consuming External APIs from Node.js
Module 5: NPM and Package Management
- Introduction to NPM and package.json
- Installing and Using Packages
- Semantic Versioning and package-lock
- npm Scripts and Project Automation
- Creating and Publishing Packages
- Dependency Security and Maintenance
Module 6: The Express.js Framework
- Introduction to Express.js
- Setting Up an Express Application
- Routing in Express
- Middleware
- Essential Third-Party Middleware
- Input Data Validation
- Error Handling
Module 7: Databases and ORMs
- Introduction to Databases
- Using MongoDB with Mongoose
- CRUD Operations
- Relationships, Population and Advanced Queries
- Using SQL Databases with Sequelize
- Migrations, Transactions and Seed Data
Module 8: Authentication and Authorization
- Introduction to Authentication
- User Registration and Password Hashing
- Sessions and Cookies with Passport.js
- Authentication with JWT
- Role-Based Access Control
- API Security Best Practices
Module 9: Testing and Debugging
- Introduction to Testing
- Unit Testing with Mocha and Chai
- Test Doubles with Sinon
- Integration Testing
- Coverage and Test Automation
- Debugging Node.js Applications
Module 10: Advanced Topics
- The Cluster Module
- Worker Threads
- Caching and Job Queues with Redis
- Performance Optimization
- Building RESTful APIs
- GraphQL with Node.js
Module 11: Deployment and DevOps
- Configuration and Environment Variables
- Logging and Monitoring in Production
- Using PM2 for Process Management
- Packaging with Docker
- Deploying to Heroku and Other PaaS
- Continuous Integration and Deployment
