Swagger API Documentation New
Available from
v1.3.0-beta
Arkos.js automatically generates comprehensive OpenAPI documentation for your API endpoints, providing interactive documentation that stays synchronized with your actual API behavior. The documentation system supports three different schema generation approaches and integrates seamlessly with your existing validation and query configurations.
Quick Start
Enable API documentation with minimal configuration:
// src/app.ts
import arkos from "arkos";
arkos.init({
swagger: {
mode: "prisma", // or "class-validator" or "zod"
options: {
definition: {
info: {
title: "My API",
version: "1.0.0",
description: "API documentation generated by Arkos.js",
},
},
},
},
});
Start your server and visit /api/docs
to see your generated API documentation.
Schema Generation Modes
Arkos offers three approaches to generate OpenAPI schemas, each with distinct advantages:
Prisma Mode: Live Schema Reflection
Best for: Rapid prototyping, APIs that closely mirror database structure
arkos.init({
swagger: {
mode: "prisma",
},
});
Prisma mode automatically generates schemas directly from your Prisma models and synchronizes with your Custom Prisma Query Options (also supported on another modes):
- Includes become schema properties: If
user.query.ts
containsinclude: { posts: true }
, the User response schema will include aposts
array - Selects limit schema fields: Only selected fields appear in documentation -
select: { id: true, name: true }
shows only those fields - Omits exclude from docs:
password: false
removes password from all generated schemas - Deep nesting respected: Complex nested selects and includes are fully reflected in schemas
Example with query options integration:
// src/modules/user/user.query.ts
import { PrismaQueryOptions } from "arkos/prisma";
import prisma from "../../utils/prisma";
export type UserDelegate = typeof prisma.user;
const userPrismaQueryOptions: PrismaQueryOptions<UserDelegate> = {
findMany: {
select: {
id: true,
name: true,
email: true,
posts: {
select: {
id: true,
title: true,
},
},
},
// password field automatically excluded from documentation
},
};
export default userPrismaQueryOptions;
The generated OpenAPI schema will show User responses with exactly these fields, ensuring documentation matches actual API behavior.
Class-Validator Mode: Decorator-Based Documentation
Best for: Projects using class-validator for validation, fine-grained control over schemas
arkos.init({
validation: {
resolver: "class-validator",
},
swagger: {
mode: "class-validator",
},
});
Uses your existing class-validator DTOs to generate schemas:
// src/modules/user/dtos/create-user.dto.ts
import { IsString, IsEmail, IsOptional } from "class-validator";
export default class CreateUserDto {
@IsString()
name: string;
@IsEmail()
email: string;
@IsOptional()
@IsString()
bio?: string;
}
The decorators automatically generate JSON Schema with validation rules included in the documentation.
Zod Mode: Schema-First Documentation
Best for: TypeScript-heavy projects, schema-first development, type safety
arkos.init({
validation: {
resolver: "zod",
},
swagger: {
mode: "zod",
},
});
Leverages Zod schemas for both validation and documentation:
// src/modules/user/schemas/create-user.schema.ts
import { z } from "zod";
const CreateUserSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
bio: z.string().optional(),
});
export default CreateUserSchema;
Provides excellent TypeScript integration and maintains a single source of truth for data structures.
Configuration Deep Dive
Essential Configuration
arkos.init({
swagger: {
endpoint: "/docs", // Documentation URL
mode: "prisma",
options: {
definition: {
openapi: "3.0.0",
info: {
title: "My API",
version: "1.0.0",
description: "Comprehensive API documentation",
},
servers: [
{
url: "http://localhost:8000",
description: "Development Server",
},
{
url: "https://api.myapp.com",
description: "Production Server",
},
],
},
},
},
});
Security Configuration
Add JWT authentication to your documentation:
Note that if authentication is enabled the JWT authentication is automatically added to the swagger documenation.
swagger: {
mode: "prisma",
options: {
definition: {
components: {
securitySchemes: {
BearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT"
},
ApiKeyAuth: {
type: "apiKey",
in: "header",
name: "X-API-Key"
}
}
},
security: [
{ BearerAuth: [] }
]
}
}
}
Scalar UI Customization
Customize the documentation interface:
swagger: {
mode: "prisma",
scalarApiReferenceConfiguration: {
theme: "deepSpace", // "default", "alternate", "deepSpace"
darkMode: true,
layout: "modern", // "classic", "modern"
showSidebar: true,
hideDownloadButton: false,
metaData: {
title: "My API Documentation",
description: "Interactive API documentation"
}
}
}
Arkos uses Scalar instead of traditional Swagger UI for several compelling reasons:
- Modern API Client Experience: Scalar provides an interface much closer to tools like Postman and Insomnia, making it immediately familiar to developers
- Superior Visual Design: Scalar offers a significantly more polished and beautiful interface compared to the dated Swagger UI aesthetic
- Better Developer Experience: Features like better syntax highlighting, improved request/response visualization, and more intuitive navigation
- Performance: Lighter weight and faster rendering compared to traditional Swagger UI
- Modern Tech Stack: Built with modern web technologies for better maintainability and extensibility
Learn more about Scalar's features and philosophy at scalar.com.
Customizing Generated Documentation
Override Auto-Generated Paths with JSDoc
Add custom documentation to your router files:
// src/modules/user/user.router.ts
import { Router } from "express";
import userController from "./user.controller";
const userRouter = Router();
/**
* @swagger
* /api/users/analytics:
* get:
* tags:
* - Users
* summary: Get user analytics
* description: Returns comprehensive analytics about user engagement and activity
* security:
* - BearerAuth: []
* parameters:
* - in: query
* name: period
* schema:
* type: string
* enum: [week, month, year]
* description: Analytics time period
* responses:
* 200:
* description: Analytics data retrieved successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* totalUsers:
* type: number
* activeUsers:
* type: number
* growthRate:
* type: number
* 401:
* description: Authentication required
*/
userRouter.get("/analytics", userController.getAnalytics);
export default userRouter;
Enhance Auto-Generated Endpoints
Override specific aspects of auto-generated documentation:
/**
* @swagger
* /api/users:
* post:
* summary: Create a new user account
* description: |
* Creates a new user with the provided information.
* Email addresses must be unique across the system.
* requestBody:
* description: User account information
* required: true
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/CreateUserDto'
* examples:
* standard:
* summary: Standard user creation
* value:
* name: "John Doe"
* email: "john@example.com"
* role: "user"
* admin:
* summary: Admin user creation
* value:
* name: "Jane Admin"
* email: "admin@example.com"
* role: "admin"
* responses:
* 201:
* description: User created successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UserDto'
* 409:
* description: Email address already exists
*/
Add Tags and Organization
Group your endpoints logically:
swagger: {
mode: "prisma",
options: {
definition: {
tags: [
{
name: "Authentication",
description: "User authentication and authorization"
},
{
name: "Users",
description: "User management operations"
},
{
name: "Posts",
description: "Blog post operations"
}
]
}
}
}
Advanced Schema Handling
Strict Mode Configuration
Control schema fallback behavior:
swagger: {
mode: "class-validator",
strict: true // Only use class-validator DTOs, no Prisma fallback
}
Strict mode behaviors:
strict: true
- Only uses the specified mode, no fallbacksstrict: false
(default) - Falls back to Prisma schemas when DTOs/schemas are missing
Mixed Schema Sources
When strict: false
, Arkos intelligently chooses schema sources:
- Custom DTOs/Schemas (if they exist)
- Prisma models (fallback)
- Auto-generated schemas (for missing pieces)
// This works even if you only define some DTOs
// Missing DTOs will be auto-generated from Prisma models
// src/modules/user/dtos/create-user.dto.ts - exists
// src/modules/user/dtos/update-user.dto.ts - missing (auto-generated)
Custom Component Schemas
Add reusable schema components:
swagger: {
mode: "prisma",
options: {
definition: {
components: {
schemas: {
ErrorResponse: {
type: "object",
properties: {
status: { type: "string", example: "error" },
message: { type: "string" },
code: { type: "number" },
errors: {
type: "array",
items: {
type: "object",
properties: {
field: { type: "string" },
message: { type: "string" }
}
}
}
}
},
PaginationMeta: {
type: "object",
properties: {
total: { type: "number" },
page: { type: "number" },
limit: { type: "number" },
totalPages: { type: "number" }
}
}
}
}
}
}
}
Live Schema Synchronization with Query Options
The most powerful feature of Arkos documentation is automatic synchronization with your Custom Prisma Query Options. This ensures your documentation always reflects actual API behavior.
How Synchronization Works
// src/modules/post/post.query.ts
import { PrismaQueryOptions } from "arkos/prisma";
import prisma from "../../utils/prisma";
export type PostDelegate = typeof prisma.post;
const postPrismaQueryOptions: PrismaQueryOptions<PostDelegate> = {
findMany: {
select: {
id: true,
title: true,
excerpt: true,
author: {
select: {
id: true,
name: true,
},
},
createdAt: true,
},
},
findOne: {
include: {
author: true,
comments: {
include: {
author: true,
},
},
tags: true,
},
},
};
export default postPrismaQueryOptions;
Generated documentation will show:
GET /api/posts
responses with only the selected fieldsGET /api/posts/{id}
responses with full author, comments, and tags included- Nested author information in comments
- No sensitive fields that were omitted
Complex Example: User Profile API
// src/modules/user/user.query.ts
import { PrismaQueryOptions } from "arkos/prisma";
import prisma from "../../utils/prisma";
export type UserDelegate = typeof prisma.user;
const userPrismaQueryOptions: PrismaQueryOptions<UserDelegate> = {
queryOptions: {
select: {
id: true,
name: true,
email: true,
createdAt: true,
// Automatically excludes password, resetToken, etc.
password: false,
resetToken: false,
},
},
findMany: {
include: {
profile: {
select: {
bio: true,
avatar: true,
},
},
_count: {
select: {
posts: true,
followers: true,
},
},
},
},
};
export default userPrismaQueryOptions;
Documentation automatically shows:
- User list includes profile bio, avatar, and post/follower counts
- Password and reset tokens never appear in any schema
- Response examples match actual API responses exactly
Production Considerations
Performance Optimization
swagger: {
mode: "prisma",
enableAfterBuild: false, // Disable in production builds
options: {
// Limit schema generation for large APIs
apis: [
"./src/routers/*.router.{ts,js}",
"./src/modules/user/*.router.{ts,js}",
// Only include specific modules for documentation
]
}
}
Security Best Practices
swagger: {
mode: "prisma",
enableAfterBuild: process.env.NODE_ENV !== "production",
options: {
definition: {
// Only show documentation in development
servers: process.env.NODE_ENV === "production"
? [{ url: "https://api.myapp.com" }]
: [{ url: "http://localhost:8000" }]
}
}
}
Environment-Specific Configuration
// src/app.ts
const isDevelopment = process.env.NODE_ENV === "development";
arkos.init({
swagger: isDevelopment
? {
mode: "prisma",
endpoint: "/docs",
options: {
definition: {
info: {
title: "My API - Development",
version: "1.0.0",
},
},
},
}
: undefined, // Completely disable in production
});
Troubleshooting & Common Issues
Schema Resolution Problems
Issue: Missing or incorrect schemas in documentation
Solutions:
- Check file naming conventions match exactly
- Verify export statements use
export default
- Ensure TypeScript compilation is working
// ✅ Correct
export default class CreateUserDto {}
// ❌ Incorrect
export class CreateUserDto {}
Performance Issues
Issue: Slow documentation generation
Solutions:
- Use
strict: true
to avoid Prisma model parsing - Limit
apis
configuration to essential files - Consider disabling in production environments
Missing Documentation for Custom Routes
Issue: Custom endpoints not appearing in documentation
Solution: Add JSDoc comments to your router files:
// src/modules/user/user.router.ts
/**
* @swagger
* components:
* schemas:
* UserStats:
* type: object
* properties:
* totalPosts:
* type: number
* averageRating:
* type: number
*/
/**
* @swagger
* /api/users/{id}/stats:
* get:
* summary: Get user statistics
* parameters:
* - name: id
* in: path
* required: true
* schema:
* type: string
* responses:
* 200:
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UserStats'
*/
userRouter.get("/:id/stats", userController.getStats);
Debug Schema Generation
Issue: Understanding why certain schemas are generated
Use the debug analysis (development only):
// Add to your development configuration
swagger: {
mode: "prisma",
// Enable debug logging in development
}
Check your console output for schema generation details and conflicts.
Best Practices
Documentation Strategy
- Start with Prisma mode for rapid development
- Migrate to class-validator/Zod as your API matures
- Use JSDoc overrides for complex endpoints
- Keep documentation close to code in router files
Schema Design
- Leverage query options for automatic synchronization
- Use consistent naming across DTOs and schemas
- Group related endpoints with meaningful tags
- Provide examples for complex request/response structures
Production Deployment
- Use environment-specific server configurations
- Secure sensitive endpoints with proper authentication schemes
- Monitor documentation size for large APIs
Team Collaboration
- Document custom endpoints immediately when creating them
- Review generated schemas match actual API behavior
- Update examples when API contracts change
- Use consistent description patterns across your team