Building a Simple REST API with the MERN Stack
In this tutorial, we will walk you through creating a simple REST API using the MERN stack. If you are not familiar with MERN, it stands for MongoDB, ExpressJS, ReactJS, and NodeJS. This stack is a popular choice for developers because it allows for easier and faster deployment of full-stack web applications using JavaScript.
Before we dive into the coding part, let’s cover some foundational concepts.
What is REST API?
REST, which stands for REpresentational State Transfer, is an architectural style that defines a set of constraints to be used for creating web services. A REST API (Application Programming Interface) allows for accessing web services in a simple, flexible manner without requiring additional processing. It was created by computer scientist Roy Fielding.
What is an API?
An API is a set of definitions and protocols for building and integrating application software. It acts as a contract between an information provider and an information user, specifying the required content from the consumer (the call) and the content provided by the producer (the response).
Why Use NPM Modules?
Node Package Manager (NPM) modules are essential for simplifying the development process. They provide pre-built functionalities that you can easily integrate into your application. By using NPM modules, you can save time and effort, allowing you to focus on the core logic of your application.
Setting Up Your Project
Let’s start by setting up our project.
1. Create a Project Folder:
- Create a folder named server
2. Open the Folder in Visual Studio Code:
- Navigate to the
server
directory and open it in Visual Studio Code.
3. Initialize NPM:
- Open the terminal in Visual Studio Code and run the following command to initialize a new Node.js project:
npm init -y
4. Install Necessary NPM Packages:
- Install the following NPM packages:
npm install nodemon express mongoose cors dotenv
Project Structure
We will organize our backend following the Model-View-Controller (MVC) pattern. Although we are not creating views for this API, the structure will include models and controllers.
- Models: Define the data structure.
- Controllers: Handle the logic for processing requests and interacting with models.
- Routes: Define the endpoints for the API.
Here’s the folder structure:
server/
│
├── Models/
│ └── Todo.js
├── Controllers/
│ └── todoController.js
├── Routes/
│ └── todoRoute.js
├── .env
└── server.js
Creating server.js
Create a server.js
file in the root of the server
folder. This file will set up and start our server.
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
require("dotenv").config();
const todoRoute = require('./routes/todoRoute')
const app = express();
app.use(cors());
app.use(express.json());
mongoose.connect(process.env.DB_URL)
.then(() => {
console.log("Connected to Database Successfully!");
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Listening to the port ${PORT}`);
});
}).catch((error) => {
console.error(`Mongoose Connection Error! ${error}`);
});
app.use('/api/todos', todoRoute);
module.exports = app;
Creating the Model
Create a file named Todo.js
inside the Models
folder. This file defines the schema for our data.
const mongoose = require("mongoose");
const todoSchema = new mongoose.Schema({
todo: {
type: String,
required: true
}
}, {timestamps: true});
module.exports = mongoose.model("Todo", todoSchema);
Creating the Controller
Create a file named todoController.js
inside the Controllers
folder. This file contains the logic for handling requests.
const Todo = require('../models/Todo');
const createTodo = async (req, res) => {
try {
const { todo } = req.body;
const newTodo = new Todo({ todo });
await newTodo.save();
res.json({ message: "Todo added successfully", todo: newTodo });
} catch (error) {
console.error(error.message);
res.status(500).send("Server Error");
}
};
const getAllTodos = async (req, res) => {
try {
const todos = await Todo.find();
res.json(todos);
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
};
const updateTodo = async (req, res) => {
try {
const todoId = req.params.todoId;
const { todo } = req.body;
const updatedTodo = await Todo.findByIdAndUpdate(todoId, { todo }, { new: true });
if (!updatedTodo) {
return res.status(404).json({ message: 'Todo not found' });
}
res.json({ message: 'Todo updated successfully', updatedTodo });
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
};
const deleteTodo = async(req, res)=>{
try{
const todoId = req.params.todoId;
await Todo.findByIdAndDelete(todoId);
res.json({message: 'Post deleted Successfully !'});
}catch(error){
console.error(error.message);
res.status(500).send("Server Error");
}
};
module.exports = { createTodo, getAllTodos, deleteTodo, updateTodo };
Creating the Routes
Create a file named todoRoute.js
inside the Routes
folder. This file defines the endpoints for our API.
const exxpress = require('express');
const router = exxpress.Router();
const {createTodo, getAllTodos, deleteTodo, updateTodo} = require('../controllers/todoController');
router.post('/', createTodo);
router.get('/', getAllTodos);
router.delete('/:todoId', deleteTodo);
router.put('/:todoId', updateTodo);
module.exports = router;
Environment Variables
Create a file named .env
in the root of the server
folder to store your environment variables.
PORT = 4000
DB_URL = <MongoDbURL>
Running the Server
To start the server, use the following command:
nodemon server.js
Your REST API is now set up and running. You can add more models, controllers, and routes to expand the functionality of your API. In future articles, we will cover CRUD operations in detail and how to integrate this backend with a React frontend.
Example Project
For a complete implementation, you can refer to my GitHub repository, which contains the full code and setup for this MERN stack REST API, including frontend integration.