We'll be creating a minimal full-stack app using the MERN
stack (MongoDB
for database, Express
and Node
for backend, and React
for frontend) to perform CRUD
operations.
Our app will allow users to
- Create a todo
- Read todos
- Update a todo
- Delete a todo
This series should enable you understand CRUD
operations using MERN
stack.
In this part (part1), we will
- Initialize our backend using
npm
and install necessary packages - Set up a MongoDB database
- Set up server using
Node
andExpress
- Create a database schema to define a
Todo
- Set up API routes to
create
,read
,update
anddelete
documents from the database - Testing our
API
routes using Insomnia
Before we get started
Prerequisites
One should have at least some basic understanding of fundamental programming concepts and some experience with HTML
, CSS
, JavaScript
.
This post is not meant to explain the MERN
stack, but it is a good introduction to building a full-stack app with it.
Install
-
VS Code
or any other editor - Latest version of
Node.js
-
Insomnia
or Postman -
Prettier
VS code extension to format the code
Part 1: Creating Backend
1. Initializing our project
Create a new folder and name it anything that you like and then open the folder in VS code and run the following code from the command prompt.
npm init -y
After running this command you will find a package.json
if the folder.
2. Setting up package.json
i. Install the following dependencies
Run the following commands in the terminal to install the dependencies
npm i cors dotenv express mongoose
cors
: allows cross-origin api calls
dotenv
: needed to access data from .env
files
express
: web application framework for node.js
mongoose
: It is needed to define the database schema and connecting to mongoDB
ii. Install the following development dependencies
Now install the following development dependencies, -D
is used to install the development dependencies.
npm i -D nodemon
After installing the dependencies the package.json
folder should look as follows.
// package.json
{
"name": "mern-todo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"config": "^3.3.6",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"mongoose": "^5.13.2"
},
"devDependencies": {
"nodemon": "^2.0.11"
}
}
iii. change the main
entry point to server.js
Now, create a server.js
file and a .env
. The server.js
file will be the entry point of the server and the .env
file will contain the MONGO_URI
. We also have to make the following changes in the package.json
//package.json
{
"name": "mern-todo",
"version": "1.0.0",
"description": "",
"main": "server.js", //changed
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"config": "^3.3.6",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"mongoose": "^5.13.2"
},
"devDependencies": {
"nodemon": "^2.0.11"
}
}
Now, create the following folders
config
: Inside theconfig
folder, create a file nameddb.js
. This file will contain the required code for connecting to theMongoDB
database.controllers
: Thecontrollers
folder will contain the files which will have the methods for the end points to communicate with the database.models
: Themodels
folder, will contain the files which will define theMongoDB schema
routers
: Therouters
folder will contain the files with theendpoints
.
At this stage the file structure should look as follows
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js
├── package-lock.json
└── package.json
iv. Change the scripts
to the following
"scripts": {
"start":"node server.js",
"dev":"nodemon server.js"
}
The package.json
file should look as follows
{
"name": "mern-todo",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js", //added
"dev": "nodemon server.js" //added
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"config": "^3.3.6",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"mongoose": "^5.13.2"
},
"devDependencies": {
"nodemon": "^2.0.11"
}
}
v. Setting up server
We will do the following to setup the server
- Import
express
- Initialize our app using
express()
- Set up a
get
method for the endpointhttp://localhost:8000
usingapp.get()
- Set the
PORT
to8000
for our server to run - Have our app to listen to
PORT
usingapp.listen()
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js <-- we are here
├── package-lock.json
└── package.json
The code will look as follows
And start the server using nodemon
using the following code. Make sure you are running the following command from the project directory.
npm run dev
If the server has started successfully then it should show the following message in the terminal
[nodemon] 2.0.11
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
server is running on http://localhost:8000
You can also open http://localhost:8000
on your browser.
vi. Getting the MONGO URI
from mongoDB
To connect to the database we will need the link for the mongoDB
collection.
- Log in to mongoDB
- Create a new project
- Build a cluster
- Select cloud provider
- Create cluster
- wait for the cluster to be created.
- Click on connect
- click on
allow access from anywhere
. ThenAdd IP address
- Create a database user. You'll need the
username
andpassword
for theMongoDB URI
. - Click on the
Choose a connection method
- Click on
Connect your application
-
Select the following driver and version
Copy the
mongodb+srv
and paste it in the.env
file
vii. Setting up .env
file
//.env
MONGO_URI = mongodb+srv://<username>:<password>@cluster0.owmij.mongodb.net
Replace the <username>
and <password>
with your database username and password which you will set in step 9.
viii. Connecting to database
.
├── config
│ └── db.js <-- we are here
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js
├── package-lock.json
└── package.json
Now, open the db.js
file which is in the config
folder and add the following changes.
- Import
mongoose
- Import
MONGO_URI
from.env
- Define the
connectDB
methof for connecting to the database - Export the
connectDB
method to be called inserver.js
Add the following changes in the server.js
file.
- Import
dotenv
- Import
connectDB
method fromconfig/db.js
- Call the
connectDB
method.
Let us make the the following changes in server.js
Save the changes it will restart the server or use the command npm run dev
. The terminal should show a message of MongoDB is connected
which we have added in the db.js
under the try block.
ix. Defining database schema
Create a todo.js
file in the models folder. We will define the database schema in this file.
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js <-- we are here
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js
├── package-lock.json
└── package.json
- Import
mongoose
- Create a
Schema
calledTodoSchema
- We will add two fields for our todo;
title
anddescription
- Type of
title
will beString
and it is a mandatory field - Type of
description
will beString
and it is not a mandatory field - Export the model
The code will look as follows
x. Defining the end points
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js <-- we are here
├── .env
├── server.js
├── package-lock.json
└── package.json
We will define the end points for the CRUD
operations
- Import
express
- Initialize
router
- We will later import the methods for the endpoint from
controllers
- Define a
GET
method toread
all the todo - Define a
POST
method tocreate
a new todo - Define a
PUT
method toupdate
a existing todo - Define a
DELETE
method todelete
a existing todo - Export the
router
The code will look as follows
xi. Defining the methods for the end points
We will define the methods for the end points in the controllers
folder
.
├── config
│ └── db.js
├── controllers
│ └── todo.js <-- we are here
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js
├── package-lock.json
└── package.json
- Import
Todo
model frommodels/todo
- Define the following four methods
getAllTodo
postCreateTodo
putUpdateTodo
deleteTodo
- Export all the methods
getAllTodo
: The find()
method will return all the todo in the collection. If the collection is empty then it will return a 404
error.
postCreateTodo
: The create()
method will create a todo and return a success message. Otherwise, it will return a 400
error.
putUpdateTodo
: The findByIdAndUpdate()
will require two parameters the id
and data
of the todo to be updated. The id
parameter will be extracted from req.params.id
.
deleteTodo
: The findByIdAndRemove()
method will require only one parameter that is the id
of the todo.
xii. Adding the methods to the end points
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js <-- we are here
├── .env
├── server.js
├── package-lock.json
└── package.json
- Import the methods for
CRUD
operations - Adding the methods to the end points
xiii. Adding the routes end points in the server.js
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js <-- we are here
├── package-lock.json
└── package.json
The final part of completing the backend is to add the endpoints to the server.js
file.
- Import
routes/todo.js
- Add the routes endpoints to the middleware
3 Testing the end points using Insomnia
- Creating a todo
We will send a POST
request to http://localhost:8000/api/todo
- Reading the todo
We will send a GET
request to http://localhost:8000/api/todo
You can check the changes in mongoDB in collections
- Updating a todo
To update a todo we will send a PUT
request to http://localhost:8000/api/todo/id
The id
has to be taken from the response message of the server.
{
"message": "Todo added successfully",
"data": {
"_id": "60ec0f9655f9735a60a2d967",
"title": "test todo",
"description": "test todo",
"__v": 0
}
}
For updating the todo we will need the id
. We will get the id
from the _id
from the preview tab. We can get the id
from the preview
after using the GET
request and POST
request.
- Deleting a todo
To delete a todo we will send a DELETE
request to http://localhost:8000/api/todo/id
4. Adding cors
.
├── config
│ └── db.js
├── controllers
│ └── todo.js
├── models
│ └── todo.js
├── node_modules
├── routes
│ └── todo.js
├── .env
├── server.js <-- we are here
├── package-lock.json
└── package.json
Added cors
so that we can make the api calls from the frontend application like react.
You can see the entire code of this blog in GitHub
Top comments (6)
succinctly demystified. Thanks!
Thank you so much for this post, well explained.
Just what I needed, thanks
Thank you for this amazing guide on building a to-do list! I followed the step and was able to implement it successfully.
I'm using MongoDb Compass what should I add in my connection string??
I'm getting error in posting the data to the databse....
Great tutorial! I appreciate all the time and effort that you have put into this.