Generate Swagger JSON API from NextJS Api Routes
If you enjoy working with next-swagger-doc, you will love next-validations: NextJS API Validations, support Zod, Yup, Fastest-Validator, Joi, and more
π Homepage
β¨ Demo
- Nextjs >= 9
- Node >= 18
This package reads your JSDoc-annotated source code on NextJS API route and generates an OpenAPI (Swagger) specification.
nextjs + swagger-jsdoc = next-swagger-doc
yarn add next-swagger-doc
To incorporate next-swagger-doc
with your Next.js 13 project, follow these steps. This setup will generate Swagger documentation for your API based on your code and provide a built-in Swagger UI for viewing the documentation.
Next, create a new file lib/swagger.ts
. This file uses the next-swagger-doc
library to create a Swagger specification based on the API routes in your Next.js project.
import { createSwaggerSpec } from "next-swagger-doc";
export const getApiDocs = async () => {
const spec = createSwaggerSpec({
apiFolder: "app/api", // define api folder under app folder
definition: {
openapi: "3.0.0",
info: {
title: "Next Swagger API Example",
version: "1.0",
},
components: {
securitySchemes: {
BearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
},
},
},
security: [],
},
});
return spec;
};
Generate a new file named app/api-doc/react-swagger.tsx
. In this file, create and export a React component that utilizes the swagger-ui-react
library to render the Swagger UI according to the provided specification.
For demonstration purposes, here is an example using swagger-ui-react
Feel free to employ any alternative swagger UI library, such as stoplightio/elements. I have added an example using this library in the example
folder.
'use client';
import SwaggerUI from 'swagger-ui-react';
import 'swagger-ui-react/swagger-ui.css';
type Props = {
spec: Record<string, any>,
};
function ReactSwagger({ spec }: Props) {
return <SwaggerUI spec={spec} />;
}
export default ReactSwagger;
Create a new file app/api-doc/page.tsx
. This page imports the Swagger spec and the Swagger UI component to display the Swagger documentation.
import { getApiDocs } from "@/lib/swagger";
import ReactSwagger from "./react-swagger";
export default async function IndexPage() {
const spec = await getApiDocs();
return (
<section className="container">
<ReactSwagger spec={spec} />
</section>
);
}
Lastly, add a Swagger comment to your API route in app/api/hello/route.ts
. This comment includes metadata about the API endpoint which will be read by next-swagger-doc
and included in the Swagger spec.
/**
* @swagger
* /api/hello:
* get:
* description: Returns the hello world
* responses:
* 200:
* description: Hello World!
*/
export async function GET(_request: Request) {
// Do whatever you want
return new Response('Hello World!', {
status: 200,
});
}
Now, navigate to localhost:3000/api-doc
(or wherever you host your Next.js application), and you should see the swagger UI.
yarn add next-swagger-doc swagger-ui-react
- Create an live swagger page, e.g:
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';
const SwaggerUI = dynamic<{
spec: any;
}>(import('swagger-ui-react'), { ssr: false });
function ApiDoc({ spec }: InferGetStaticPropsType<typeof getStaticProps>) {
return <SwaggerUI spec={spec} />;
}
export const getStaticProps: GetStaticProps = async () => {
const spec: Record<string, any> = createSwaggerSpec({
apiFolder: 'pages/api' // or 'src/pages/api',
definition: {
openapi: '3.0.0',
info: {
title: 'Next Swagger API Example',
version: '1.0',
},
},
});
return {
props: {
spec,
},
};
};
export default ApiDoc;
- Step 1: Create an api route on nextjs, e.g:
pages/api/doc.ts
import { withSwagger } from "next-swagger-doc";
const swaggerHandler = withSwagger({
definition: {
openapi: "3.0.0",
info: {
title: "NextJS Swagger",
version: "0.1.0",
},
},
apiFolder: "pages/api",
});
export default swaggerHandler();
- Step 2: Add JSdoc to any NextJS API routes, for example:
pages/api/hello.ts
import { NextApiRequest, NextApiResponse } from "next";
/**
* @swagger
* /api/hello:
* get:
* description: Returns the hello world
* responses:
* 200:
* description: hello world
*/
const handler = (_req: NextApiRequest, res: NextApiResponse) => {
res.status(200).json({
result: "hello world",
});
};
export default handler;
- Step 3: Access the Swagger API doc
- Step 1: create a JSON config file as
next-swagger-doc.json
{
"apiFolder": "pages/api",
"schemaFolders": ["models"],
"definition": {
"openapi": "3.0.0",
"info": {
"title": "Next Swagger API Example",
"version": "1.0"
}
}
}
- Step 2: run cli for generating swagger file
yarn next-swagger-doc-cli next-swagger-doc.json
gh repo clone jellydn/next-swagger-doc
cd examples/next14-app
pnpm install
pnm run dev
Then open http://localhost:3000/api-doc or http://localhost:3000/ on your browser
In order to set an eslint rule that checks that all the APIs actually have a swagger JsDoc description we can use the following settings:
Install the JsDoc eslint plugin:
yarn add -D eslint-plugin-jsdoc
Create the custom rule in your eslint configuration file:
{
//...your configuration
"overrides": [
//...your overrides
{
// Force the setting of a swagger description on each api endpoint
"files": ["pages/api/**/*.ts"],
"plugins": ["jsdoc"],
"rules": {
"jsdoc/no-missing-syntax": [
"error",
{
"contexts": [
{
"comment": "JsdocBlock:has(JsdocTag[tag=swagger])",
"context": "any",
"message": "@swagger documentation is required on each API. Check this out for syntax info: https://github.com/jellydn/next-swagger-doc"
}
]
}
]
}
]
}
This project uses pre-commit to enforce code quality. To install pre-commit hooks, run:
pre-commit install
π€ Huynh Duc Dung
- Website: https://productsway.com/
- Twitter: @jellydn
- Github: @jellydn
Give a βοΈ if this project helped you!
Thanks goes to these wonderful people (emoji key):
Dung Duc Huynh (Kaka) π» π |
tmirkovic π |
Matthew Holloway π» |
leventemihaly π |
PAHRIZAL MA'RUP π» |
Aris π |
Valerio Ageno π |
cachho π» |
This project follows the all-contributors specification. Contributions of any kind welcome!