js

How to Build Self-Updating API Documentation with AdonisJS, Swagger, and TypeDoc

Learn to create living API docs using AdonisJS, Swagger, and TypeDoc that evolve with your code and reduce support overhead.

How to Build Self-Updating API Documentation with AdonisJS, Swagger, and TypeDoc

I was staring at a support ticket that made me sigh. A developer trying to use our API had spent three hours trying to figure out how to filter a product list. The endpoint was right there, but the documentation was a single, outdated line in a forgotten README file. That moment was a turning point. I realized that for an API to be truly successful, its documentation must be as robust and reliable as the code itself. It shouldn’t be an afterthought; it should be a core feature. This is why I want to show you how to build living, breathing documentation that grows with your application. Let’s build something that answers questions before they’re even asked.

Have you ever tried to use an API where the documentation felt like a ghost town—empty, silent, and slightly unnerving? I have. It’s frustrating. Good documentation is a sign of respect for the developers who will use your work. It’s the bridge between your brilliant code and the world. Today, we’ll construct that bridge using AdonisJS, combining the power of Swagger for external API consumers and TypeDoc for the internal team maintaining the codebase.

We start by setting up our project. The goal is to have two documentation streams generated automatically: one for the public REST API and another for the internal TypeScript code. First, create a new AdonisJS API project.

npm init adonisjs@latest api-docs-project -- --kit=api
cd api-docs-project

Next, we install the tools that will do the heavy lifting. We need Swagger for our REST endpoints and TypeDoc for our TypeScript source code.

npm install @adonisjs/swagger
npm install --save-dev typedoc

Now, let’s configure Swagger. Create a file called config/swagger.ts. This is where we define the look, feel, and information about our API. Think of it as the welcome sign and map for your API city.

import { SwaggerConfig } from '@ioc:Adonis/Addons/Swagger'

export default {
  uiEnabled: true,
  uiUrl: 'docs',
  specEnabled: true,
  specUrl: '/swagger.json',
  middleware: [],
  options: {
    definition: {
      openapi: '3.0.0',
      info: {
        title: 'My Production API',
        version: '1.0.0',
        description: 'The official interface for our services.',
      },
      servers: [
        { url: 'http://localhost:3333', description: 'Development' },
      ],
    },
    apis: ['app/**/*.ts', 'start/routes.ts'],
  },
} as SwaggerConfig

With the configuration ready, we need to register the Swagger provider. Open your .adonisrc.json file and add it to the providers array. This tells AdonisJS to load and use our Swagger setup.

{
  "providers": [
    "./providers/AppProvider",
    "@adonisjs/core",
    "@adonisjs/swagger"
  ]
}

The magic happens when we write our controllers. Instead of documenting in a separate file, we write the documentation as comments right above our methods. This keeps the docs and code in sync. Here’s how you might document a simple endpoint to fetch users.

/**
 * @swagger
 * /api/users:
 *   get:
 *     summary: Get a list of users
 *     description: Returns a paginated list of all registered users.
 *     responses:
 *       200:
 *         description: A list of users.
 */
public async index({ request, response }: HttpContextContract) {
  const users = await User.query().paginate(request.input('page', 1))
  return response.ok(users)
}

See how the @swagger comment block defines the endpoint? When you run your application, AdonisJS and the Swagger plugin will read these comments and build the interactive API documentation page automatically. Navigate to http://localhost:3333/docs, and you’ll see a fully interactive UI where you can test every endpoint.

But what about the code itself? The other half of the equation is documenting your TypeScript types, classes, and functions for your fellow developers. This is where TypeDoc comes in. It reads your TypeScript code and generates a clean website of your codebase structure. Create a typedoc.json file in your project root.

{
  "entryPoints": ["app"],
  "out": "docs/code",
  "exclude": ["**/node_modules/**", "**/*.spec.ts", "**/*.test.ts"]
}

Now, document a service class. Good internal documentation explains the “why,” not just the “what.”

/**
 * Handles the complex logic for processing and validating financial transactions.
 * This service ensures all monetary operations adhere to business rules before
 * they are committed to the database.
 */
export default class TransactionService {
  /**
   * Validates and creates a new transaction record.
   * @param payload - The raw transaction data from the API request.
   * @throws {ValidationException} If the payload fails business logic checks.
   * @returns The newly created and sanitized Transaction model instance.
   */
  public async create(payload: CreateTransactionDTO): Promise<Transaction> {
    // ... implementation logic
  }
}

To generate this internal documentation, you add a script to your package.json.

{
  "scripts": {
    "docs:code": "typedoc"
  }
}

Run npm run docs:code, and TypeDoc will create a docs/code folder with an HTML site detailing all your modules, classes, and methods. This becomes an invaluable reference for onboarding new team members.

How do you ensure this documentation never gets stale? The answer is automation. We integrate documentation generation into our development workflow. For instance, we can set up a Git hook to ensure the Swagger spec is updated before every commit. Or, better yet, we make it part of our Continuous Integration (CI) pipeline. Here’s a simple GitHub Actions workflow that builds and deploys our docs on every push to the main branch.

name: Deploy Documentation
on:
  push:
    branches: [ main ]
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
      - name: Install Dependencies
        run: npm ci
      - name: Generate API Docs
        run: npm run build
      - name: Generate Code Docs
        run: npm run docs:code
      - name: Deploy to Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs

This workflow does a few key things. It installs dependencies, builds the AdonisJS app (which generates the latest Swagger JSON), runs TypeDoc to generate the code documentation, and then publishes the entire docs folder to GitHub Pages. Now, your documentation is always up-to-date and publicly accessible with every release.

What’s the result of all this work? You end up with a self-documenting system. Your API consumers have a clear, interactive guide at https://your-api.com/docs. Your development team has a detailed code reference at https://your-company.github.io/repo/code. The support tickets about “how do I use this endpoint?” drop dramatically. New developers can understand the codebase in days instead of weeks. The documentation is no longer a chore; it’s a living part of the application that provides real value.

This approach transforms documentation from a static manual into a dynamic asset. It builds trust with your users and efficiency within your team. The initial setup takes a bit of time, but the long-term payoff in saved hours and reduced frustration is immense. Your future self—and every developer who interacts with your code—will thank you.

Did this guide help clarify the path to better API docs? If you found it useful, please share it with a colleague who might be battling outdated documentation. Have you tried a different approach that worked well? I’d love to hear about your experiences in the comments below. Let’s keep building tools that are a joy to use and a pleasure to maintain.


As a best-selling author, I invite you to explore my books on Amazon. Don’t forget to follow me on Medium and show your support. Thank you! Your support means the world!


101 Books

101 Books is an AI-driven publishing company co-founded by author Aarav Joshi. By leveraging advanced AI technology, we keep our publishing costs incredibly low—some books are priced as low as $4—making quality knowledge accessible to everyone.

Check out our book Golang Clean Code available on Amazon.

Stay tuned for updates and exciting news. When shopping for books, search for Aarav Joshi to find more of our titles. Use the provided link to enjoy special discounts!


📘 Checkout my latest ebook for free on my channel!
Be sure to like, share, comment, and subscribe to the channel!


Our Creations

Be sure to check out our creations:

Investor Central | Investor Central Spanish | Investor Central German | Smart Living | Epochs & Echoes | Puzzling Mysteries | Hindutva | Elite Dev | JS Schools


We are on Medium

Tech Koala Insights | Epochs & Echoes World | Investor Central Medium | Puzzling Mysteries Medium | Science & Epochs Medium | Modern Hindutva

Keywords: api documentation,adonisjs,swagger,typedoc,developer experience



Similar Posts
Blog Image
Build Scalable Event-Driven Microservices with Node.js, Kafka, and Docker: Complete Professional Guide

Learn to build scalable event-driven microservices with Node.js, Kafka & Docker. Master event sourcing, CQRS patterns & distributed systems architecture.

Blog Image
How to Secure Your Express.js API with Joi Validation Like a Pro

Learn how to protect your Node.js API using Joi and Express.js for clean, reliable, and secure data validation.

Blog Image
Build Type-Safe Event-Driven Architecture: TypeScript, RabbitMQ & Domain Events Tutorial

Learn to build scalable, type-safe event-driven architecture using TypeScript, RabbitMQ & domain events. Master CQRS, event sourcing & reliable messaging patterns.

Blog Image
Complete Guide to Next.js Prisma Integration: Build Type-Safe Full-Stack Applications in 2024

Learn to integrate Next.js with Prisma ORM for type-safe full-stack development. Build robust apps with seamless database management and TypeScript support.

Blog Image
How to Build Type-Safe Full-Stack Apps with Vue, Vite, and TypeORM

Eliminate frontend-backend bugs by sharing types across your stack using Vue, Vite, and TypeORM. Learn how to build safer apps faster.

Blog Image
Building Type-Safe Event-Driven Microservices with NestJS NATS and TypeScript Complete Guide

Learn to build robust event-driven microservices with NestJS, NATS & TypeScript. Master type-safe event schemas, distributed transactions & production monitoring.