Skip to content
Mike Reams

Try

Searches titles, summaries and topics across posts, work, diagrams, pages and the 47 Toolbox resources.

↑ ↓ move · Enter open · Esc close
← Blog

Post ·

Documenting a Next.js API With OpenAPI and Swagger UI

Serve an OpenAPI spec from a Next.js App Router route and render it with Swagger UI to get interactive API docs that stay in step with the code.

Next.js With Swagger 3 Setup

First written in 2022 while building the API for Creative Social; rewritten in 2026 for the current OpenAPI release and the Next.js App Router.

OpenAPI and Swagger, briefly

OpenAPI is a standard way to describe a REST API in YAML or JSON: its endpoints and operations, parameters and responses, authentication, and contact and license details. It used to be called the Swagger Specification.

Swagger is the family of open-source tools built around OpenAPI. The ones you'll reach for most:

Why describe your API this way

A spec is a contract that tools can read. With one in hand you can publish interactive docs, generate client SDKs and server stubs, import the API into testing tools, and review the design before anyone writes code. Design-first teams write the spec, then build to it.

The shape of a spec

Start with the OpenAPI version and some metadata, then describe each path. Everything is case-sensitive.

openapi: 3.1.0
info:
  title: Sample API
  description: Optional. CommonMark is allowed.
  version: 0.1.9
paths:
  /users:
    get:
      summary: List users
      responses:
        "200":
          description: A JSON array of user names
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string

Which version to target: 3.2.0 is the latest release (September 2025); 3.1 aligned schemas with JSON Schema; some tools still require 3.0. Use the newest version your whole tool chain supports — for most chains today, that's 3.1.

Serving the spec and docs from Next.js

With the App Router, keep the spec as a file in the repo, serve it from a route handler, and render Swagger UI on its own page.

// app/api/openapi/route.ts
import spec from "@/openapi.json";

export function GET() {
  return Response.json(spec);
}
// app/api-docs/page.tsx
"use client";
import SwaggerUI from "swagger-ui-react";
import "swagger-ui-react/swagger-ui.css";

export default function ApiDocs() {
  return <SwaggerUI url="/api/openapi" />;
}
  • swagger-ui-react is heavy and runs in the browser. Keep it on the docs page only, so it never loads with the rest of the app.
  • Hand-written or generated? A hand-written spec (design-first) reviews well. A spec generated from annotations in your route code, with a library such as next-swagger-doc (code-first), stays in step with the code. Pick one source of truth.
  • Public or not? If the API isn't public, protect the docs page and the spec route, or leave them out of production builds.