Skip to main content
The Dev helper provides utilities for inspecting and visualizing your application’s routes during development. These tools help you understand your route structure, debug routing issues, and display route information.

Import

import { showRoutes, inspectRoutes, getRouterName } from 'hono/dev'

Display Routes

showRoutes

Print all registered routes to the console in a formatted table:
import { Hono } from 'hono'
import { showRoutes } from 'hono/dev'

const app = new Hono()

app.get('/', (c) => c.text('Home'))
app.get('/posts', (c) => c.json([]))
app.post('/posts', (c) => c.json({}))
app.get('/posts/:id', (c) => c.text('Post'))

showRoutes(app)
Output:
GET  /
GET  /posts
POST /posts
GET  /posts/:id
Parameters:
hono
Hono
required
The Hono application instance
options
ShowRoutesOptions
Optional configuration object

Options

options.verbose
boolean
default:"false"
When true, displays all middleware in addition to handlers
options.colorize
boolean
Enable or disable colored output. Auto-detects terminal support by default.

Verbose Mode

Show all middleware and handlers:
import { showRoutes } from 'hono/dev'

app.use('*', logger())
app.use('/api/*', authenticate)
app.get('/api/users', getUsers)

showRoutes(app, { verbose: true })
Output:
GET  /api/users
     logger
     authenticate
     getUsers

Colorization

Control colored output:
import { showRoutes } from 'hono/dev'

// Force colors on
showRoutes(app, { colorize: true })

// Force colors off
showRoutes(app, { colorize: false })

// Auto-detect (default)
showRoutes(app)

Inspect Routes

inspectRoutes

Get route information as a data structure for programmatic use:
import { inspectRoutes } from 'hono/dev'

const app = new Hono()

app.get('/', (c) => c.text('Home'))
app.post('/posts', (c) => c.json({}))

const routes = inspectRoutes(app)
console.log(routes)
Output:
[
  {
    path: '/',
    method: 'GET',
    name: '[handler]',
    isMiddleware: false
  },
  {
    path: '/posts',
    method: 'POST',
    name: '[handler]',
    isMiddleware: false
  }
]
Parameters:
hono
Hono
required
The Hono application instance
Returns: RouteData[] - Array of route information objects

RouteData Type

interface RouteData {
  path: string           // Route pattern (e.g., '/posts/:id')
  method: string         // HTTP method (e.g., 'GET', 'POST')
  name: string          // Handler or middleware name
  isMiddleware: boolean // Whether this is middleware or a handler
}

Get Router Name

getRouterName

Get the name of the router being used:
import { getRouterName } from 'hono/dev'

const app = new Hono()
const routerName = getRouterName(app)
console.log(routerName) // 'SmartRouter', 'RegExpRouter', 'TrieRouter', etc.
Parameters:
app
Hono
required
The Hono application instance
Returns: string - The name of the router implementation

Named Functions

Use named functions to get meaningful output:
import { showRoutes } from 'hono/dev'

const authenticateUser = (c, next) => {
  // Auth logic
  return next()
}

const getUsers = (c) => {
  return c.json({ users: [] })
}

app.use('/api/*', authenticateUser)
app.get('/api/users', getUsers)

showRoutes(app, { verbose: true })
Output:
GET  /api/users
     authenticateUser
     getUsers
Named functions provide better debugging information than anonymous functions. The helper will show [middleware] or [handler] for unnamed functions.

Use Cases

Startup Logging

Display routes when the server starts:
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import { showRoutes } from 'hono/dev'

const app = new Hono()

// Define routes...
app.get('/', (c) => c.text('Hello'))
app.get('/api/users', (c) => c.json([]))

if (process.env.NODE_ENV === 'development') {
  showRoutes(app)
}

serve(app)

Generate Documentation

Generate route documentation from your app:
import { inspectRoutes } from 'hono/dev'
import { writeFileSync } from 'fs'

const app = new Hono()

// Define routes...

const routes = inspectRoutes(app)
const markdown = routes
  .filter(r => !r.isMiddleware)
  .map(r => `- \`${r.method} ${r.path}\``)
  .join('\n')

writeFileSync('ROUTES.md', `# API Routes\n\n${markdown}`)

Testing Routes

Validate expected routes in tests:
import { inspectRoutes } from 'hono/dev'
import { describe, it, expect } from 'vitest'

describe('Routes', () => {
  it('should have all expected routes', () => {
    const routes = inspectRoutes(app)
    const paths = routes.map(r => `${r.method} ${r.path}`)
    
    expect(paths).toContain('GET /')
    expect(paths).toContain('GET /api/users')
    expect(paths).toContain('POST /api/users')
  })
})

Route Comparison

Compare routes between different configurations:
import { inspectRoutes } from 'hono/dev'

const appV1 = new Hono()
const appV2 = new Hono()

// Define routes for each version...

const routesV1 = inspectRoutes(appV1).map(r => `${r.method} ${r.path}`)
const routesV2 = inspectRoutes(appV2).map(r => `${r.method} ${r.path}`)

const newRoutes = routesV2.filter(r => !routesV1.includes(r))
const removedRoutes = routesV1.filter(r => !routesV2.includes(r))

console.log('New routes:', newRoutes)
console.log('Removed routes:', removedRoutes)

Debug Middleware Order

Visualize middleware execution order:
import { showRoutes } from 'hono/dev'

const requestId = (c, next) => {
  c.set('requestId', crypto.randomUUID())
  return next()
}

const logger = (c, next) => {
  console.log(`${c.get('requestId')}: ${c.req.method} ${c.req.path}`)
  return next()
}

app.use('*', requestId)
app.use('*', logger)
app.use('/admin/*', authenticate)
app.get('/admin/users', getUsers)

showRoutes(app, { verbose: true })
Output:
GET  /admin/users
     requestId
     logger
     authenticate
     getUsers

Router Detection

Identify which router implementation is being used:
import { getRouterName } from 'hono/dev'

const app = new Hono()
const router = getRouterName(app)

console.log(`Using ${router} for routing`)

if (router === 'RegExpRouter') {
  console.log('Consider using SmartRouter for better performance')
}

Filtering Routes

Filter routes programmatically:
import { inspectRoutes } from 'hono/dev'

const routes = inspectRoutes(app)

// Get only API routes
const apiRoutes = routes.filter(r => r.path.startsWith('/api/'))

// Get only POST routes
const postRoutes = routes.filter(r => r.method === 'POST')

// Get only handlers (no middleware)
const handlers = routes.filter(r => !r.isMiddleware)

console.log('API Routes:', apiRoutes.length)
console.log('POST Routes:', postRoutes.length)
console.log('Handlers:', handlers.length)

Type Definitions

interface ShowRoutesOptions {
  verbose?: boolean
  colorize?: boolean
}

interface RouteData {
  path: string
  method: string
  name: string
  isMiddleware: boolean
}

function showRoutes<E extends Env>(
  hono: Hono<E>,
  opts?: ShowRoutesOptions
): void

function inspectRoutes<E extends Env>(
  hono: Hono<E>
): RouteData[]

function getRouterName<E extends Env>(
  app: Hono<E>
): string

Best Practices

Development Only

Use these utilities in development only. Avoid in production for performance.

Named Functions

Use named functions for better debugging and route inspection output

Verbose for Debug

Enable verbose mode when debugging middleware order or execution flow

Test Route Coverage

Use inspectRoutes in tests to validate expected routes are registered
These helpers are intended for development and debugging. Avoid using them in production code as they may impact performance.
The showRoutes function automatically detects color support in your terminal. You can override this with the colorize option.

Build docs developers (and LLMs) love