ExoSnip Code Snippets

Express.js Snippets

← Back to Home

About Express.js

Express helps you build web APIs quickly. This learning track uses modular layers, request validation, error handling, and a mini project-ready API pattern.

Project Structure for Express API Learning

Layer your API from route to controller to service to keep endpoints easy to test and extend.

bookmarks-api/
  src/
    app.js
    server.js
    routes/bookmarkRoutes.js
    controllers/bookmarkController.js
    services/bookmarkService.js
    middleware/errorHandler.js
    middleware/validate.js
    middleware/apiKeyAuth.js
    schemas/bookmarkSchemas.js
  tests/
    bookmarks.test.js
  package.json

Install Dependencies

Install Express and common API helpers for logging, CORS, environment config, and schema validation.

npm init -y
npm install express cors morgan dotenv zod
npm install -D supertest

Bootstrap App with Middlewares (src/app.js)

Register middleware once in app.js, then keep server startup in a separate file.

import express from 'express'
import cors from 'cors'
import morgan from 'morgan'
import bookmarkRoutes from './routes/bookmarkRoutes.js'
import { errorHandler } from './middleware/errorHandler.js'

const app = express()
app.use(cors())
app.use(express.json())
app.use(morgan('dev'))
app.get('/health', (_req, res) => res.json({ ok: true }))
app.use('/api/bookmarks', bookmarkRoutes)
app.use(errorHandler)

export default app

Zod Validation Middleware (src/middleware/validate.js)

Validate input at route boundaries and fail fast with useful errors.

export function validate(schema) {
  return (req, _res, next) => {
    const result = schema.safeParse(req.body)
    if (!result.success) {
      return next({ status: 400, message: result.error.issues[0].message })
    }
    req.body = result.data
    next()
  }
}

Bookmark Schema and Routes (src/routes/bookmarkRoutes.js)

Pair input schemas with route declarations for predictable endpoint behavior.

import { Router } from 'express'
import * as controller from '../controllers/bookmarkController.js'
import { validate } from '../middleware/validate.js'
import { createBookmarkSchema } from '../schemas/bookmarkSchemas.js'

const router = Router()
router.get('/', controller.listBookmarks)
router.post('/', validate(createBookmarkSchema), controller.createBookmark)
export default router

Controller + Service Pattern

Controllers stay HTTP-focused while services contain business rules.

// src/controllers/bookmarkController.js
import * as service from '../services/bookmarkService.js'

export async function listBookmarks(_req, res) {
  res.json(await service.list())
}

export async function createBookmark(req, res) {
  const created = await service.create(req.body)
  res.status(201).json(created)
}

Central Error Handler (src/middleware/errorHandler.js)

Use one error handler to enforce consistent response format across all routes.

export function errorHandler(err, _req, res, _next) {
  const status = err.status || 500
  const message = err.message || "Internal Server Error"
  res.status(status).json({ message })
}

Mini Project: API Key Middleware (src/middleware/apiKeyAuth.js)

Add lightweight auth to your learning API. This is a practical upgrade for personal tools.

export function apiKeyAuth(req, _res, next) {
  const provided = req.get('x-api-key')
  if (!provided || provided !== process.env.API_KEY) {
    return next({ status: 401, message: 'Unauthorized' })
  }
  next()
}

Integration Test with Supertest (tests/bookmarks.test.js)

Verify core route behavior quickly with real HTTP requests against your app object.

import request from 'supertest'
import app from '../src/app.js'

test('GET /health returns ok', async () => {
  await request(app).get('/health').expect(200, { ok: true })
})

Server Entrypoint (src/server.js)

Keep process startup separate from app configuration for easier testing.

import 'dotenv/config'
import app from './app.js'

const port = process.env.PORT || 3000
app.listen(port, () => {
  console.log(`API listening on http://localhost:${port}`)
})

Run Express API Locally

Use a server entrypoint and environment file to run your mini project consistently.

echo "API_KEY=dev-secret" > .env
node src/server.js
curl http://localhost:3000/health

Next Learning Upgrades

These upgrades turn your snippets into a production-ready Express baseline.

1. Add pagination and sorting query parameters.
2. Add request rate limiting middleware.
3. Add OpenAPI docs for API consumers.
4. Add database migrations and seeds.
5. Add CI checks for linting and tests.