Swagger Annotations
The template includes a utility module for generating standardized OpenAPI/Swagger JSDoc annotations for Next.js App Router API routes. This system avoids duplication of common response schemas and parameters.
File Structure
lib/swagger/
annotations.ts # Annotation types, generator functions, common templates
Core Types
Route Configuration
export interface SwaggerRouteConfig {
tags: string[];
summary: string;
description: string;
security?: Array<Record<string, string[]>>;
parameters?: SwaggerParameter[];
requestBody?: SwaggerRequestBody;
responses: Record<string, SwaggerResponse>;
}
Parameters
export interface SwaggerParameter {
name: string;
in: 'query' | 'path' | 'header';
required?: boolean;
schema: {
type: string;
format?: string;
minimum?: number;
maximum?: number;
default?: any;
enum?: string[];
};
description?: string;
example?: any;
}
Request Body
export interface SwaggerRequestBody {
required: boolean;
content: {
'application/json': {
schema: {
$ref?: string;
type?: string;
properties?: Record<string, any>;
};
example?: any;
};
};
}
Response
export interface SwaggerResponse {
description: string;
content?: {
'application/json': {
schema: {
$ref?: string;
type?: string;
properties?: Record<string, any>;
};
example?: any;
examples?: Record<string, any>;
};
};
}
Generating Annotations
createSwaggerAnnotation
Generates a complete JSDoc Swagger annotation string from a configuration object:
import { createSwaggerAnnotation } from '@/lib/swagger/annotations';
const annotation = createSwaggerAnnotation('/api/items', 'get', {
tags: ['Items'],
summary: 'List all items',
description: 'Returns a paginated list of items',
parameters: [
{
name: 'page',
in: 'query',
schema: { type: 'integer', minimum: 1, default: 1 },
description: 'Page number',
},
{
name: 'limit',
in: 'query',
schema: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
description: 'Items per page',
},
],
responses: {
'200': {
description: 'Successful response',
content: {
'application/json': {
schema: { type: 'object' },
example: { success: true, data: [], meta: { page: 1, total: 100 } },
},
},
},
'500': {
description: 'Server error',
content: {
'application/json': {
schema: { $ref: '#/components/schemas/ErrorResponse' },
},
},
},
},
});
createAdminRouteAnnotation
A shorthand for admin-only routes that automatically adds sessionAuth security:
import { createAdminRouteAnnotation } from '@/lib/swagger/annotations';
const annotation = createAdminRouteAnnotation('/api/admin/users', 'get', {
tags: ['Admin', 'Users'],
summary: 'List all users',
description: 'Admin endpoint to list all registered users',
parameters: CommonAnnotations.paginationParameters,
responses: {
'200': { description: 'List of users' },
'401': CommonAnnotations.responses.unauthorized,
'403': CommonAnnotations.responses.forbidden,
},
});
Common Annotations
The CommonAnnotations object provides reusable response templates and parameters:
Standard Error Responses
CommonAnnotations.responses.unauthorized
// => { description: 'Authentication required', content: { ... } }
CommonAnnotations.responses.forbidden
// => { description: 'Forbidden - Admin access required', content: { ... } }
CommonAnnotations.responses.notFound
// => { description: 'Resource not found', content: { ... } }
CommonAnnotations.responses.serverError
// => { description: 'Internal server error', content: { ... } }
Each response includes an example body:
{ "success": false, "error": "Unauthorized" }
Pagination Parameters
CommonAnnotations.paginationParameters
// => [
// { name: 'page', in: 'query', schema: { type: 'integer', minimum: 1, default: 1 }, ... },
// { name: 'limit', in: 'query', schema: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, ... },
// ]
Admin Security
CommonAnnotations.adminSecurity
// => [{ sessionAuth: [] }]
Usage in API Routes
Annotations are placed as JSDoc comments above route handler exports. The Swagger generator processes these during build to produce the OpenAPI spec:
// app/api/items/route.ts
/**
* @swagger
* /api/items:
* get:
* tags: ["Items"]
* summary: "List all items"
* description: "Returns a paginated list of items"
* parameters:
* - name: "page"
* in: query
* required: false
* schema:
* type: integer
* minimum: 1
* default: 1
* description: "Page number for pagination"
* responses:
* 200:
* description: "Successful response"
* 500:
* description: "Internal server error"
*/
export async function GET(request: Request) {
// handler implementation
}
Building Custom Annotations
Combine common templates with route-specific configuration:
import { createSwaggerAnnotation, CommonAnnotations } from '@/lib/swagger/annotations';
const itemCreateAnnotation = createSwaggerAnnotation('/api/items', 'post', {
tags: ['Items'],
summary: 'Create a new item',
description: 'Creates a new item submission',
security: CommonAnnotations.adminSecurity,
requestBody: {
required: true,
content: {
'application/json': {
schema: { $ref: '#/components/schemas/CreateItemInput' },
example: {
name: 'My Tool',
description: 'A great tool for developers',
source_url: 'https://example.com',
},
},
},
},
responses: {
'201': {
description: 'Item created successfully',
content: {
'application/json': {
schema: { type: 'object' },
example: { success: true, data: { id: '...', slug: 'my-tool' } },
},
},
},
'400': {
description: 'Validation error',
content: {
'application/json': {
schema: { $ref: '#/components/schemas/ErrorResponse' },
example: { success: false, error: 'Name is required' },
},
},
},
'401': CommonAnnotations.responses.unauthorized,
'500': CommonAnnotations.responses.serverError,
},
});
Related Files
lib/swagger/annotations.ts- Annotation types, generators, and common templatesapp/api/- API route handlers that use the annotations