Skip to main content

Automated API Documentation System

Ever Works includes an automated OpenAPI documentation system that generates comprehensive API docs from your code.

Overview​

The system provides:

  • πŸ“ Automated generation - From code annotations to OpenAPI spec
  • πŸ”„ Hybrid approach - Preserves manual docs, adds automated ones
  • 🎯 Type-safe - TypeScript integration
  • πŸ“Š Swagger UI - Interactive API explorer
  • πŸ”§ Hot reload - Auto-regenerates during development

Architecture​

Hybrid Approach​

  • βœ… Preserves existing public/openapi.json file
  • βœ… Adds @swagger annotations in route code
  • βœ… Merges both sources automatically
  • βœ… Generates complete and consistent OpenAPI file

Installation​

1. Install Dependencies​

# Run the installation script
./scripts/install-swagger-deps.sh

# Or manually with npm
npm install -D swagger-jsdoc @types/swagger-jsdoc tsx nodemon

2. Available Scripts​

# Generate documentation once
npm run generate-docs

# Watch mode for development (auto-regenerates)
npm run docs:watch

# Development with automatic generation
npm run dev

Usage​

Adding Annotations to Routes​

// app/api/example/route.ts
import { NextRequest, NextResponse } from 'next/server';

/**
* @swagger
* /api/example:
* get:
* tags: ["Example"]
* summary: "Get example data"
* description: "Returns example data from the API"
* responses:
* 200:
* description: "Success"
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* data:
* type: array
* items:
* type: string
*/
export async function GET() {
return NextResponse.json({ success: true, data: ["example"] });
}

Using Annotation Utilities​

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

/**
* @swagger
* /api/admin/users:
* get:
* tags: ["Admin"]
* summary: "Get all users"
* security:
* - bearerAuth: []
* responses:
* 200:
* description: "Success"
* 401:
* $ref: '#/components/responses/Unauthorized'
* 500:
* $ref: '#/components/responses/ServerError'
*/
export async function GET() {
// Implementation
}

Common Annotations​

The system provides reusable annotation components:

// lib/swagger/annotations.ts

export const CommonAnnotations = {
responses: {
unauthorized: {
description: "Unauthorized - Invalid or missing authentication",
content: {
"application/json": {
schema: {
type: "object",
properties: {
error: { type: "string", example: "Unauthorized" }
}
}
}
}
},
serverError: {
description: "Internal Server Error",
content: {
"application/json": {
schema: {
type: "object",
properties: {
error: { type: "string", example: "Internal server error" }
}
}
}
}
}
},

security: {
bearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT"
}
}
};

File Structure​

scripts/
β”œβ”€β”€ generate-openapi.ts # Main generation script
β”œβ”€β”€ tsconfig.json # TypeScript config for scripts
└── install-swagger-deps.sh # Dependencies installer

lib/swagger/
└── annotations.ts # Reusable annotation utilities

templates/
└── route-template.ts # Template for new routes

public/
└── openapi.json # Generated OpenAPI specification

Configuration​

OpenAPI Base Configuration​

// scripts/generate-openapi.ts
const swaggerDefinition = {
openapi: '3.0.0',
info: {
title: 'Ever Works API',
version: '1.0.0',
description: 'API documentation for Ever Works directory platform',
},
servers: [
{
url: 'http://localhost:3000',
description: 'Development server',
},
{
url: 'https://yourdomain.com',
description: 'Production server',
},
],
components: {
securitySchemes: {
bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
},
},
},
};

Swagger UI Configuration​

Access the interactive API documentation at:

  • Development: http://localhost:3000/api-docs
  • Production: https://yourdomain.com/api-docs

Best Practices​

1. Consistent Tagging​

Group related endpoints with tags:

/**
* @swagger
* /api/items:
* get:
* tags: ["Items"] // Use consistent tag names
*/

2. Detailed Descriptions​

Provide clear descriptions and examples:

/**
* @swagger
* /api/items/{id}:
* get:
* summary: "Get item by ID"
* description: "Retrieves a single item from the directory by its unique identifier"
* parameters:
* - name: id
* in: path
* required: true
* description: "Unique item identifier"
* schema:
* type: string
* example: "item-123"
*/

3. Schema Definitions​

Define reusable schemas in components:

/**
* @swagger
* components:
* schemas:
* Item:
* type: object
* required:
* - id
* - name
* properties:
* id:
* type: string
* example: "item-123"
* name:
* type: string
* example: "Example Item"
* description:
* type: string
* example: "Item description"
*/

4. Error Responses​

Document all possible error responses:

/**
* @swagger
* /api/items:
* post:
* responses:
* 201:
* description: "Item created successfully"
* 400:
* description: "Invalid request data"
* 401:
* description: "Unauthorized"
* 500:
* description: "Server error"
*/

Troubleshooting​

Documentation Not Generating​

Issue: OpenAPI file not updating

Solution: Check the generation script

# Run manually to see errors
npm run generate-docs

# Check for syntax errors in annotations

Swagger UI Not Loading​

Issue: API docs page shows error

Solution: Verify OpenAPI file is valid

# Validate OpenAPI spec
npx swagger-cli validate public/openapi.json

Annotations Not Detected​

Issue: Route annotations not appearing in docs

Solution: Ensure correct format

// βœ… Correct
/**
* @swagger
* /api/route:
* get:
* ...
*/

// ❌ Incorrect (missing @swagger tag)
/**
* /api/route:
* get:
* ...
*/

Advanced Features​

Request Body Schemas​

/**
* @swagger
* /api/items:
* post:
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - name
* properties:
* name:
* type: string
* description:
* type: string
*/

Authentication​

/**
* @swagger
* /api/admin/settings:
* get:
* security:
* - bearerAuth: []
* responses:
* 401:
* description: "Unauthorized"
*/

Query Parameters​

/**
* @swagger
* /api/items:
* get:
* parameters:
* - name: page
* in: query
* schema:
* type: integer
* default: 1
* - name: limit
* in: query
* schema:
* type: integer
* default: 10
*/

Next Steps​

Resources​