DEV Community

Cover image for Building an Express.js CRUD Application from Scratch: A Step-by-Step Guide for Beginners
Mohin Sheikh
Mohin Sheikh

Posted on

Building an Express.js CRUD Application from Scratch: A Step-by-Step Guide for Beginners

Image description

📖 Table of Contents

  1. Introduction to Express.js
  2. Setting Up the Project Environment
  3. Project Structure Overview
  4. Installing Dependencies
  5. Creating the Express Server
  6. Defining Routes
  7. Creating Controllers
  8. Setting Up a Database (Optional)
  9. Implementing CRUD Operations
    • Create (POST)
    • Read (GET)
    • Update (PUT)
    • Delete (DELETE)
  10. Middleware and Error Handling
  11. Testing the APIs with Postman
  12. Conclusion and Best Practices

1. Introduction to Express.js

  • What is Express.js?

    Express.js is a minimal and flexible Node.js web application framework that provides a robust set of features for building web and mobile applications.

  • Why Use Express.js?

    • Lightweight and fast.
    • Flexible routing system.
    • Middleware support.
    • Easy integration with databases.

2. Setting Up the Project Environment

  • Install Node.js (LTS version recommended).
  • Verify installation:
  node -v
  npm -v
Enter fullscreen mode Exit fullscreen mode
  • Initialize a new Node.js project:
  mkdir express-crud-app
  cd express-crud-app
  npm init -y
Enter fullscreen mode Exit fullscreen mode

3. Project Structure Overview

Organize your project like this:

express-crud-app/
│
├── src/
│   ├── controllers/
│   │   ├── userController.ts
│   │
│   ├── routes/
│   │   ├── userRoutes.ts
│   │
│   ├── models/
│   │   ├── userModel.ts
│   │
│   ├── middlewares/
│   │   ├── errorHandler.ts
│   │
│   ├── app.ts
│
├── package.json
├── tsconfig.json
└── README.md
Enter fullscreen mode Exit fullscreen mode

4. Installing Dependencies

Install necessary dependencies:

npm install express body-parser mongoose
npm install --save-dev typescript @types/express @types/node nodemon
Enter fullscreen mode Exit fullscreen mode

Update package.json scripts:

"scripts": {
  "start": "node dist/app.js",
  "dev": "nodemon src/app.ts"
}
Enter fullscreen mode Exit fullscreen mode

5. Creating the Express Server

File: src/app.ts

import express, { Request, Response } from 'express';
import userRoutes from './routes/userRoutes';

const app = express();
const PORT = 3000;

app.use(express.json());

// Routes
app.use('/api/users', userRoutes);

// Health Check
app.get('/', (req: Request, res: Response) => {
  res.send('Express Server is running!');
});

// Start Server
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

6. Defining Routes

File: src/routes/userRoutes.ts

import { Router } from 'express';
import {
  getUsers,
  getUserById,
  createUser,
  updateUser,
  deleteUser
} from '../controllers/userController';

const router = Router();

router.get('/', getUsers);
router.get('/:id', getUserById);
router.post('/', createUser);
router.put('/:id', updateUser);
router.delete('/:id', deleteUser);

export default router;
Enter fullscreen mode Exit fullscreen mode

7. Creating Controllers

File: src/controllers/userController.ts

import { Request, Response } from 'express';

let users = [
  { id: 1, name: 'John Doe', email: 'john@example.com' },
];

export const getUsers = (req: Request, res: Response) => {
  res.status(200).json(users);
};

export const getUserById = (req: Request, res: Response) => {
  const user = users.find(u => u.id === parseInt(req.params.id));
  if (user) {
    res.status(200).json(user);
  } else {
    res.status(404).json({ message: 'User not found' });
  }
};

export const createUser = (req: Request, res: Response) => {
  const newUser = { id: users.length + 1, ...req.body };
  users.push(newUser);
  res.status(201).json(newUser);
};

export const updateUser = (req: Request, res: Response) => {
  const user = users.find(u => u.id === parseInt(req.params.id));
  if (user) {
    Object.assign(user, req.body);
    res.status(200).json(user);
  } else {
    res.status(404).json({ message: 'User not found' });
  }
};

export const deleteUser = (req: Request, res: Response) => {
  users = users.filter(u => u.id !== parseInt(req.params.id));
  res.status(200).json({ message: 'User deleted' });
};
Enter fullscreen mode Exit fullscreen mode

8. Middleware and Error Handling

File: src/middlewares/errorHandler.ts

import { Request, Response, NextFunction } from 'express';

export const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error(err.stack);
  res.status(500).json({ message: 'Something went wrong!' });
};
Enter fullscreen mode Exit fullscreen mode

Add it to app.ts:

import { errorHandler } from './middlewares/errorHandler';
app.use(errorHandler);
Enter fullscreen mode Exit fullscreen mode

9. Testing with Postman

Sample Requests and Responses

1. Create User (POST /api/users)

Request Body:

{
  "name": "Alice",
  "email": "alice@example.com"
}
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "id": 2,
  "name": "Alice",
  "email": "alice@example.com"
}
Enter fullscreen mode Exit fullscreen mode

2. Get All Users (GET /api/users)

Response:

[
  {
    "id": 1,
    "name": "John Doe",
    "email": "john@example.com"
  },
  {
    "id": 2,
    "name": "Alice",
    "email": "alice@example.com"
  }
]
Enter fullscreen mode Exit fullscreen mode

3. Update User (PUT /api/users/:id)

Request Body:

{
  "name": "Updated Name"
}
Enter fullscreen mode Exit fullscreen mode

Response:

{
  "id": 1,
  "name": "Updated Name",
  "email": "john@example.com"
}
Enter fullscreen mode Exit fullscreen mode

4. Delete User (DELETE /api/users/:id)

Response:

{
  "message": "User deleted"
}
Enter fullscreen mode Exit fullscreen mode

10. Conclusion and Best Practices

  • Always validate user input.
  • Use middleware effectively.
  • Follow RESTful API conventions.
  • Organize code into meaningful files and folders.

11. Next Steps


✨ Congratulations! You've built an Express.js CRUD application from scratch.


Author: Mohin Sheikh

Follow me on GitHub for more insights!

Top comments (0)