Setting Up Your First Node.js Application
Leaving the browser sandbox can feel intimidating. Here is how to install Node.js, run raw JavaScript from your terminal, and build an HTTP server from scratch.
If you’ve spent your JavaScript career strictly in the browser, opening the terminal to run server-side code feels like stepping out of a sandbox and into a machine shop.
In the browser, a lot of decisions are made for you. The HTML file loads the script, the DOM is just there, and the application stops when the user closes the tab. On the server, you have to build the machine yourself. You decide when it starts, what port it listens to, and how it responds to the outside world.
Today, we are going to set up that machine. We won’t use any frameworks like Express or NestJS. Frameworks are incredibly useful, but they hide the mechanics of how Node.js actually communicates with the operating system. Before we abstract the details away, we need to understand what the metal looks like.
Let’s build your first Node.js application, step by step.
Step 1: Acquiring the Engine
To run JavaScript outside the browser, you need to install the Node.js runtime on your computer.
Regardless of whether you are on macOS, Windows, or Linux, the easiest starting point is to go to the official website (nodejs.org) and download the installer.
You will usually see two versions: Current (the latest features) and LTS (Long Term Support). Always grab the LTS version. It is stable, heavily tested, and the standard for production environments.
Once the installer finishes, open your terminal (or Command Prompt / PowerShell on Windows). We need to verify that your operating system now recognizes Node as a valid command.
node -v
If it prints a version number (like v20.11.0), you are ready to go.
Step 2: The Sandbox in the Terminal (REPL)
Before we write any files, let’s talk directly to the Node engine. In your terminal, just type node and hit Enter.
node
Welcome to Node.js v20.11.0.
Type ".help" for more information.
>
You are now inside the REPL. This stands for Read, Eval, Print, Loop.
It is the exact equivalent of opening the Developer Tools console in your browser. Node reads what you type, evaluates the JavaScript, prints the result, and loops back to wait for your next command.
Try it out:
> const greeting = "Hello from the terminal!";
undefined
> greeting.toUpperCase();
'HELLO FROM THE TERMINAL!'
> Math.random() * 100;
42.8719320
The REPL is fantastic for quick tests, debugging logic, or checking how a specific JavaScript method works without needing to spin up a whole project.
But it’s entirely temporary. When you leave, the memory is wiped. To exit the REPL, type .exit and hit Enter, or press Ctrl + C twice.
Step 3: Writing Your First Node Script
Real applications live in files. Create a new directory for your project, open it in your code editor, and create a file named app.js.
Let's write a simple script that grabs some basic information about the operating system running the code. Node gives us a built-in module called os for this exact purpose.
// app.js
// Import the built-in operating system module
const os = require('os');
console.log("System Information Check:");
console.log(`Platform: ${os.platform()}`);
console.log(`CPU Architecture: ${os.arch()}`);
console.log(`Total Memory: ${os.totalmem() / 1024 / 1024 / 1024} GB`);
To execute this file, go back to your terminal, ensure you are in the same folder as app.js, and run the node command followed by the filename:
node app.js
You should see your system's specs printed out.
Notice what happened: Node read the file top-to-bottom, executed the synchronous commands, and then immediately exited back to the terminal prompt. The process died naturally because there was no more code to run.
But a web server isn't supposed to die. It’s supposed to run forever, waiting for users.
Step 4: Building a Raw HTTP Server
Let’s build an actual web server. Create a new file called server.js.
To do this, we need to use another built-in Node module: http. This module gives Node the ability to open a network port on your machine and listen for incoming HTTP traffic.
Here is the complete, raw code for a functioning web server:
// server.js
const http = require('http');
// 1. Define the port and the host
const PORT = 3000;
const HOST = '127.0.0.1'; // This means "localhost" (your own machine)
// 2. Create the server
const server = http.createServer((req, res) => {
// This callback runs EVERY time a browser requests this server
// Log the request method and URL to our terminal
console.log(`Incoming Request: \({req.method} \){req.url}`);
// Set the HTTP response status code to 200 (OK)
res.statusCode = 200;
// Tell the browser what type of data we are sending back
res.setHeader('Content-Type', 'text/plain');
// Send the data and end the response
res.end('Hello from the raw Node.js backend!\n');
});
// 3. Tell the server to start listening
server.listen(PORT, HOST, () => {
console.log(`Server is up and running at http://\({HOST}:\){PORT}`);
console.log('Press Ctrl+C to stop it.');
});
Breaking Down the Mechanics
There are three critical concepts happening in this code:
The Callback Engine: The function we pass into
http.createServer()doesn't execute immediately. It is an event listener. It just sits there, waiting. When someone navigates to your server, Node triggers this callback, passing in two objects:req(the incoming request data) andres(the outgoing response toolkit).The Headers (
res.setHeader): Browsers are dumb; they need to be told exactly what they are looking at. By setting theContent-Typetotext/plain, we are explicitly telling the browser not to try to render HTML, just display text.Closing the Loop (
res.end): If you forget to callres.end(), the browser will just spin forever, waiting for the server to finish talking. You must explicitly end the connection.
Step 5: Booting It Up
Go to your terminal and run the server file:
node server.js
Unlike our app.js script, the terminal prompt will not return. The process hangs. Your Node application is now actively monitoring Port 3000 on your network interface.
Open your web browser and navigate to: http://localhost:3000
You will see your "Hello from the raw Node.js backend!" message.
Look back at your terminal. You should see a log of the incoming request:
Server is up and running at http://127.0.0.1:3000
Incoming Request: GET /
Incoming Request: GET /favicon.ico
(Notice that the browser automatically asked for a favicon, which triggered our callback a second time!)
To shut the server down and get your terminal back, press Ctrl + C.
The Takeaway
Congratulations. You just built a backend.
If you look at the server.js code, you might notice that routing different URLs (like /users or /about) would quickly become a messy series of if/else statements inspecting req.url. Handling JSON parsing, file uploads, and security headers manually using the raw http module is tedious and error-prone.
That is exactly why frameworks like Express exist. They wrap this raw http.createServer logic in a much friendlier, cleaner API.
But Express is just a wrapper. Underneath the hood, every single request on a Node.js server flows through the exact req and res objects you just learned how to manipulate. By starting here, you don't just know how to type commands—you actually know how the machine works.

