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 tasks
  • POST /api/tasks with body {"title": "Buy groceries"} — Create a task
  • PUT /api/tasks/1 with body {"done": true} — Update a task
  • DELETE /api/tasks/1 — Delete a task

Next Steps

This tutorial uses in-memory storage — a great starting point. For a real project, consider:

  1. Connecting to a database (MongoDB with Mongoose, or PostgreSQL with Prisma)
  2. Adding authentication with JWT
  3. Using environment variables with dotenv
  4. Deploying to Railway, Render, or Fly.io

You now have a solid foundation for building RESTful APIs with Node.js and Express.