npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

hono-swagger-ui

v1.0.5

Published

Automatic Swagger UI middleware for Hono applications

Downloads

39

Readme

Hono Swagger UI 📚

npm version npm downloads license

Automatic Swagger/OpenAPI documentation middleware for Hono applications. Generate beautiful, interactive API documentation with zero configuration and automatic route discovery!

🎯 TL;DR

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app, { title: 'My API' });
app.use('*', swaggerUI.init());

app.get('/users/:id', (c) => c.json({ id: c.req.param('id') }));

// Visit /swagger-ui for interactive docs! 🚀

3 lines of code = Complete API documentation with interactive testing!

✨ Features

  • 🚀 Zero Configuration - Works out of the box with your existing Hono routes
  • 🔍 Auto-Scanning - Automatically detects and documents all Hono routers
  • 📖 Auto-Documentation - Automatically detects and documents your API routes
  • 👀 File Watching - Real-time documentation updates when files change
  • 🎨 Beautiful UI - Integrates Swagger UI for interactive documentation
  • 🔍 Zod Integration - Full support for @hono/zod-validator schemas
  • 🏷️ Custom Tags - Organize your endpoints with custom tags and descriptions
  • 🔧 Flexible Configuration - Customize everything from route paths to API info
  • 📱 Mobile Friendly - Responsive documentation that works on all devices
  • 🎯 TypeScript - Full TypeScript support with type safety

🚀 Quick Start

Installation

npm install hono-swagger-ui
# or
yarn add hono-swagger-ui
# or
pnpm add hono-swagger-ui

Simple Example

Here's a complete working example:

// app.ts
import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();

// Initialize swagger middleware
const swaggerUI = swagger(app, {
  title: 'My API',
  version: '1.0.0',
  description: 'A simple API example'
});

// Apply the swagger middleware
app.use('*', swaggerUI.init());

// Define your routes (these will be automatically documented)
app.get('/', (c) => {
  return c.json({ message: 'Hello World!' });
});

app.get('/users/:id', (c) => {
  const id = c.req.param('id');
  return c.json({ id, name: 'John Doe', email: '[email protected]' });
});

app.post('/users', async (c) => {
  const body = await c.req.json();
  return c.json({ id: '123', ...body }, 201);
});

// Start the server
const port = 3000;
console.log(`🚀 Server running on http://localhost:${port}`);
console.log(`📚 Swagger UI: http://localhost:${port}/swagger-ui`);

export default {
  port,
  fetch: app.fetch,
};

Run the Example

# Install dependencies
npm install hono hono-swagger-ui

# Run with Bun
bun run app.ts

# Or with Node.js
npx tsx app.ts

Visit http://localhost:3000/swagger-ui to see your interactive API documentation!

💡 Want to try it right now? Copy the simple-example.ts file and run it with bun run simple-example.ts!

Basic Usage with Auto-Scanning

For larger applications with multiple routers:

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();

// Initialize swagger
const swaggerUI = swagger(app, {
  title: 'My API',
  version: '1.0.0'
});

// Apply middleware
app.use('*', swaggerUI.init());

// Your existing routes work automatically!
app.get('/users/:id', (c) => {
  return c.json({ id: c.req.param('id'), name: 'John' });
});

// Enable auto-scanning for automatic route discovery
await swaggerUI.enableAutoScan('./src');

export default app;

Auto-Scanning with Routers

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

// Create routers (auto-detected)
const usersRouter = new Hono();
const authRouter = new Hono();

usersRouter.get('/', (c) => c.json({ users: [] }));
usersRouter.get('/:id', (c) => c.json({ id: c.req.param('id') }));

authRouter.post('/login', (c) => c.json({ token: 'abc123' }));

const app = new Hono();
const swaggerUI = swagger(app, { title: 'My API' });
app.use('*', swaggerUI.init());

// Mount routes (no manual registration needed!)
app.route('/api/users', usersRouter);
app.route('/api/auth', authRouter);

// Enable auto-scanning
await swaggerUI.enableAutoScan('./src');

// Optionally enable file watching for real-time updates
await swaggerUI.enableFileWatching('./src');

Routes are automatically discovered and documented! 🚀

What You Get Out of the Box

With just a few lines of code, you get:

Interactive API Documentation - Beautiful Swagger UI interface
Automatic Route Detection - All your routes are documented automatically
Path Parameter Support - :id becomes {id} in the documentation
HTTP Method Support - GET, POST, PUT, DELETE all documented
Request/Response Examples - See your API in action
Try It Out - Test your endpoints directly from the UI
Mobile Responsive - Works on all devices

Quick Test

After running the example above, you can:

  1. View Documentation: Visit http://localhost:3000/swagger-ui
  2. Test Endpoints: Click "Try it out" on any endpoint
  3. See Parameters: Path parameters like :id are automatically documented
  4. Explore Responses: See example responses for each endpoint

📖 Documentation

🆕 Auto-Scanning Features

The new auto-scanning functionality automatically detects and documents all your Hono routers:

Router Detection

  • File System Scanning: Scans your src directory for Hono routers
  • Pattern Recognition: Detects new Hono() instances in TypeScript/JavaScript files
  • Route Extraction: Extracts all routes from discovered routers
  • Smart Path Generation: Automatically generates base paths from file structure

File Watching

  • Real-time Updates: Monitors file changes and updates documentation automatically
  • Debounced Scanning: Prevents excessive scanning during rapid file changes
  • Error Handling: Graceful error handling for file system issues

Usage

// Enable auto-scanning (scans once and registers all routes)
await swaggerUI.enableAutoScan('./src');

// Enable file watching (monitors for changes and updates automatically)
await swaggerUI.enableFileWatching('./src');

// Disable file watching when needed
swaggerUI.disableFileWatching();

File Structure

The scanner automatically generates paths from your file structure:

src/routes/users.ts     → /api/users
src/routes/auth.ts      → /api/auth
src/routes/admin.ts     → /api/admin

⚠️ Deprecation Notice

The registerSubApp method has been deprecated in favor of auto-scanning:

Before (Deprecated):

swaggerUI.registerSubApp('/api/users', usersRouter);
app.route('/api/users', usersRouter);

After (Recommended):

app.route('/api/users', usersRouter);
await swaggerUI.enableAutoScan('./src');

See DEPRECATION_NOTICE.md for detailed migration guide.

Configuration Options

interface SwaggerOptions {
  title?: string;           // API title (default: 'API Documentation')
  version?: string;         // API version (default: '1.0.0')
  description?: string;     // API description
  route?: string;          // Swagger UI route (default: '/swagger-ui')
  excludePaths?: string[]; // Paths to exclude from documentation
  info?: {
    title?: string;
    version?: string;
    description?: string;
    contact?: {
      name?: string;
      email?: string;
      url?: string;
    };
    license?: {
      name?: string;
      url?: string;
    };
  };
}

Advanced Usage

import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
import { swagger } from 'hono-swagger-ui';

// Create routers with enhanced documentation
const usersRouter = new Hono();
const authRouter = new Hono();

const UserSchema = z.object({
  id: z.string(),
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(120).optional()
});

// Enhanced route documentation with Zod validation
usersRouter.get('/:id',
  zValidator('param', z.object({ id: z.string() })),
  swaggerUI.documentRoute({
    tags: ['Users'],
    summary: 'Get user by ID',
    description: 'Retrieve a single user by their unique identifier'
  }),
  (c) => {
    const { id } = c.req.valid('param');
    return c.json({ id, name: 'John Doe', email: '[email protected]' });
  }
);

usersRouter.post('/',
  zValidator('json', UserSchema.omit({ id: true })),
  swaggerUI.documentRoute({
    tags: ['Users'],
    summary: 'Create user',
    description: 'Create a new user with the provided data'
  }),
  async (c) => {
    const userData = c.req.valid('json');
    return c.json({ id: '123', ...userData }, 201);
  }
);

authRouter.post('/login',
  zValidator('json', z.object({
    email: z.string().email(),
    password: z.string().min(6)
  })),
  swaggerUI.documentRoute({
    tags: ['Authentication'],
    summary: 'User login',
    description: 'Authenticate user and return access token'
  }),
  (c) => {
    return c.json({ token: 'abc123', expiresIn: 3600 });
  }
);

const app = new Hono();

const swaggerUI = swagger(app, {
  title: 'My Advanced API',
  version: '2.0.0',
  description: 'A comprehensive API with full documentation',
  route: '/docs', // Custom route
  excludePaths: ['/internal', '/health'], // Exclude internal routes
  info: {
    contact: {
      name: 'API Support',
      email: '[email protected]',
      url: 'https://example.com/support'
    },
    license: {
      name: 'MIT',
      url: 'https://opensource.org/licenses/MIT'
    }
  }
});

app.use('*', swaggerUI.init());

// Mount routes (auto-scanning will detect and document these)
app.route('/api/users', usersRouter);
app.route('/api/auth', authRouter);

// Enable auto-scanning and file watching
await swaggerUI.enableAutoScan('./src');
await swaggerUI.enableFileWatching('./src');

🎯 Benefits of Auto-Scanning

  • Zero Configuration: No need to manually register routes
  • Automatic Discovery: All routes are found automatically
  • Real-time Updates: Documentation updates when files change
  • No Missing Routes: Impossible to forget to document a route
  • Flexible Paths: Base paths generated from file structure
  • Less Code: No manual registration required
  • Better DX: Improved developer experience

Manual Route Documentation (Legacy)

For special cases, you can still manually add routes to documentation:

swaggerUI.addRoute({
  method: 'get',
  path: '/api/custom/{id}',
  parameters: [
    {
      name: 'id',
      in: 'path',
      required: true,
      schema: { type: 'string' }
    }
  ],
  responses: {
    '200': {
      description: 'Success',
      content: {
        'application/json': {
          schema: {
            type: 'object',
            properties: {
              id: { type: 'string' },
              data: { type: 'object' }
            }
          }
        }
      }
    }
  },
  tags: ['Custom'],
  summary: 'Custom endpoint'
});

Note: With auto-scanning, manual route documentation is rarely needed.

🔧 Integration Examples

Different Ways to Use

1. Simple Setup (Recommended for beginners)

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app, { title: 'My API' });
app.use('*', swaggerUI.init());

// Your routes here...
app.get('/hello', (c) => c.json({ message: 'Hello!' }));

export default app;

2. With Auto-Scanning (For larger apps)

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app, { title: 'My API' });
app.use('*', swaggerUI.init());

// Mount routers
app.route('/api/users', usersRouter);
app.route('/api/auth', authRouter);

// Auto-detect all routes
await swaggerUI.enableAutoScan('./src');

3. With File Watching (For development)

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app, { title: 'My API' });
app.use('*', swaggerUI.init());

// Auto-detect and watch for changes
await swaggerUI.enableAutoScan('./src');
await swaggerUI.enableFileWatching('./src');

With Bun

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app);
app.use('*', swaggerUI.init());

// Your routes...

export default {
  port: 3000,
  fetch: app.fetch,
};

With Node.js

import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app);
app.use('*', swaggerUI.init());

// Your routes...

const port = 3000;
console.log(`Server running at http://localhost:${port}/swagger-ui`);
serve({
  fetch: app.fetch,
  port
});

With Cloudflare Workers

import { Hono } from 'hono';
import { swagger } from 'hono-swagger-ui';

const app = new Hono();
const swaggerUI = swagger(app);
app.use('*', swaggerUI.init());

// Your routes...

export default app;

🎯 Zod Integration

The middleware automatically detects and converts Zod schemas to OpenAPI specifications:

import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(1, 'Name is required'),
  email: z.string().email('Invalid email format'),
  age: z.number().int().min(18, 'Must be 18 or older').optional(),
  role: z.enum(['user', 'admin']).default('user')
});

app.post('/users',
  zValidator('json', CreateUserSchema),
  (c) => {
    const user = c.req.valid('json');
    return c.json({ id: '123', ...user });
  }
);

This automatically generates proper OpenAPI schema with:

  • Required fields
  • Type validation
  • Format validation (email, etc.)
  • Min/max constraints
  • Enum values
  • Default values

🔧 Troubleshooting

Common Issues

Routes Not Showing Up?

  • Make sure you've applied the middleware: app.use('*', swaggerUI.init())
  • Check that your routes are defined after the middleware
  • For routers, use auto-scanning: await swaggerUI.enableAutoScan('./src')

Getting 404 on /swagger-ui?

  • Ensure the middleware is applied before your routes
  • Check that the route path is correct (default: /swagger-ui)
  • Verify the server is running

Auto-scanning Not Working?

  • Make sure the source path is correct: ./src
  • Check that your routers use new Hono()
  • Ensure files have .ts, .js, .tsx, or .jsx extensions

TypeScript Errors?

npm install @types/node typescript
# or
bun add -d @types/node typescript

Getting Help

🛠️ Development

# Clone the repository
git clone https://github.com/yourusername/hono-swagger-ui.git
cd hono-swagger-ui

# Install dependencies
npm install

# Build the package
npm run build

# Run tests
npm test

# Run example
cd example
npm install
npm run dev

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Development Guidelines

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Make your changes
  4. Add tests for your changes
  5. Ensure all tests pass (npm test)
  6. Commit your changes (git commit -m 'Add some AmazingFeature')
  7. Push to the branch (git push origin feature/AmazingFeature)
  8. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Hono - The ultrafast web framework
  • Swagger UI - Interactive API documentation
  • Zod - TypeScript-first schema validation

⚡ Performance

This middleware is designed to be lightweight and performant:

  • Routes are analyzed on-demand
  • OpenAPI spec is cached and generated once
  • Swagger UI assets are loaded from CDN
  • Minimal runtime overhead

🔒 Security

  • No sensitive information is exposed in documentation
  • Configurable path exclusions for internal routes
  • CORS headers properly handled
  • No eval() or unsafe operations

📊 Roadmap

  • [x] ✅ Auto-scanning router detection
  • [x] ✅ File watching for real-time updates
  • [x] ✅ Automatic route discovery
  • [x] ✅ Smart path generation
  • [ ] Enhanced Zod schema conversion
  • [ ] JSDoc comment parsing
  • [ ] Custom theme support
  • [ ] Authentication documentation
  • [ ] Response example generation
  • [ ] Postman collection export
  • [ ] Multiple API version support

📚 Additional Documentation


Made with ❤️ for the Hono community