How to Build a Simple Node.js Server from Scratch – A Beginner’s Guide

How to Build a Simple Node.js Server from Scratch – A Beginner’s Guide

August 1, 2025 • By Shakib Khan

In today's development landscape, most Node.js developers rely on frameworks like Express.js to create servers efficiently. However, in this article, we will take a step back from abstraction and explore the core of Node.js by building a server from scratch — without using any external frameworks. This deep dive into a raw Node.js server will help you understand how things work under the hood.

If you're reading this article, it likely means you're already familiar with Node.js and have it installed on your system. So, without covering the basics, we'll jump straight into the core coding aspects of building a raw Node.js server.

How to Set Up the Project

For now, all you need to do is create a folder and then create a file named server.js inside it. Once that's done, you're ready to start coding.

mkdir raw-node-server
cd raw-node-server
touch server.js  // If you are using linux or git bash
// You can also create this folder & file using desktop ui 😂

First, we need to import something from the 'http' package. It's built-in package, so we don't need to install it

const { createServer } = require("http");

Next, we need to create a server using the createServer function.

const server = createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/html" }); // 200 is the status code & Content-Type means what type of content we are sending from the server
  res.end("<h1>Hello World</h1>");
});

We've set up the server, and most of the work is done. But will it run? No, because it's not listening on any port yet. So, we need to make it listen to a port to start working.

server.listen(3000, () => {
  console.log("Server is running on port 3000");
});

After that, run the code, and your server will start working.

node server.js

If you've done all these steps correctly, it means you've created a basic Node.js server without using any extra frameworks.

Now, let's add some routes.

const server = createServer((req, res) => {
  if (req.url === "/") {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end("<h1>We are on the home page</h1>");
  }
  if (req.url === "/about") {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end("<h1>We are on the about page</h1>");
  } else {
    res.writeHead(404, { "Content-Type": "text/html" });
    res.end("<h1>404 Not Found</h1>");
  }
});

We can add routes using if-else statements. So now, you're someone who knows how to set up routes in a raw Node.js server.

Now, let's learn how to send HTML content

To do that, we need to import another built-in module called fs, which stands for File System.

const fs = require("fs");
const { createServer } = require("http");
const fs = require("fs");

const server = createServer((req, res) => {
  if (req.url === "/") {
  // New Added
    const homePage = fs.readFileSync("index.html", "utf-8");
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end(homePage);
  // Ending
  }
});

server.listen(3000, () => {
  console.log("Server is running on port 3000");
});
<!--  index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cool Website</title>
</head>
<body>
    <h1>Cool Contents</h1>
</body>
</html>
node server.js

We are using the fs module to read an HTML file.

Let's serve JSON data

const { createServer } = require("http");

const server = createServer((req, res) => {
  if (req.url === "/") {
    const data = { success: true, message: "We are on the home page" };  // JSON data
    res.writeHead(200, { "Content-Type": "application/json" });  // Status code 200 & Content type json
    res.end(JSON.stringify(data));
  }
});

server.listen(3000, () => {
  console.log("Server is running on port 3000");
});
node server.js

Now, if you open your browser and go to http://localhost:3000, you will see a JSON response.

Let's talk about Content Type & Status Code

Have you noticed that we use different content types when sending different kinds of content?

res.writeHead(200, { "Content-Type": "text/plain" });  // when you are serving plain text
res.writeHead(200, { "Content-Type": "text/html" });  // when you are serving html
res.writeHead(200, { "Content-Type": "text/css" });  // when you are serving css
res.writeHead(200, { "Content-Type": "application/json" }); // when you are serving json data

What is a status code?

There are different types of status codes. For example:

  • 200 means the response was successful.
  • 201 means something was created.
  • 404 means the page was not found.
  • 500 means there was an internal server error.

There are many more. You can learn more about status codes here:

HTTP response status codes

I think this is enough for now. Today, we learned a lot about building a raw Node.js server without using any external packages.

If you have any questions or notice any mistakes, please feel free to leave a comment below. Your feedback is highly appreciated!

See you in the next article!

Programs must be written for people to read, and only incidentally for machines to execute. — Harold Abelson, computer scientist and co-author of Structure and Interpretation of Computer Program