Skip to main content

Swagger System

The template provides a complete Swagger/OpenAPI documentation system built on swagger-jsdoc. It includes annotation helpers in lib/swagger/annotations.ts for standardizing API documentation across all route handlers.

Architecture

Annotation Type System

The lib/swagger/annotations.ts module defines TypeScript interfaces that mirror the OpenAPI 3.0 specification:

SwaggerRouteConfig

The main configuration object for documenting an API route:

interface SwaggerRouteConfig {
tags: string[]; // API grouping tags
summary: string; // Brief description
description: string; // Detailed description
security?: Array<Record<string, string[]>>; // Security requirements
parameters?: SwaggerParameter[]; // Query/path/header params
requestBody?: SwaggerRequestBody; // Request body schema
responses: Record<string, SwaggerResponse>; // Response definitions
}

SwaggerParameter

Defines query, path, or header parameters:

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;
}

SwaggerRequestBody

Defines the request body structure:

interface SwaggerRequestBody {
required: boolean;
content: {
'application/json': {
schema: {
$ref?: string; // Reference to a component schema
type?: string; // Inline type definition
properties?: Record<string, any>;
};
example?: any;
};
};
}

SwaggerResponse

Defines response status codes and their schemas:

interface SwaggerResponse {
description: string;
content?: {
'application/json': {
schema: {
$ref?: string;
type?: string;
properties?: Record<string, any>;
};
example?: any;
examples?: Record<string, any>;
};
};
}

Common Annotations

The CommonAnnotations object provides reusable building blocks:

Standard Error Responses

CommonAnnotations.responses.unauthorized
// { description: 'Authentication required', ... }

CommonAnnotations.responses.forbidden
// { description: 'Forbidden - Admin access required', ... }

CommonAnnotations.responses.notFound
// { description: 'Resource not found', ... }

CommonAnnotations.responses.serverError
// { description: 'Internal server error', ... }

Each error response includes a standard example:

{
"success": false,
"error": "Error message"
}

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: [] }]

Creating Annotations

createSwaggerAnnotation()

Generates a complete @swagger JSDoc comment string:

import { createSwaggerAnnotation, CommonAnnotations } from '@/lib/swagger/annotations';

const annotation = createSwaggerAnnotation('/api/items', 'GET', {
tags: ['Items'],
summary: 'List all items',
description: 'Returns a paginated list of items with filtering support',
parameters: [
...CommonAnnotations.paginationParameters,
{
name: 'category',
in: 'query',
required: false,
schema: { type: 'string' },
description: 'Filter by category',
example: 'Web Development'
}
],
responses: {
'200': {
description: 'Paginated list of items',
content: {
'application/json': {
schema: { $ref: '#/components/schemas/Pagination' },
example: {
items: [{ id: '1', title: 'Sample Item' }],
pagination: { page: 1, pageSize: 10, total: 50, totalPages: 5 }
}
}
}
},
'500': CommonAnnotations.responses.serverError
}
});

createAdminRouteAnnotation()

Shorthand for admin-protected routes. Automatically adds sessionAuth security:

import { createAdminRouteAnnotation, CommonAnnotations } from '@/lib/swagger/annotations';

const annotation = createAdminRouteAnnotation('/api/admin/users', 'GET', {
tags: ['Admin'],
summary: 'List all users',
description: 'Returns all registered users with their profiles and roles',
parameters: CommonAnnotations.paginationParameters,
responses: {
'200': {
description: 'User list with pagination',
content: {
'application/json': {
schema: { type: 'object' },
example: {
items: [{ id: '1', email: 'admin@example.com', role: 'admin' }],
pagination: { page: 1, pageSize: 10, total: 100, totalPages: 10 }
}
}
}
},
'401': CommonAnnotations.responses.unauthorized,
'403': CommonAnnotations.responses.forbidden,
'500': CommonAnnotations.responses.serverError
}
});

Writing Route Documentation

Direct Annotation Pattern

The most common approach is writing @swagger comments directly in route files:

// app/api/items/route.ts

/**
* @swagger
* /api/items:
* get:
* tags: ["Items"]
* summary: "Get all items"
* description: "Returns paginated items list with optional category filter"
* parameters:
* - name: "page"
* in: query
* schema:
* type: integer
* default: 1
* - name: "limit"
* in: query
* schema:
* type: integer
* default: 10
* responses:
* 200:
* description: "Success"
* 500:
* description: "Server error"
*/
export async function GET(request: Request) {
// implementation
}

POST Route with Request Body

/**
* @swagger
* /api/items:
* post:
* tags: ["Items"]
* summary: "Create a new item"
* security:
* - sessionAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* title:
* type: string
* description:
* type: string
* category:
* type: string
* example:
* title: "My New Item"
* description: "Item description"
* category: "Web Development"
* responses:
* 201:
* description: "Item created"
* 400:
* description: "Validation error"
* 401:
* description: "Unauthorized"
*/
export async function POST(request: Request) {
// implementation
}

Tag Organization

Organize API routes into logical groups using tags:

TagRoutesDescription
Items/api/items/*Public item listing and details
Admin/api/admin/*Admin dashboard operations
Auth/api/auth/*Authentication flows
Profile/api/profile/*User profile management
Newsletter/api/newsletter/*Newsletter subscriptions
Comments/api/comments/*Comment CRUD operations
Payments/api/payments/*Payment processing
Cron/api/cron/*Scheduled job endpoints

Security Schemes

Three security schemes are defined in the OpenAPI configuration:

Usage in Annotations

# JWT Bearer authentication
security:
- sessionAuth: []

# Cookie-based session
security:
- session: []

# Cron job secret
security:
- cronSecret: []

Generated Output

The generate-openapi.ts script produces public/openapi.json with this structure:

{
"openapi": "3.0.0",
"info": { "title": "Ever Works API", "version": "1.0.0" },
"servers": [{ "url": "/" }],
"paths": {
"/api/items": { "get": { ... }, "post": { ... } },
"/api/admin/users": { "get": { ... } }
},
"components": {
"securitySchemes": { ... },
"schemas": {
"ErrorResponse": { ... },
"PaginationMeta": { ... },
"Pagination": { ... }
}
},
"tags": [
{ "name": "Items" },
{ "name": "Admin" }
]
}

Best Practices

  1. Document every public route -- All routes in app/api/ should have @swagger annotations
  2. Use $ref for shared schemas -- Reference component schemas instead of duplicating definitions
  3. Include examples -- Always provide example values for request and response bodies
  4. Use CommonAnnotations -- Leverage the shared error responses and pagination parameters
  5. Tag consistently -- Group related endpoints under the same tag name
  6. Describe parameters -- Include description and example for every parameter
  7. Document all status codes -- Cover success, validation error, auth error, and server error cases
  8. Keep annotations close to handlers -- Place @swagger comments directly above the route handler function