Skip to content
Ravi Agheda
← All writing

— 1 min read

How to integrate Swagger UI in your Node project with auto-generation

Generate interactive API docs from JSDoc comments in an Express app, instead of hand-writing and maintaining a separate OpenAPI spec.

  • Node.js
  • Swagger
  • API

Hand-writing an OpenAPI YAML file works, but it drifts from the actual routes the moment someone changes an endpoint and forgets to update the spec. swagger-jsdoc generates the spec from JSDoc comments sitting right next to the route handlers, so the docs live with the code.

1. Install the packages

npm install swagger-jsdoc swagger-ui-express

2. Configure swagger-jsdoc

// swagger.js
import swaggerJsdoc from "swagger-jsdoc";

export const swaggerSpec = swaggerJsdoc({
  definition: {
    openapi: "3.0.0",
    info: {
      title: "My API",
      version: "1.0.0",
    },
  },
  apis: ["./routes/*.js"], // files to scan for JSDoc annotations
});

3. Annotate a route

/**
 * @openapi
 * /users/{id}:
 *   get:
 *     summary: Get a user by ID
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: User found
 *       404:
 *         description: User not found
 */
router.get("/users/:id", getUserById);

4. Mount the UI

import swaggerUi from "swagger-ui-express";
import { swaggerSpec } from "./swagger.js";

app.use("/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));

Visit /docs and you get a full interactive Swagger UI — request/response schemas, a "Try it out" button, everything — generated straight from the comments above each route.

Notes

  • Keep the annotation next to the handler it describes, not in a separate file — that's the whole point of the auto-generation approach.
  • For shared schemas (a User object reused across several endpoints), define components.schemas once in the swaggerJsdoc config and reference it with $ref instead of repeating the shape everywhere.
  • Gate /docs behind auth or an environment check in production if the API surface itself is private.