What You'll Build
In this tutorial, you'll create a simple but production-ready REST API for a task manager app using Node.js and Express. By the end, you'll understand routing, middleware, request validation, and clean project structure.
Prerequisites
- Node.js v18+ installed
- Basic understanding of JavaScript
- A terminal and a code editor (VS Code recommended)
Step 1: Initialize Your Project
Create a new directory and initialize a Node project:
mkdir task-api && cd task-api
npm init -y
npm install express
Also install nodemon for automatic server restarts during development:
npm install --save-dev nodemon
Add a start script to your package.json:
"scripts": {
"dev": "nodemon index.js"
}
Step 2: Create the Entry Point
Create index.js in the project root:
const express = require('express');
const app = express();
const PORT = 3000;
app.use(express.json());
app.get('/', (req, res) => {
res.json({ message: 'Task API is running' });
});
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Step 3: Define Your Routes
Create a routes/tasks.js file to keep things organized:
const express = require('express');
const router = express.Router();
let tasks = [];
let nextId = 1;
// GET all tasks
router.get('/', (req, res) => res.json(tasks));
// POST create task
router.post('/', (req, res) => {
const { title } = req.body;
if (!title) return res.status(400).json({ error: 'Title is required' });
const task = { id: nextId++, title, done: false };
tasks.push(task);
res.status(201).json(task);
});
// PUT update task
router.put('/:id', (req, res) => {
const task = tasks.find(t => t.id === parseInt(req.params.id));
if (!task) return res.status(404).json({ error: 'Task not found' });
Object.assign(task, req.body);
res.json(task);
});
// DELETE task
router.delete('/:id', (req, res) => {
tasks = tasks.filter(t => t.id !== parseInt(req.params.id));
res.status(204).send();
});
module.exports = router;
Step 4: Register the Routes
Back in index.js, mount the router:
const tasksRouter = require('./routes/tasks');
app.use('/api/tasks', tasksRouter);
Step 5: Add a Global Error Handler
Place this at the bottom of index.js, before app.listen:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Internal Server Error' });
});
Testing Your API
Run npm run dev and test with a tool like Postman, Insomnia, or curl:
GET /api/tasks— List all tasksPOST /api/taskswith body{"title": "Buy groceries"}— Create a taskPUT /api/tasks/1with body{"done": true}— Update a taskDELETE /api/tasks/1— Delete a task
Next Steps
This tutorial uses in-memory storage — a great starting point. For a real project, consider:
- Connecting to a database (MongoDB with Mongoose, or PostgreSQL with Prisma)
- Adding authentication with JWT
- Using environment variables with
dotenv - Deploying to Railway, Render, or Fly.io
You now have a solid foundation for building RESTful APIs with Node.js and Express.