Skip to main content

Command Palette

Search for a command to run...

Setting Up Your First Node.js Application: A Step-by-Step Guide from Install to HTTP Server

Updated
6 min read
Setting Up Your First Node.js Application: A Step-by-Step Guide from Install to HTTP Server

Setting Up Your First Node.js Application: A Step-by-Step Guide from Install to HTTP Server

Audience: This post is for developers who are new to Node.js but comfortable with basic JavaScript. No prior server-side experience required.

TL;DR: Install Node.js, verify it works in your terminal, explore the REPL, write a .js file, run it with the node command, and build a minimal HTTP server using only Node's built-in http module — no Express, no dependencies.


Problem

Most Node.js tutorials start with npm install express before you understand what Node even is. That skips the foundation entirely. Before you use any framework, you need to know: How does Node run JavaScript? What happens when you execute a file? How does it handle an HTTP request at the lowest level?

This post fills that gap.


Solution

We'll go step-by-step through the full setup process — from installing the runtime to serving HTTP responses — using only Node's standard library.


Step 1: Install Node.js

Go to https://nodejs.org and download the LTS (Long Term Support) version. As of 2025, that's Node.js 20.x or 22.x.

Why LTS? LTS releases are supported for 30 months with security and bug fixes. The Current release gets new features faster but isn't recommended for production or learning stability.

OS-neutral options:

  • Windows / macOS: Use the official installer from nodejs.org
  • Linux (Ubuntu/Debian):
# Using NodeSource repository for the latest LTS
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
  • All platforms (recommended for managing versions): Use nvm
# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Restart your terminal, then install Node LTS
nvm install --lts
nvm use --lts

Using nvm is the best long-term choice because it lets you switch Node versions per project.


Step 2: Verify the Installation

Open your terminal and run:

node --version

Expected output:

v20.11.1

Also verify npm (Node Package Manager) was installed alongside Node:

npm --version

Expected output:

10.2.4

If either command returns command not found, the installation didn't complete correctly. On Windows, restart your terminal or check that Node's install directory is in your PATH environment variable.


Step 3: Understand and Use the Node REPL

What is the REPL?

REPL stands for Read-Eval-Print Loop. It's an interactive runtime session where Node reads your input, evaluates it as JavaScript, prints the result, and waits for the next input. Think of it as a JavaScript console that runs in your terminal instead of a browser.

It's useful for:

  • Testing small expressions quickly
  • Exploring built-in modules
  • Debugging logic in isolation

Start the REPL:

node

Your prompt changes to >.

Try these inside the REPL:

> 2 + 2
4

> const name = 'Node.js'
> `Hello from ${name}`
'Hello from Node.js'

> typeof process
'object'

> process.version
'v20.11.1'

> process.platform
'linux'   // or 'darwin' on macOS, 'win32' on Windows

The process object is global in Node — it gives you runtime information about the current Node process. You'll use it constantly.

To exit the REPL, press Ctrl + C twice or type .exit.


Step 4: Create and Run Your First JavaScript File

Create a directory for your project:

mkdir node-fundamentals
cd node-fundamentals

Create a file called greet.js:

// greet.js
const userName = 'Alice';
const currentHour = new Date().getHours();

let greeting;

if (currentHour < 12) {
  greeting = 'Good morning';
} else if (currentHour < 18) {
  greeting = 'Good afternoon';
} else {
  greeting = 'Good evening';
}

console.log(`${greeting}, ${userName}!`);
console.log(`Node.js version: ${process.version}`);
console.log(`Platform: ${process.platform}`);

Run it:

node greet.js

Expected output (if run in the morning):

Good morning, Alice!
Node.js version: v20.11.1
Platform: linux

What just happened — the execution flow:

greet.js (source file)
     |
     v
Node.js Runtime
     |
     |-- V8 Engine parses and compiles the JS
     |-- libuv handles I/O (not used here, but available)
     |-- process object injected into scope
     |
     v
stdout (your terminal)
Good morning, Alice!

Node reads the file as a string, passes it to the V8 JavaScript engine (the same engine Chrome uses), executes it synchronously top-to-bottom, writes to stdout via console.log, and exits. No browser, no DOM, no window object — just JavaScript running directly on your machine.


Step 5: Write a Hello World HTTP Server

Node ships with a built-in http module. No installation required. This is the foundation that frameworks like Express are built on.

Create a file called server.js:

// server.js
const http = require('http');

const HOST = '127.0.0.1';
const PORT = 3000;

const server = http.createServer((request, response) => {
  const { method, url } = request;

  console.log(`[${new Date().toISOString()}] ${method} ${url}`);

  // Set response headers
  response.setHeader('Content-Type', 'text/plain');

  // Route handling without a framework
  if (url === '/' && method === 'GET') {
    response.statusCode = 200;
    response.end('Hello, World!\n');
  } else if (url === '/health' && method === 'GET') {
    response.statusCode = 200;
    response.end('OK\n');
  } else {
    response.statusCode = 404;
    response.end('Not Found\n');
  }
});

server.listen(PORT, HOST, () => {
  console.log(`Server running at http://${HOST}:${PORT}/`);
  console.log('Press Ctrl+C to stop');
});

Run the server:

node server.js

Terminal output:

Server running at http://127.0.0.1:3000/
Press Ctrl+C to stop

Now test it. Open a second terminal and use curl:

curl http://127.0.0.1:3000/

Output:

Hello, World!
curl http://127.0.0.1:3000/health

Output:

OK
curl http://127.0.0.1:3000/missing

Output:

Not Found

Back in the first terminal, you'll see the request log:

[2025-01-15T08:32:11.042Z] GET /
[2025-01-15T08:32:14.318Z] GET /health
[2025-01-15T08:32:17.901Z] GET /missing

What's happening under the hood:

http.createServer() returns a Server object. The callback you pass is an event listener — Node registers it to fire every time an HTTP request arrives. Node's event loop keeps the process alive and calls this callback each time a new TCP connection completes an HTTP request. Without a framework, you manually check request.url and request.method to route requests.

response.end() writes the body and signals that the response is complete. Calling it is mandatory — if you don't, the client will hang waiting for more data.


Results

At this point you have:

  • Node.js installed and verified
  • A working understanding of the REPL for quick testing
  • A runnable .js script demonstrating Node's execution model
  • A functioning HTTP server handling three routes with proper status codes and logging

All of this with zero external dependencies.


Trade-offs

What we didThe limitation
Used built-in http moduleURL parsing, body parsing, and routing become verbose at scale. Use Express or Fastify for real applications.
Manual url string matchingDoesn't handle query parameters, dynamic segments, or method mismatch gracefully without extra code
Single fileFine for learning; production apps need module separation, error handling middleware, and process management (e.g., PM2)
require() syntaxModern Node supports ES Modules (import/export). require is CommonJS — still widely used, but be aware both exist

This setup is intentionally minimal. Its value is teaching you what's underneath — not what to ship to production.


Conclusion

You now have a concrete mental model of how Node.js works: it's a JavaScript runtime built on V8 and libuv, capable of running scripts and handling I/O (like HTTP) without a browser. The REPL is your scratchpad. node filename.js is how you execute code. The http module is the raw foundation of every Node web server.

The logical next step is to look at how Express wraps this http module — once you've seen the raw version, the abstractions will make sense instead of feeling like magic.


Further Reading