How We Implemented Swagger API Documentation in Our Node.js Backend

Modern APIs are only as good as their documentation. At Bonnetid, we maintain a fairly large and evolving Admin API that powers mosque management, prayer times, jamaat schedules, media uploads, and user administration. Keeping documentation accurate, discoverable, and always in sync with the codebase was critical for us.

This post walks through how we implemented Swagger (OpenAPI) documentation in our Node.js + Express backend, why we structured it the way we did, and how it scales as our API grows.

Why Swagger?

We chose Swagger (OpenAPI 3.0) because it gives us:

  • Living documentation generated directly from code
  • Built-in support for JWT authentication
  • A UI to test APIs instantly
  • A structured schema system reusable across endpoints
  • Zero duplication between implementation and documentation

Most importantly, Swagger allows our frontend, mobile, and partner teams to work independently without constantly asking for API details.

High-Level Architecture

Our Swagger setup is intentionally decoupled from business logic:

  • Swagger configuration lives in one place (swagger.js)
  • Route-level documentation lives next to the routes themselves
  • Schemas are reusable across all endpoints
  • Security rules match our real middleware behavior

This keeps things clean, predictable, and scalable.

Integrating Swagger into the Express Server

We expose Swagger as a public, read-only endpoint at /api-docs.

Server-level integration

In our main server file, Swagger is mounted just like any other Express middleware:

Why this matters?

  • The documentation is always available
  • Authorization tokens persist between requests
  • We hide unnecessary UI elements for a cleaner look
  • Works seamlessly in both development and production
Centralized Swagger Configuration

All OpenAPI configuration lives in a single file: swagger.js.

OpenAPI definition

This ensures every endpoint automatically inherits:

  • API metadata
  • Versioning
  • Description
  • Environment-specific server URLs

Environment-Aware Server URLs

Swagger automatically points to the correct API base URL depending on the environment:

This allows developers to test APIs locally or in staging without changing anything.

JWT Authentication with Bearer Tokens

Since our platform uses Supabase authentication, all protected endpoints require a JWT. We define this once:

And then reference it per route:

Swagger UI automatically shows the Authorize button, allowing developers to paste a token and test protected endpoints instantly.

Reusable Data Schemas

One of the biggest advantages of Swagger is schema reuse.

We define complex models once, such as:

  • Mosque
  • JamaatPeriod
  • Prayertime
  • AdhanAudio
  • HijriDates
  • User

These schemas are then referenced across multiple endpoints using $ref, keeping documentation consistent and DRY.

Route-Level Documentation (Where Swagger Really Shines)

Instead of maintaining a separate documentation file, we document APIs right above the routes.

Benefits of this approach
  • Documentation lives next to the code
  • Changes to routes naturally update docs
  • Impossible for docs to drift out of sync
  • Easy for new developers to understand APIs

Handling Permissions & Roles Transparently

Our backend enforces permissions using middleware such as:

Swagger reflects this accurately by:

  • Marking secured endpoints
  • Grouping APIs by feature (tags)

This ensures the documentation matches real access control, not an idealized version.

Feature-Based API Grouping

Swagger automatically groups endpoints using tags like:

  • Jamaat
  • Mosque
  • Users
  • Prayertime
  • Adhan Audio
  • Hijri Calendar

This mirrors our folder structure and makes navigation intuitive even as the API grows.

Results & Impact

By integrating Swagger this way, we achieved:

  • Reduced onboarding time for developers
  • Always up-to-date documentation
  • Faster debugging and testing
  • Better collaboration across teams
  • Confidence while shipping new features

Swagger is now a first-class citizen in our backend architecture—not an afterthought.

Final Thoughts

Good documentation is not something you write after building an API—it’s something you build into the API itself.

By combining Express, Swagger JSDoc, and disciplined structure, we created documentation that evolves naturally with our codebase and scales with our product.

If you’re building a serious API, Swagger isn’t optional—it’s infrastructure.

Scroll to Top