Skip to main content

Command Palette

Search for a command to run...

Building a Todo App using Express.js + MongoDB

Updated
5 min read
Building a Todo App using Express.js + MongoDB
S

I'm Shubham (@shubhamsinghbundela), I'm a Software Engineer, a Full-stack developer, a tech enthusiast, and a technical writer here on @Hashnode. I have a strong zeal to share my acquired knowledge and I am also willing to learn from others.

Last time, I wrote about Understanding HTTP Requests, Responses, and Methods using Node.js.

This time, I took it one step further…

I built a Todo Application using Express.js and MongoDB


What I Built

  • User Signup & Signin

  • Create Todo

  • Get Todos of logged-in user

  • Protected routes using middleware

  • MongoDB for database


Step 1: Setup Express Server

First, I created a basic Express server:

const express = require("express");
const app = express();

app.use(express.json());

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

Step 2: Setup MongoDB

  1. Go to https://cloud.mongodb.com/

  2. Create account & login

  3. Create a Cluster

  4. Go to Database Access

    • Create username & password
  5. Go to Network Access

    • Add IP: 0.0.0.0/0 (for development)
  6. Click Connect

  7. Copy connection string

Example:

mongodb+srv://username:password@cluster.mongodb.net/dbname

MongoDB Connection Code

Before connecting MongoDB, first we need to install mongoose.

Step 1: Install Mongoose

Run this command in your project:

npm install mongoose

Step 2: Connect to MongoDB

Now write the connection code:

const mongoose = require("mongoose");

async function connectDB() {
    try {
        await mongoose.connect("mongodb+srv://<username>:<password>@todo.dtrpx.mongodb.net/todo");
        console.log("MongoDB connected");
    } catch (err) {
        console.error("Connection error:", err);
    }
}

connectDB();

Initially, I tried connecting to MongoDB (cloud) but faced a DNS issue

Problem:

MongoDB connection was failing due to DNS resolution.

Fix:

After watching a YouTube video: , I added this:

const dns = require("dns");
dns.setServers(["1.1.1.1", "8.8.8.8"]);

This fixed the issue and I was able to connect to cloud MongoDB.


Step 3: Create Schema using Mongoose

Before writing any backend or frontend logic, I first designed how my data should look.

This step is very important.

Learning:
Always define your schema first before building APIs or UI.

Because:

  • It gives clarity on what data you need

  • Helps structure your database properly

  • Makes backend logic easier to write

const userSchema = new mongoose.Schema({
    userName: String,
    password: String,
    firstName: String,
    lastName: String
})

const todoSchema = new mongoose.Schema({
    description: String,
    userId: mongoose.Types.ObjectId
})

const userModel = mongoose.model("users", userSchema);
const todoModel = mongoose.model("todos", todoSchema);

module.exports = {
    userModel: userModel,
    todoModel: todoModel
}

Step 4: Signup Route

Before writing code, let’s understand the goal.

What we want to achieve:

  • Allow a new user to register

  • Store user details in database

  • Prevent duplicate users

app.post("/signup", async (req, res) => {
  const { userName, password, firstName, lastName } = req.body;

  // checking user exist or not
  const existingUser = await userModel.findOne({
    userName,
    password,
  });

  if (existingUser) {
    return res.status(403).json({
      message: "User already exists",
    });
  }

  // added new user in userModel collection
  const newUser = await userModel.create({
    userName,
    password,
    firstName,
    lastName,
  });

  res.json({
    id: newUser._id,
  });
});

Step 5: Signin + JWT Token

Before writing code, let’s understand the goal.

What we want to achieve:

  • Verify user credentials

  • If valid → allow login

  • Generate a JWT token for authentication

app.post("/signin", async (req, res) => {
  const { userName, password } = req.body;

  const userExist = await userModel.findOne({ userName });

  if (!userExist) {
    return res.status(404).json({
      message: "User not found",
    });
  }

  const token = jwt.sign(
    { userId: userExist.id },
    "shubham123"
  );

  res.json({ token });
});

Step 6: Auth Middleware

This ensures only logged-in users can access routes.

function authMiddleware(req, res, next) {
    const token = req.headers.token;

    const decode = jwt.verify(token, "shubham123");

    req.userId = decode.userId;

    next();
}

Step 7: Create Todo

Before writing the code, let’s understand

What are we trying to achieve?

We want:
1. Only logged-in users should be able to create a todo i.e. Each todo should be linked to the specific user who created it

When user tries to create a todo, first authentication happens using authMiddleware.

  • It verifies the token

  • Extracts userId

  • Attaches it to req.userId

Then we use this userId to link the todo with the logged-in user.

So each todo belongs to a specific user, and later we can fetch user-specific todos.

app.post("/todo", authMiddleware, async (req, res) => {
  const newTodo = await todoModel.create({
    description: req.body.description,
    userId: req.userId
  });

  res.json({
    id: newTodo._id
  });
});

Step 8: Get All Todos

app.get("/todos", authMiddleware, async (req, res) => {
  const allTodos = await todoModel.find({
    userId: req.userId
  });

  res.json({ allTodos });
});

Testing using Postman

I used Postman to test APIs.

Signup

{
  "userName": "shubham",
  "password": "1234",
  "firstName": "Shubham",
  "lastName": "Singh"
}

Signin

  • Method: POST

  • URL: /signin

Copy the token from response


Create Todo

  • Method: POST

  • URL: /todo

  • Headers:

token: YOUR_TOKEN
  • Body:
{
  "description": "Learn Express"
}

Get Todos

  • Method: GET

  • URL: /todos

  • Headers:

token: YOUR_TOKEN

Complete Source Code

👉 I’ve uploaded the complete project on GitHub. You can check it here:

GitHub Repo:
https://github.com/shubhamsinghbundela/Todo-application-using-express/tree/main

More from this blog

Shubham Tech. Blog's

55 posts

Problem Solver | Currently Working As a Full Stack Developer, Community Leader At @Dev_Matrix | Previously Contributor at @RealDevSquad, @TeamShiksha