Next REST Framework
Type-safe, self-documenting REST APIs for Next.js
Table of contents
Next REST Framework is an open-source, opinionated, lightweight, easy-to-use set of tools to build type-safe, self-documenting HTTP REST APIs with Next.js. Building OpenAPI specification-compliant REST APIs can be cumbersome and slow but Next REST Framework makes this easy with auto-generated OpenAPI documents and docs using TypeScript and object schemas.
This is a monorepo containing the following packages / projects:
- The primary
next-rest-framework
package
- An example application for live demo and local development
Lightweight, type-safe, easy to use
- Designed to work with TypeScript so that your requests and responses are strongly typed.
- Object-schema validation with Zod. The object schemas are automatically converted to JSON schema format for the auto-generated OpenAPI specification.
- Auto-generated and extensible
openapi.json
spec file from your business logic.
- Auto-generated Redoc and/or SwaggerUI documentation frontend.
- Works with Next.js Middleware and other server-side libraries, like NextAuth.js.
- Supports both Next.js App Router and Pages Router, even at the same time.
- Fully customizable and compatible with any existing Next.js project.
npm install --save next-rest-framework
To get access to the auto-generated documentation, initialize the docs endpoint somewhere in your codebase. You can also skip this step if you don't want to expose a public API documentation.
App Router:
import { docsRouteHandler } from 'next-rest-framework';
export const GET = docsRouteHandler();
Pages Router:
import { docsApiRouteHandler } from 'next-rest-framework';
export default docsApiRouteHandler();
This is enough to get you started. Now you can access the API documentation in your browser. Calling this endpoint will automatically generate the openapi.json
OpenAPI specification file, located in the public
folder by default. You can also configure this endpoint to disable the automatic generation of the OpenAPI spec file or use the CLI command npx next-rest-framework generate
to generate it. You can also create multiple docs endpoints for various use cases. See the full configuration options of this endpoint in the Docs handler section.
App Router:
import { routeHandler, routeOperation } from 'next-rest-framework';
import { NextResponse } from 'next/server';
import { z } from 'zod';
const TODOS = [
{
id: 1,
name: 'TODO 1',
completed: false
}
];
const handler = routeHandler({
GET: routeOperation({
operationId: 'getTodos',
tags: ['example-api', 'todos', 'app-router']
})
.output([
{
status: 200,
contentType: 'application/json',
schema: z.array(
z.object({
id: z.number(),
name: z.string(),
completed: z.boolean()
})
)
}
])
.handler(() => {
return NextResponse.json(TODOS, {
status: 200
});
}),
POST: routeOperation({
operationId: 'createTodo',
tags: ['example-api', 'todos', 'app-router']
})
.input({
contentType: 'application/json',
body: z.object({
name: z.string()
})
})
.output([
{
status: 201,
contentType: 'application/json',
schema: z.string()
}
])
.handler(async (req) => {
const { name } = await req.json();
console.log('Strongly typed TODO name: ', name);
return NextResponse.json('New TODO created.', {
status: 201
});
})
});
export { handler as GET, handler as POST };
Pages Router:
import { apiRouteHandler, apiRouteOperation } from 'next-rest-framework';
import { z } from 'zod';
const TODOS = [
{
id: 1,
name: 'TODO 1',
completed: false
}
];
export default apiRouteHandler({
GET: apiRouteOperation({
operationId: 'getTodos',
tags: ['example-api', 'todos', 'pages-router']
})
.output([
{
status: 200,
contentType: 'application/json',
schema: z.array(
z.object({
id: z.number(),
name: z.string(),
completed: z.boolean()
})
)
}
])
.handler((req, res) => {
res.status(200).json(TODOS);
}),
POST: apiRouteOperation({
operationId: 'createTodo',
tags: ['example-api', 'todos', 'pages-router']
})
.input({
contentType: 'application/json',
body: z.object({
name: z.string()
})
})
.output([
{
status: 201,
contentType: 'application/json',
schema: z.string()
}
])
.handler((req, res) => {
const { name } = req.body;
console.log('Strongly typed TODO name: ', name);
res.status(201).json('New TODO created.');
})
});
These type-safe endpoints will be now auto-generated to your OpenAPI spec:

The following options can be passed to the docsRouteHandler
(App Router) and docsApiRouteHandler
(Pages Router) functions for customizing Next REST Framework:
deniedPaths | Array of paths that are denied by Next REST Framework and not included in the OpenAPI spec. Supports wildcards using asterisk * and double asterisk ** for recursive matching. Example: ['/api/disallowed-path', '/api/disallowed-path-2/*', '/api/disallowed-path-3/**'] Defaults to no paths being disallowed. |
allowedPaths | Array of paths that are allowed by Next REST Framework and included in the OpenAPI spec. Supports wildcards using asterisk * and double asterisk ** for recursive matching. Example: ['/api/allowed-path', '/api/allowed-path-2/*', '/api/allowed-path-3/**'] Defaults to all paths being allowed. |
openApiObject | An OpenAPI Object that can be used to override and extend the auto-generated specification. |
openApiJsonPath | Path that will be used for fetching the OpenAPI spec - defaults to /openapi.json . This path also determines the path where this file will be generated inside the public folder. |
autoGenerateOpenApiSpec | Setting this to false will not automatically update the generated OpenAPI spec when calling the Next REST Framework endpoint. Defaults to true . |
docsConfig | A Docs config object for customizing the generated docs. |
suppressInfo | Setting this to true will suppress all informational logs from Next REST Framework. Defaults to false . |
generatePathsTimeout | Timeout in milliseconds for generating the OpenAPI spec. Defaults to 5000. For large applications you might have to increase this. |
The docs config options can be used to customize the generated docs:
provider | Determines whether to render the docs using Redoc (redoc ) or SwaggerUI swagger-ui . Defaults to redoc . |
title | Custom title, used for the visible title and HTML title. |
description | Custom description, used for the visible description and HTML meta description. |
faviconUrl | Custom HTML meta favicon URL. |
logoUrl | A URL for a custom logo. |
The following options cam be passed to the routeHandler
(App Router) and apiRouteHandler
(Pages Router) functions to create new API endpoints:
GET | PUT | POST | DELETE | OPTIONS | HEAD | PATCH | A Method handler object. | true |
openApiPath | An OpenAPI Path Item Object that can be used to override and extend the auto-generated specification. | false |
The route operation functions routeOperation
(App Router) and apiRouteOperation
(Pages Router) allow you to define your API handlers for your endpoints. These functions accept an OpenAPI Operation object as a parameter, that can be used to override the auto-generated specification. Calling this function allows you to chain your API handler logic with the following functions.
input | An Input function for defining the validation and documentation of the request. |
output | An Output function for defining the validation and documentation of the response. |
handler | A Handler function for defining your business logic. |
The input function is used for validation and documentation of the request, taking in an object with the following properties:
contentType | The content type header of the request. When the content type is defined, a request with an incorrect content type header will get an error response. | false |
body | A Zod schema describing the format of the request body. | false |
query | A Zod schema describing the format of the query parameters. | false |
Calling the input function allows you to chain your API handler logic with the Output and Handler functions.
The output function is used for validation and documentation of the response, taking in an array of objects with the following properties:
status | A status code that your API can return. | true |
contentType | The content type header of the response. | true |
schema | A Zod schema describing the format of the response data. A response body not matching to the schema will lead to a TS error. | true |
Calling the input function allows you to chain your API handler logic with the Handler function.
The handler function is a strongly-typed function to implement the business logic for your API. The function takes in strongly-typed versions of the same parameters as the Next.js Route Handlers and API Routes handlers.
See the changelog in CHANGELOG.md
All contributions are welcome!
ISC, see full license in LICENSE.