Skip to main content
The Factory Helper provides utilities for creating type-safe Hono applications, middleware, and handlers with proper type inference.

Import

import { createFactory, createMiddleware } from 'hono/factory'
import { Factory } from 'hono/factory'

Functions

createFactory()

Creates a factory instance for creating type-safe Hono components.
function createFactory<E extends Env = Env, P extends string = string>(init?: {
  initApp?: InitApp<E>
  defaultAppOptions?: HonoOptions<E>
}): Factory<E, P>
init.initApp
(app: Hono<E>) => void
Optional function to initialize new app instances
init.defaultAppOptions
HonoOptions<E>
Default options for created apps
return
Factory<E, P>
A factory instance with methods for creating apps, middleware, and handlers
Example
import { createFactory } from 'hono/factory'

// Create a factory with environment types
type Env = {
  Bindings: {
    DB: Database
    API_KEY: string
  }
  Variables: {
    user: User
  }
}

const factory = createFactory<Env>()

createMiddleware()

Creates type-safe middleware without needing a factory instance.
function createMiddleware<
  E extends Env = any,
  P extends string = string,
  I extends Input = {},
  R extends HandlerResponse<any> | void = void
>(
  middleware: MiddlewareHandler<E, P, I, R extends void ? Response : R>
): MiddlewareHandler<E, P, I, R extends void ? Response : R>
middleware
MiddlewareHandler
required
The middleware handler function
return
MiddlewareHandler
The same middleware with proper type inference
Example
import { createMiddleware } from 'hono/factory'

const logger = createMiddleware(async (c, next) => {
  console.log(`[${c.req.method}] ${c.req.url}`)
  await next()
})

app.use(logger)

Factory Methods

factory.createApp()

Creates a new Hono application instance.
factory.createApp(options?: HonoOptions<E>): Hono<E>
options
HonoOptions<E>
Options for the Hono app (merged with default options)
return
Hono<E>
A new Hono application instance
Example
const factory = createFactory<Env>({
  initApp: (app) => {
    // Initialize all apps with common middleware
    app.use('*', logger())
  },
  defaultAppOptions: {
    strict: false
  }
})

const app = factory.createApp()
const apiApp = factory.createApp({ strict: true })

factory.createMiddleware()

Creates type-safe middleware with the factory’s environment types.
factory.createMiddleware<I extends Input = {}, R extends HandlerResponse<any> | void = void>(
  middleware: MiddlewareHandler<E, P, I, R extends void ? Response : R>
): MiddlewareHandler<E, P, I, R extends void ? Response : R>
middleware
MiddlewareHandler
required
The middleware handler function
return
MiddlewareHandler
Type-safe middleware
Example
type Env = {
  Bindings: {
    DB: Database
  }
  Variables: {
    user: User
  }
}

const factory = createFactory<Env>()

const authMiddleware = factory.createMiddleware(async (c, next) => {
  const token = c.req.header('Authorization')
  
  if (!token) {
    return c.text('Unauthorized', 401)
  }
  
  const user = await verifyToken(token, c.env.DB)
  c.set('user', user) // Type-safe: user must match Env.Variables.user
  
  await next()
})

app.use(authMiddleware)

factory.createHandlers()

Creates an array of type-safe handlers.
factory.createHandlers(...handlers: H[]): H[]
handlers
H[]
required
Variable number of handler functions
return
H[]
Array of handlers with proper type inference
Example
const factory = createFactory<Env>()

const handlers = factory.createHandlers(
  // Middleware
  async (c, next) => {
    console.log('Before')
    await next()
    console.log('After')
  },
  // Handler
  (c) => {
    const user = c.get('user') // Type-safe
    return c.json({ user })
  }
)

app.get('/profile', ...handlers)

Examples

Basic Factory Usage

import { createFactory } from 'hono/factory'
import type { User, Database } from './types'

type Env = {
  Bindings: {
    DB: Database
  }
  Variables: {
    user: User
  }
}

const factory = createFactory<Env>()

// Create middleware
const authMiddleware = factory.createMiddleware(async (c, next) => {
  const user = await authenticate(c.req.header('Authorization'))
  c.set('user', user)
  await next()
})

// Create handlers
const getUser = factory.createHandlers(
  authMiddleware,
  (c) => {
    const user = c.get('user')
    return c.json(user)
  }
)

const app = factory.createApp()
app.get('/user', ...getUser)

Reusable Middleware Factory

import { createFactory } from 'hono/factory'

type Env = {
  Variables: {
    requestId: string
  }
}

const factory = createFactory<Env>()

// Create a reusable middleware generator
function createRequestId() {
  return factory.createMiddleware(async (c, next) => {
    c.set('requestId', crypto.randomUUID())
    await next()
  })
}

const app = factory.createApp()
app.use('*', createRequestId())

app.get('/', (c) => {
  const requestId = c.get('requestId') // Type-safe
  return c.json({ requestId })
})

Modular App Structure

// factories/app.ts
import { createFactory } from 'hono/factory'
import { logger } from 'hono/logger'

export type AppEnv = {
  Bindings: {
    DB: Database
  }
  Variables: {
    user: User | null
  }
}

export const factory = createFactory<AppEnv>({
  initApp: (app) => {
    app.use('*', logger())
  }
})

// middleware/auth.ts
import { factory } from '../factories/app'

export const authMiddleware = factory.createMiddleware(async (c, next) => {
  const user = await getUser(c.req.header('Authorization'))
  c.set('user', user)
  await next()
})

// routes/users.ts
import { factory } from '../factories/app'
import { authMiddleware } from '../middleware/auth'

const userHandlers = factory.createHandlers(
  authMiddleware,
  (c) => {
    const user = c.get('user')
    return c.json({ user })
  }
)

export const userRoutes = factory.createApp()
userRoutes.get('/', ...userHandlers)

// app.ts
import { factory } from './factories/app'
import { userRoutes } from './routes/users'

const app = factory.createApp()
app.route('/users', userRoutes)

Typed Input Validation

import { createFactory } from 'hono/factory'
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const factory = createFactory()

const schema = z.object({
  name: z.string(),
  age: z.number()
})

const handlers = factory.createHandlers(
  zValidator('json', schema),
  (c) => {
    const data = c.req.valid('json') // Type is inferred
    return c.json({ message: `Hello ${data.name}` })
  }
)

app.post('/create', ...handlers)

Benefits

Type Safety

The factory ensures all components share the same environment types:
const factory = createFactory<Env>()

// All created components have access to Env types
const middleware = factory.createMiddleware(async (c, next) => {
  c.env.DB // ✓ Type-safe
  c.get('user') // ✓ Type-safe
  await next()
})

Reusability

Create reusable middleware and handlers:
function createAuthMiddleware(requiredRole: string) {
  return factory.createMiddleware(async (c, next) => {
    const user = c.get('user')
    if (user.role !== requiredRole) {
      return c.text('Forbidden', 403)
    }
    await next()
  })
}

app.get('/admin', createAuthMiddleware('admin'), (c) => {
  return c.text('Admin panel')
})

Consistent Setup

Initialize all apps with common configuration:
const factory = createFactory<Env>({
  initApp: (app) => {
    app.use('*', logger())
    app.use('*', cors())
  }
})

// All apps automatically have logger and cors
const app1 = factory.createApp()
const app2 = factory.createApp()

Build docs developers (and LLMs) love