This content originally appeared on DEV Community and was authored by sudip khatiwada
Want to build a backend API in under an hour? Think of a CRUD API like a digital librarian – it helps you Create new books, Read existing ones, Update book details, and Delete books from your collection. Today, we’ll build this “librarian” using Node.js, Express, and MongoDB Atlas.
What You’ll Build
By the end of this tutorial, you’ll have a working REST API that manages a simple book collection. Perfect for beginners wanting to understand backend development fundamentals.
Setting Up Your Environment
First, ensure you have Node.js installed on your machine. Create a new project directory and initialize it:
mkdir books-api
cd books-api
npm init -y
npm install express mongoose cors dotenv
This installs our essential packages: Express for the server, Mongoose for MongoDB integration, CORS for cross-origin requests, and dotenv for environment variables.
MongoDB Atlas Setup
MongoDB Atlas is like having a cloud-based library storage system. Sign up for a free account at mongodb.com/atlas and:
- Create a new cluster (choose the free tier)
- Set up database access with a username/password
- Whitelist your IP address (or use 0.0.0.0/0 for development)
- Get your connection string from the “Connect” button
Screenshot suggestion: Show the MongoDB Atlas dashboard highlighting the connection string location.
Building the CRUD API
Create a .env
file for your MongoDB connection:
MONGODB_URI=your_connection_string_here
PORT=3000
Now, let’s build our complete API server in server.js
:
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
require('dotenv').config();
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
// Connect to MongoDB Atlas
mongoose.connect(process.env.MONGODB_URI)
.then(() => console.log('Connected to MongoDB Atlas'))
.catch(err => console.error('MongoDB connection error:', err));
// Book Schema
const bookSchema = new mongoose.Schema({
title: { type: String, required: true },
author: { type: String, required: true },
year: { type: Number, required: true },
genre: String
}, { timestamps: true });
const Book = mongoose.model('Book', bookSchema);
// CRUD Routes
// CREATE - Add a new book
app.post('/api/books', async (req, res) => {
try {
const book = new Book(req.body);
const savedBook = await book.save();
res.status(201).json(savedBook);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
// READ - Get all books
app.get('/api/books', async (req, res) => {
try {
const books = await Book.find();
res.json(books);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// READ - Get single book by ID
app.get('/api/books/:id', async (req, res) => {
try {
const book = await Book.findById(req.params.id);
if (!book) {
return res.status(404).json({ error: 'Book not found' });
}
res.json(book);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// UPDATE - Update a book
app.put('/api/books/:id', async (req, res) => {
try {
const book = await Book.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true, runValidators: true }
);
if (!book) {
return res.status(404).json({ error: 'Book not found' });
}
res.json(book);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
// DELETE - Remove a book
app.delete('/api/books/:id', async (req, res) => {
try {
const book = await Book.findByIdAndDelete(req.params.id);
if (!book) {
return res.status(404).json({ error: 'Book not found' });
}
res.json({ message: 'Book deleted successfully' });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Testing Your API
Start your server with:
node server.js
Test your endpoints using tools like Postman or curl:
-
POST
/api/books
– Create a book -
GET
/api/books
– Get all books -
GET
/api/books/:id
– Get one book -
PUT
/api/books/:id
– Update a book -
DELETE
/api/books/:id
– Delete a book
Understanding the Code
Our Express MongoDB tutorial demonstrates key concepts:
- Mongoose Schema: Defines our book structure with validation
- Async/Await: Handles database operations cleanly
- Error Handling: Provides meaningful error responses
- RESTful Routes: Follows standard HTTP methods for CRUD operations
Next Steps
Congratulations! You’ve built a functional Node.js CRUD API. Your “digital librarian” can now manage books efficiently.
Ready to level up? Try adding authentication to your API next, or explore adding search functionality to filter books by genre or author. The fundamentals you’ve learned here form the backbone of most modern web applications.
This tutorial provides a solid foundation for building REST APIs with the popular MERN stack. Remember to secure your MongoDB Atlas credentials and never commit your .env
file to version control!
This content originally appeared on DEV Community and was authored by sudip khatiwada