Setting Up Your First Modern Node.js Backend Project
Start a backend project from scratch using Node.js and modern JavaScript while understanding why package.json, src, .gitignore, and ES Modules exist.

Setting Up Your First Modern Node.js Backend Project
Backend Development Series
This article is Update 2 of our step-by-step Backend Development series.
← Update 1 · Series Overview · Update 3 →
In the previous Backend Development update, we did something very important before writing code:
We identified a real-world problem first.
Our community needed a central digital platform where important information such as announcements, opportunities, articles, educational information and notices could be published and accessed easily.
Now that we understand the problem, we can finally begin building the backend.
But we are going to start small.
No database yet.
No authentication.
No controllers.
No middleware.
No complicated architecture.
Our first goal is simply:
Create a clean Node.js project and understand what every file is doing.
What Is Node.js?
JavaScript originally became popular as a language that runs inside web browsers.
For example:
textChrome
Firefox
Edge
SafariJavaScript inside the browser can handle things such as:
- Button clicks
- Form interactions
- Page updates
- Animations
- Frontend logic
But backend development needs JavaScript to run outside the browser.
That is where Node.js becomes important.
Node.js allows us to execute JavaScript on a computer or server.
Conceptually:
textJavaScript
↓
Node.js
↓
Server-Side ApplicationWith Node.js, JavaScript can be used to build:
- APIs
- Backend servers
- Command-line tools
- Automation scripts
- Development tools
- Real-time applications
For our project, Node.js will provide the runtime environment for our backend.
Creating the Project Folder
We begin with an empty folder.
For example:
textcommunity-platform-api/The name describes what we are building.
This project will contain the backend API for our Community Information Platform.
If you are using a terminal, you could create the folder with:
bashmkdir community-platform-apiThen enter it:
bashcd community-platform-apiIf you use Visual Studio Code:
bashcode .Now we have a completely empty project.
That is a good thing.
We are going to add only what we understand.
Initializing the Node.js Project
We use pnpm as our package manager.
To initialize the project:
bashpnpm initThis creates:
textpackage.jsonOur structure becomes:
textcommunity-platform-api/
│
└── package.json
What Is package.json?
package.json is one of the most important files in a Node.js project.
You can think of it as the project's:
Identity card and configuration record.
It can describe things such as:
- Project name
- Project version
- Description
- Scripts
- Dependencies
- Development dependencies
A simple example may look like:
json{
"name": "community-platform-api",
"version": "1.0.0",
"description": "Backend API for a community information platform"
}As the project grows, this file will also tell us which packages the application depends on.
For example, later we may see:
json{
"dependencies": {
"express": "..."
}
}This means:
The application depends on Express.
What Is a Package Manager?
A package manager helps us install and manage reusable code created by other developers.
For example, instead of writing our own web framework from scratch, we can install:
textExpressInstead of manually downloading packages, pnpm can manage them.
Conceptually:
textOur Application
↓
package.json
↓
pnpm
↓
Installed PackagesLater we will run commands such as:
bashpnpm add expressand pnpm will:
- Download Express
- Track it as a dependency
- Update the project lock file
- Make the package available to our application
Using Modern JavaScript Modules
We want this project to use modern JavaScript syntax.
For example:
jsimport express from "express";instead of older CommonJS syntax such as:
jsconst express = require("express");To make that clear to Node.js, we add:
json"type": "module"to package.json.
A simple project configuration may look like:
json{
"name": "community-platform-api",
"version": "1.0.0",
"description": "Backend API for a community information platform",
"type": "module",
"scripts": {}
}Now we can consistently use:
jsimportand:
jsexportthroughout the project.
Why Learn import and export?
As an application grows, keeping everything inside one file becomes difficult.
Eventually we will want files to communicate with each other.
For example:
textserver.js
post.routes.js
post.controller.js
database.jsOne file may need functionality from another.
That is where modules become useful.
For example:
jsexport const greet = () => {
console.log("Hello");
};Another file can import it:
jsimport { greet } from "./greet.js";This helps us divide large systems into smaller understandable pieces.
Creating the src Folder
Next we create:
textsrc/Our project becomes:
textcommunity-platform-api/
│
├── src/
│
└── package.jsonsrc usually means:
textsourceThis is where our main application source code will live.
Instead of throwing every JavaScript file into the project root, we keep application code organized under:
textsrc/
Why Not Create Every Folder Now?
You may have seen backend projects that contain:
textsrc/
├── controllers/
├── middleware/
├── models/
├── routes/
├── services/
├── utils/
├── validators/
It may be tempting to create all of those immediately.
But there is a problem.
If you create folders before understanding why they exist, backend architecture becomes something you memorize instead of something you understand.
We are taking a different approach.
Our rule is:
Introduce architecture when we encounter the problem that architecture solves.
For example:
textToo many endpoints inside server.js
↓
Introduce routes/Later:
textToo much logic inside routes
↓
Introduce controllers/Later:
textRepeated authentication logic
↓
Introduce middleware/This way, each folder will make sense.
Creating server.js
Inside src, create:
textserver.jsOur structure becomes:
textcommunity-platform-api/
│
├── src/
│ └── server.js
│
└── package.jsonserver.js will initially become the entry point of our backend application.
The entry point is simply:
The file where our backend begins running.
At this stage, server.js can remain empty.
We will turn it into an actual HTTP server in the next step.
Creating .gitignore
Next, create:
text.gitignoreOur project becomes:
textcommunity-platform-api/
│
├── src/
│ └── server.js
│
├── .gitignore
└── package.jsonThe .gitignore file tells Git:
Do not track certain files or folders.
For now, we can add:
gitignorenode_modules
.env
Why Ignore node_modules?
Once packages are installed, Node.js projects usually contain:
textnode_modules/This folder can become very large.
It may contain thousands of files belonging to packages used by the application.
We do not normally need to commit the entire folder to Git.
Why?
Because another developer can install the dependencies again using:
bashpnpm installThe package information is already tracked through files such as:
textpackage.json
pnpm-lock.yamlSo:
textnode_modules/can be regenerated.
What Is pnpm-lock.yaml?
Once we begin installing packages, pnpm will create:
textpnpm-lock.yamlThis file records precise information about installed dependencies.
For example:
textpackage.jsonmay broadly describe which dependencies the application uses.
The lock file helps keep installations consistent.
This becomes useful when:
- Another developer clones the project
- The application is deployed
- The project is installed on another machine
Why Ignore .env?
Later our application will need configuration such as:
textDatabase URLs
Secret keys
API credentials
Authentication secrets
Email credentialsThese should not be casually placed inside public source code.
A file such as:
text.envmay eventually contain:
envDATABASE_URL="..."
JWT_SECRET="..."
EMAIL_PASSWORD="..."Because this may contain sensitive configuration, we tell Git:
gitignore.envDo not commit it.
Even though we do not need .env yet, preparing .gitignore early helps us develop good habits.
Our Project Is Still Tiny
At the end of this setup, the project is simply:
textcommunity-platform-api/
│
├── src/
│ └── server.js
│
├── .gitignore
└── package.jsonThat may not look impressive.
But this small structure gives us a very clean foundation.
Understanding the Current Mental Model
So far:
textReal-World Problem
↓
Need a Backend
↓
Create Node.js Project
↓
package.json
↓
Nothing has been added without a reason.
What We Have Learned
At this stage, we already understand several important concepts.
Node.js
Allows us to run JavaScript outside the browser.
package.json
Describes and configures our Node.js application.
pnpm
Manages our project dependencies.
ES Modules
Allow us to organize JavaScript using:
jsimport
exportsrc/
Contains application source code.
server.js
Will become the entry point of our backend.
.gitignore
Prevents files such as:
textnode_modules
.envfrom being tracked by Git.
The Important Lesson
The most important lesson in this stage is not simply:
bashpnpm initThe real lesson is understanding why the files appear.
Instead of memorizing:
textCreate package.json
Create src
Create server.js
Create .gitignorewe understand:
textNeed Node.js project configuration
↓
package.json
Need place for source code
↓
src/
This kind of thinking makes larger applications much easier to understand.
Why We Are Not Using TypeScript Yet
You may notice that we are using:
textserver.jsinstead of:
textserver.tsThat is intentional.
The goal of this learning project is to understand backend concepts using JavaScript first.
We want to clearly understand:
- Functions
- Objects
- Modules
- Requests
- Responses
- Routes
before introducing another layer.
Once those foundations are comfortable, TypeScript can improve the project with things such as:
- Static typing
- Better editor assistance
- Safer refactoring
- Better type checking
But first:
Understand the system itself.
Beginner-Friendly Does Not Mean Outdated
Starting with JavaScript does not mean using old patterns.
We can still use modern approaches.
For example:
jsimport something from "./something.js";instead of:
jsconst something = require("./something");The goal is:
Keep the learning experience beginner-friendly while still using modern development practices.
Our Architecture So Far
Currently:
textcommunity-platform-api/
│
├── src/
│ └── server.js
│
├── .gitignore
└── package.jsonNo unnecessary complexity.
But that will change naturally as our application develops new requirements.
What's Next?
Right now:
textserver.jsdoes nothing.
We have a Node.js project, but we do not yet have an HTTP server.
In Backend Development Update #3, we will change that.
We will introduce Express and understand:
- What Express is
- Why Node.js alone is not the whole application
- What a server is
- What a port is
- What
localhostmeans
By the end of the next update, our backend will actually respond to requests.
GREE Software Academy
The goal is not to rush toward a complicated final architecture.
The goal is to understand every step that gets us there.
textStart Small
↓
Understand It
↓
Add One Concept
↓
Understand Why
↓
That is how we turn beginner JavaScript knowledge into real backend development ability.
One concept at a time.
Continue Learning
You have completed Update 2 — Setting Up Your First Modern Node.js Backend Project.
Previous
← Update 1 — From JavaScript Syntax to Solving Real Problems
Next
Update 3 — Build Your First Express Server with Beginner JavaScript →
In the next lesson, we turn our basic Node.js project into a real HTTP server and understand Express, localhost, ports, routes, requests, responses and JSON.

