gradient

Next Swagger doc

Daniel Wanja

Daniel Wanja / November 21, 2022

4 min read––– views

Next allows easily to create APIs. But how do you document them? In this post, I will show you how to use Swagger to document your Next.js APIs.

What is Swagger?

Swagger is an open-source software framework backed by a large ecosystem of tools that helps developers design, build, document, and consume RESTful web services. Swagger allows consumers to understand the capabilities of a remote service without access to source code, documentation, or through network traffic inspection. When properly defined via Swagger, a consumer can understand and interact with the remote service with a minimal amount of implementation logic.

Description provided by GitHub Copilot ;-)

Merging the Xhibiter and Lee's next-portfolio

Check them out here on this site: api-doc

How to use Swagger with Next.js

After a quick Google search I found the next-swagger-doc npm package, tried it and it worked like a charm. It's a simple package that allows you to easily add Swagger to your Next.js project. Let me know if you are using a different package or approach to document your APIs.

To install:

pnpm add next-swagger-doc swagger-ui-react

Then I create the api-doc page as follows:

pages/api-doc.tsx
import { GetStaticProps, InferGetStaticPropsType } from 'next';
import { createSwaggerSpec } from 'next-swagger-doc';
import dynamic from 'next/dynamic';
import 'swagger-ui-react/swagger-ui.css';
import Container from 'components/Container';

const SwaggerUI = dynamic<{
  spec: any;
}>(import('swagger-ui-react'), { ssr: false });

function ApiDoc({ spec }: InferGetStaticPropsType<typeof getStaticProps>) {
  return <SwaggerUI spec={spec} />; // <== 🔥 SwaggerUI is rendered here
}

export const getStaticProps: GetStaticProps = async () => {
  const spec: Record<string, any> = createSwaggerSpec({
    definition: {
      openapi: '3.0.0',
      info: {
        title: 'Swagger API Docs for https://n-so.com',
        version: '1.0'
      }
    }
  });

  return {
    props: {
      spec
    }
  };
};

export default ApiDoc;

This code scans your pages/api folder for the @swagger documentation and generates a Swagger spec file. Then it renders the Swagger UI using the swagger-ui-react package.

And that's it ¯\(ツ)

Well, you stil have to write the documention.

@swagger

To document your APIs, you can use the @swagger decorator before your API function. For example:

pages/api/views.ts
import type { NextApiRequest, NextApiResponse } from 'next';
import prisma from 'lib/prisma';

/**
 * @swagger
 * /api/views:
 *   get:
 *     description: Returns the view count of all blog posts.
 *     responses:
 *       200:
 *         description: A JSON object containing total view count of all blog posts.
 *         content:
 *           application/json:
 *             example:
 *               total: "74"
 *
 */
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  try {
    const totalViews = await prisma.views.aggregate({
      _sum: {
        count: true
      }
    });

    return res.status(200).json({ total: totalViews._sum.count.toString() });
  } catch (e) {
    return res.status(500).json({ message: e.message });
  }
}

The format of that documentation is similar to what one would write in the openapi.yaml file. You can find more information about the format here.

An easy way to generate the documentation is to use Postman:

  1. First add a collection with all the calls you want to document.
  2. Execute the call in postman and make sure to clck Save Response in the body tab.
  3. Export the collection which would save a file, for my example n-so.com.postman_collection.json.

Then you can use the postman-to-openapi package as follows

npm install -g postman-to-openapi
p2o n-so.com.postman_collection.json -f views.yml

This generates the following file (note I removed the response headers):

openapi: 3.0.0
info:
  title: n-so.com
  version: 1.0.0
servers:
  - url: https://n-so.com
paths:
  /api/views:
    get:
      tags:
        - default
      summary: https://n-so.com/api/views
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              example:
                total: '84'

You can then copy the content of the paths object and paste it in the @swagger decorator.

Enjoy!