Build Your First Express Server with Beginner JavaScript
Turn a basic Node.js project into a running backend server and understand Express, ports, localhost, routes, requests, responses, JSON and the HTTP request-response cycle.

Build Your First Express Server with Beginner JavaScript
Backend Development Series
This article is Update 3 of our step-by-step Backend Development series.
← Update 2 · Series Overview
We now have a clean Node.js project.
Our structure currently looks like this:
textcommunity-platform-api/
│
├── src/
│ └── server.js
│
├── .gitignore
└── package.jsonBut there is one obvious problem.
Our backend does not actually do anything yet.
There is no running server.
There is no API endpoint.
There is nothing listening for HTTP requests.
Today, we change that.
Our goal is simple:
Turn this empty Node.js project into a real HTTP backend using Express.
By the end of this update, visiting:
texthttp://localhost:3000will return information from our backend.
What Is Express?
Node.js allows JavaScript to run outside the browser.
However, building HTTP servers directly with lower-level Node.js APIs requires us to handle more details ourselves.
Express gives us a simpler way to build:
- Backend servers
- REST APIs
- Routes
- Request handling
- Responses
- Middleware
Think of the relationship like this:
textJavaScript
↓
Node.js
↓
Express
↓
Our Backend APIJavaScript is the language.
Node.js is the runtime.
Express gives us convenient tools for building the web server.
Installing Express
Inside the project terminal, run:
bashpnpm add expressAfter installation, the project will contain new items such as:
textcommunity-platform-api/
│
├── node_modules/
│
├── src/
│ └── server.js
│
├── .gitignore
What Changed?
The two obvious additions are:
textnode_modules/and:
textpnpm-lock.yaml
Understanding node_modules
node_modules contains the installed packages required by the application.
Because we installed:
textExpresspnpm downloaded Express and its required dependencies.
This folder is managed by the package manager.
You generally should not manually edit code inside:
textnode_modules/If the folder is deleted, dependencies can be restored using:
bashpnpm install
Express Appears in package.json
After installation, package.json will contain Express inside the dependencies.
Conceptually:
json{
"dependencies": {
"express": "..."
}
}This means:
Our application now depends on Express.
Creating the Express Application
Open:
textsrc/server.jsStart with:
jsimport express from "express";
const app = express();
const PORT = 3000;There are already several important concepts here.
Let's understand them before adding anything else.
Importing Express
We wrote:
jsimport express from "express";This means:
Bring the Express package into this file so we can use it.
Remember that Express was installed using:
bashpnpm add expressNow our JavaScript file can access it.
What Does express() Do?
This line:
jsconst app = express();creates an Express application.
We store that application inside:
jsappLater, app will be used for things such as:
jsapp.get()
app.post()
app.patch()
app.delete()
app.use()
app.listen()You can think of app as representing our backend application.
Understanding the Port
We also created:
jsconst PORT = 3000;A computer can run many network applications at once.
Ports help identify which application should receive a connection.
You can imagine your computer like a large building.
The computer is the building.
Ports are different doors.
For example:
textComputer
│
├── Port 3000 → Our Backend API
├── Port 5432 → PostgreSQL
├── Port 5173 → Frontend Development Server
└── Other Ports → Other ServicesFor our backend, we are choosing:
text3000So our server will eventually be available at:
texthttp://localhost:3000
What Is localhost?
During development, you will see:
textlocalhostvery often.
localhost means:
This computer.
Therefore:
texthttp://localhost:3000means:
Connect to the HTTP application running on my own computer using port 3000.
At this stage, the backend is not publicly deployed to the internet.
It is running locally on your development machine.
Creating Our First Route
Now add:
jsapp.get("/", (req, res) => {
res.json({
message: "Welcome to our Community Information Platform",
});
});Our file now looks like:
jsimport express from "express";
const app = express();
const PORT = 3000;
app.get("/", (req, res) => {
res.json({
This introduces one of the most important backend concepts:
Routes
What Is a Route?
A route tells the backend:
When a particular type of HTTP request reaches a particular URL, what should happen?
We wrote:
jsapp.get("/")The:
textGETpart is the HTTP method.
The:
text/part is the route path.
Together:
textGET /means:
When someone sends a GET request to the root of this application, run this function.
What Does GET Mean?
GET is an HTTP method commonly used when a client wants to retrieve information.
Examples:
textGET /postscould mean:
Give me the Posts.
And:
textGET /userscould mean:
Give me the Users.
Later:
textGET /posts/5could mean:
Give me Post number 5.
For now, we simply have:
textGET /
Understanding req
Inside the route we have:
js(req, res)req means:
textrequestThe request represents information coming into our backend.
Later, it may contain:
- Request body
- Route parameters
- Query parameters
- Headers
- Cookies
- Authentication data
The flow begins like this:
textCLIENT
│
│ Request
↓
BACKEND
Understanding res
res means:
textresponseWe use it to send information back to the client.
For example:
jsres.json({
message: "Welcome to our Community Information Platform",
});The complete flow becomes:
textCLIENT
│
│ HTTP Request
↓
BACKEND
│
│ HTTP Response
↓
This request-response cycle is one of the foundations of backend development.
Why Return JSON?
We used:
jsres.json(...)instead of directly returning HTML.
Our backend is being built as an API.
Different applications may eventually communicate with it.
For example:
text Website
↑
│
Mobile App ← Backend API → Admin Dashboard
│
↓
Other ClientsJSON gives these clients a structured format for exchanging information.
For example:
json{
"message": "Welcome to our Community Information Platform"
}
JSON Looks Familiar to JavaScript Developers
JSON resembles JavaScript objects.
A JavaScript object may look like:
jsconst response = {
message: "Hello",
};A JSON representation may look like:
json{
"message": "Hello"
}That familiarity makes JSON convenient when building JavaScript-based APIs.
Starting the Server
We have created the application and the route.
But the application still needs to start listening for requests.
Add:
jsapp.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});Our complete server.js becomes:
jsimport express from "express";
const app = express();
const PORT = 3000;
app.get("/", (req, res) => {
res.json({
Understanding app.listen()
This:
jsapp.listen(PORT)tells the Express application:
Start the server and listen for incoming connections on this port.
Without it, we may define routes, but the backend is not actively listening for network requests.
Conceptually:
textRun server.js
↓
Create Express Application
↓
Register Routes
↓
Listen on Port 3000
↓
Then:
textClient Sends Request
↓
Express Receives Request
↓
Find Matching Route
↓
Run Route Function
↓
Creating Development Scripts
Instead of manually typing:
bashnode src/server.jsevery time, we can create scripts inside:
textpackage.jsonFor example:
json{
"scripts": {
"dev": "node --watch src/server.js",
"start": "node src/server.js"
}
}Now we can run:
bashpnpm devduring development.
And:
bashpnpm startfor a normal application start.
What Does --watch Do?
This script:
textnode --watch src/server.jsuses Node.js watch mode.
Without watch mode, development may look like:
textWrite Code
↓
Stop Server
↓
Start Server
↓
Test
↓
With watch mode:
textWrite Code
↓
Save File
↓
Node Detects Change
↓
Server RestartsThat makes development much faster.
Running the Backend
Now run:
bashpnpm devThe terminal should show something similar to:
textServer running on http://localhost:3000Now open your browser and visit:
texthttp://localhost:3000You should receive:
json{
"message": "Welcome to our Community Information Platform"
}Congratulations.
You now have a real backend server running.
What Just Happened?
When you entered:
texthttp://localhost:3000into the browser, the browser acted as a client.
It sent a request.
Conceptually:
textBrowser
│
│ GET /
↓
Express
│
↓
app.get("/")
That simple flow is incredibly important.
Follow the Request Step by Step
Let's slow it down.
Step 1 — Browser Makes a Request
The browser requests:
textGET /from:
textlocalhost:3000
Step 2 — Express Receives It
Our application is listening on:
text3000So Express receives the request.
Step 3 — Express Searches for a Matching Route
Express sees:
jsapp.get("/")The method matches:
textGETThe path matches:
text/So the route function executes.
Step 4 — The Route Sends JSON
Our function runs:
jsres.json({
message: "Welcome to our Community Information Platform",
});Express creates an HTTP response containing JSON.
Step 5 — The Browser Receives the Response
The browser displays:
json{
"message": "Welcome to our Community Information Platform"
}The request-response cycle is complete.
The Mental Model
The important thing to remember is:
textSomeone asks the backend for something
↓
REQUEST
↓
Backend processes it
↓
RESPONSE
↓
This idea will continue appearing throughout the entire project.
Even after we introduce:
- Authentication
- Databases
- Controllers
- Middleware
- Validation
- File uploads
the general request-response model remains.
Our Project Structure Now
The project now looks approximately like:
textcommunity-platform-api/
│
├── node_modules/
│
├── src/
│ └── server.js
│
├── .gitignore
Still very simple.
And that is intentional.
What We Have Learned So Far
At this stage, we understand:
JavaScript
The language we are writing.
Node.js
The environment running our JavaScript backend.
Express
The framework helping us build the HTTP API.
app
Our Express application.
Port
The network location our server listens on.
localhost
Our own development computer.
Route
Defines how a request should be handled.
req
Represents the incoming request.
res
Represents the outgoing response.
JSON
The structured format our API commonly returns.
app.listen()
Starts the server and waits for requests.
Notice How Beginner JavaScript Is Already Becoming a Backend
Consider the concepts we used.
We created a constant:
jsconst PORT = 3000;That is beginner JavaScript.
We created a function:
js(req, res) => {
}That is JavaScript.
We created an object:
js{
message: "Welcome to our Community Information Platform"
}That is beginner JavaScript.
We imported a module:
jsimport express from "express";That is modern JavaScript.
These concepts are now working together to create a real HTTP server.
That is the entire point of this learning journey.
You Do Not Need Thousands of Lines of Code to Build Something Real
Our first backend server is tiny.
But it already has:
textA Runtime
A Web Framework
A Server
A Port
A Route
A Request
A Response
A JSON APIThe application will become more advanced gradually.
The important thing is that we understand what each addition contributes.
A New Problem Is Beginning to Appear
Right now everything lives inside:
textserver.jsThat is fine because we only have one route.
But imagine adding:
textGET /posts
GET /posts/:id
POST /posts
PATCH /posts/:id
DELETE /posts/:id
GET /users
POST /users
Suddenly:
textserver.jscould become very large.
That creates our next architectural problem.
And whenever we encounter a problem, we ask:
What solution exists for this problem?
In this case, the answer will lead us toward:
textroutes/
What's Next?
In Backend Development Update #4, we will introduce proper API routing.
We will learn:
- What an API route is
- Why URLs matter
- Why HTTP methods matter
- How
express.Router()works - Why
/api/posts
Our architecture will evolve from:
textsrc/
└── server.jstoward:
textsrc/
├── routes/
│ └── post.routes.js
│
└── server.jsBut importantly, we now know why that change becomes necessary.
GREE Software Academy
Backend development becomes much easier when you stop trying to memorize the final architecture.
Instead:
textBuild Something Small
↓
Understand It
↓
Encounter a Limitation
↓
Understand the Limitation
↓
Today we turned an empty JavaScript project into a working HTTP server.
Next, we will begin turning that server into a properly organized API.
Start small. Understand why. Then scale.
Continue Learning
You have completed Update 3 — Build Your First Express Server with Beginner JavaScript.
Previous
← Update 2 — Setting Up Your First Modern Node.js Backend Project
Coming Next
Update 4 — Organizing the API With Routes
Next, we will solve the problem of putting too many endpoints inside server.js by introducing:
- API routes
express.Router()- Resource-based routing
/api/posts- The
routes/folder

