🧑‍💻 Build a Simple TODO App with Express.js – Beginner’s Guide

Skanda Prasad DSkanda Prasad D
4 min read

Hello fellow devs! 👋

After spending way too much time in the HTML/CSS/JS loop for the past year, I decided it was finally time to break out and dive into backend development. 🚀 This is the first real backend project I’ve worked on, and it’s a TODO app built with Node.js + Express.js.

If you’re a beginner like me, this article will guide you step-by-step in creating your first Express.js app. Let’s go!

🧱 Tech Stack:

  • Node.js

  • Express.js

  • File System (fs) for storing data in JSON files

🔥 Features of the App:

  • User Signup (POST /signup)

  • User Login (POST /login)

  • View Tasks (GET /tasks)

  • Add Tasks (POST /tasks)

  • Delete Tasks (DELETE /tasks)

🧑‍💻 Setup

Before we get started, make sure you have Node.js installed. If not, head over to Node.js official website to download it.

Create a new folder for your project and initialize it with npm:

mkdir express-todo-app
cd express-todo-app
npm init -y
npm install express

🧑‍💻 Step-by-Step Code Breakdown

1. Setting Up Express

In your index.js (or index2.js), we’ll start by setting up the Express server and importing the necessary modules:

const fs = require("fs");
const express = require("express");
const app = express();
const path = require("path");
const PORT = 3001;

app.use(express.json()); // Here, we're also setting up JSON parsing with express.json() middleware.

2. Signup Route

Let’s allow users to sign up. The POST /signup route will handle user creation:

app.post("/signup", (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).send("Username and password are required");
  }

  fs.readFile("user.json", "utf-8", function (err, data) {
    let users = [];
    if (err && err.code !== "ENOENT") {
      return res.status(500).send("Error reading user file");
    }
    if (!err) {
      try {
        users = JSON.parse(data);
      } catch (parseErr) {
        return res.status(500).send("Error parsing user data");
      }
    }

    if (users.find((user) => user.username === username)) {
      return res.status(400).send("Username already exists");
    }

    users.push({ username, password });

    fs.writeFile("user.json", JSON.stringify(users, null, 2), (err) => {
      if (err) return res.status(500).send("Error saving user");
      res.status(201).send("User created successfully");
    });
  });
});

3. Login Route

Here, we authenticate users when they try to log in:

app.post("/login", (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).send("Username and password are required");
  }

  fs.readFile("user.json", "utf-8", function (err, data) {
    if (err) return res.status(500).send("Error reading user file");

    let users = [];
    try {
      users = JSON.parse(data);
    } catch (parseErr) {
      return res.status(500).send("Error parsing user data");
    }

    const user = users.find(
      (user) => user.username === username && user.password === password
    );

    if (!user) {
      return res.status(400).send("Invalid credentials");
    }

    res.send("Login Successful");
  });
});

4. Get Tasks for User

Once logged in, a user can fetch their tasks:

app.get("/tasks", (req, res) => {
  const { username } = req.body;

  if (!username) {
    return res.status(400).send("Username is required");
  }

  fs.readFile("todo2.json", "utf-8", function (err, data) {
    if (err && err.code !== "ENOENT") {
      return res.status(500).send("Error reading tasks file");
    }

    let tasks = [];
    if (!err) {
      try {
        tasks = JSON.parse(data);
      } catch (parseErr) {
        return res.status(500).send("Error parsing tasks data");
      }
    }

    const userTasks = tasks.filter((task) => task.username === username);
    res.json(userTasks);
  });
});

5. Add and Delete Tasks

The app also lets users add and delete tasks:

app.post("/tasks", (req, res) => {
  const { username, task } = req.body;
  // Add task logic
});

app.delete("/tasks", (req, res) => {
  const { username, task } = req.body;
  // Delete task logic
});

// Both operations read and write to todo2.json to store tasks.

💡 What I Learned

  • Setting up a backend server with Express.js and Node.js

  • Working with file system (fs) for mock data storage

  • Creating RESTful APIs for user authentication and task management

  • Handling JSON data and error handling in Express


🚀 What’s Next?

  • Add authentication using JWT

  • Switch from JSON files to a real MongoDB database

  • Build a React frontend for this app

🔗 Check out my code on GitHub:

GIthub Repo

Feel free to leave any questions or suggestions below. Happy coding! ✨

0
Subscribe to my newsletter

Read articles from Skanda Prasad D directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Skanda Prasad D
Skanda Prasad D