Skip to content

Module Recap

Module 04 covered middleware and project structure — the patterns that turn a simple Express script into a maintainable, production-quality API.

Middleware is the (req, res, next) pipeline. Every request passes through a chain of functions before reaching a route handler. Each function can modify req/res, end the request, or call next() to continue. Order matters.

Built-in and third-party middleware handle common needs. express.json() parses request bodies. cors() enables cross-origin requests from your frontend. morgan() logs every request. Register them before routes, in this order.

Custom middleware is just functions. Write middleware factories (functions that return middleware) for reusable, configurable behavior. Use res.locals to attach request-scoped data for downstream handlers.

Express Router groups related routes. express.Router() creates a sub-application mounted at a path. Separate route files by resource. Separate business logic into controller files — route files only map paths to controller functions.

Error middleware centralizes error handling. The 4-argument (err, req, res, next) signature identifies error middleware. A custom AppError class carries status codes. Register error middleware last. Wrap async handlers to catch Promise rejections.

The Bulletin API’s structure after Module 04:

// src/index.ts — clean, declarative
import express from 'express'
import cors from 'cors'
import morgan from 'morgan'
import authRouter from './routes/auth.js'
import postsRouter from './routes/posts.js'
import commentsRouter from './routes/comments.js'
import { errorHandler } from './middleware/errorHandler.js'
import { config } from './config.js'
const app = express()
app.use(morgan('dev'))
app.use(cors({ origin: config.frontendUrl }))
app.use(express.json())
app.use('/auth', authRouter)
app.use('/posts', postsRouter)
app.use('/posts', commentsRouter)
app.use((req, res) => res.status(404).json({ error: 'Not found' }))
app.use(errorHandler)
app.listen(config.port)

Every route, middleware, and error handler has a clear, single responsibility.

TermWhat it means
Middleware(req, res, next) function in the Express request pipeline
next()Passes to the next middleware; next(err) jumps to error handler
res.localsRequest-scoped data passed between middleware
express.json()Parses JSON bodies into req.body
cors()Sets headers to allow cross-origin requests
morgan()HTTP request logger
express.Router()Creates a sub-application for route grouping
ControllerFile containing business logic separated from route definitions
Error middleware4-argument (err, req, res, next) — must be registered last
AppErrorCustom error class that carries an HTTP status code

Module 05 — SQLite and Data Persistence →

Module 05 replaces the in-memory data store with a real database. You’ll learn relational database concepts, set up SQLite with better-sqlite3, design the Bulletin schema, and write SELECT, INSERT, UPDATE, and DELETE queries. By the end, your API data survives server restarts.