Skip to content
Development
Skill

/hono-routing

Type-safe Hono APIs with routing, middleware, RPC. Use for request validation, Zod/Valibot validators, or encountering middleware type inference, validation hook, RPC errors.

From plugin
secondsky-claude-skills
219183 skills42 agents62 commands2 MCP
Install
$ npx -y skills add secondsky/claude-skills --skill hono-routing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/hono-routing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Type-safe Hono APIs with routing, middleware, RPC. Use for request validation, Zod/Valibot validators, or encountering middleware type inference, validation hook, RPC errors.

SKILL.md

hono-routing.SKILL.md
name: hono-routing
description: "Type-safe Hono APIs with routing, middleware, RPC. Use for request validation, Zod/Valibot validators, or encountering middleware type inference, validation hook, RPC errors."

license: MIT
metadata:
  version: "2.0.0"
  package_version: "4.12.12"
  last_verified: "2025-11-21"
  errors_prevented: 12
  templates_included: 9
  references_included: 6
  keywords:
    - hono
    - hono routing
    - hono middleware
    - hono rpc
    - hono validator
    - zod validator
    - valibot validator
    - type-safe api
    - hono context
    - hono error handling
    - HTTPException
    - c.req.valid
    - middleware composition
    - hono hooks
    - typed routes
    - hono client
    - middleware response not typed
    - hono validation failed
    - hono rpc type inference

Hono Routing & Middleware

**Status**: Production Ready ✅ **Last Updated**: 2025-11-21 **Dependencies**: None (framework-agnostic) **Latest Versions**: hono@4.12.12, zod@4.3.6, valibot@1.1.0

---

Quick Start (5 Minutes)

Install

bun add hono@4.12.12  # preferred
# or: bun add hono@4.12.12

**Why Hono:**

  • **Fast**: Built on Web Standards, runs on any JavaScript runtime
  • **Lightweight**: ~10KB, no dependencies
  • **Type-safe**: Full TypeScript support with type inference
  • **Flexible**: Works on Cloudflare Workers, Deno, Bun, Node.js, Vercel

Basic App

import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.json({ message: 'Hello Hono!' })
})

export default app

**CRITICAL:**

  • Use `c.json()`, `c.text()`, `c.html()` for responses
  • Return the response (don't use `res.send()` like Express)
  • Export app for runtime

Add Validation

bun add zod@4.3.6 @hono/zod-validator@0.7.4
import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

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

app.post('/user', zValidator('json', schema), (c) => {
  const data = c.req.valid('json')
  return c.json({ success: true, data })
})

---

Critical Rules

Always Do

✅ **Return responses** from handlers (c.json, c.text, c.html, etc.)

✅ **Use c.req.valid('source')** after validation middleware to get typed data

✅ **Export app** for deployment (Cloudflare Workers, Bun, Deno, Node.js)

✅ **Use validation middleware** (zValidator, vValidator) for type-safe request data

✅ **Call await next()** in middleware to pass control to next handler

✅ **Use HTTPException** for expected errors (returns proper HTTP status)

✅ **Use template tag validators** (zValidator, vValidator) not hooks

✅ **Define context types** for custom variables (`Hono<{ Variables: { ... } }>`)

✅ **Use sub-apps** (app.route()) for organizing large APIs

✅ **Type your RPC routes** (`export type AppType = typeof routes`) for client

Never Do

❌ **Never forget to return** response from handlers

❌ **Never use req.json() directly** without validation - use c.req.valid()

❌ **Never mix validation hooks** with middleware - use middleware only

❌ **Never forget await next()** in middleware - breaks middleware chain

❌ **Never use res.send()** - not available (use c.json(), c.text(), etc.)

❌ **Never skip error handling** - use app.onError() for global handler

❌ **Never access unvalidated data** after validation middleware

❌ **Never use blocking operations** in middleware - breaks async chain

❌ **Never hardcode origins** in CORS - use environment variables

❌ **Never skip type exports** for RPC - client won't have types

---

Top 5 Errors (See references/top-errors.md for all 12)

Error #1: Middleware Response Not Typed

**Problem**: Middleware returns response but route handler still executes **Solution**: Don't return from middleware if you want chain to continue - only set variables

// ❌ Wrong - breaks chain
app.use('*', (c) => {
  return c.json({ error: 'Unauthorized' }, 401)
})

// ✅ Correct - throw HTTPException instead
app.use('*', (c, next) => {
  if (!isAuthorized) {
    throw new HTTPException(401, { message: 'Unauthorized' })
  }
  await next()
})

Error #2: Validation Hook vs Middleware Confusion

**Problem**: Using validation hooks instead of middleware **Solution**: Always use middleware validators (zValidator, vValidator)

// ❌ Wrong - hooks deprecated
app.post('/user', (c) => {
  const data = c.req.json<User>() // No runtime validation!
})

// ✅ Correct - middleware with runtime validation
app.post('/user', zValidator('json', schema), (c) => {
  const data = c.req.valid('json') // Validated & typed!
})

Error #3: Missing await next() in Middleware

**Problem**: Middleware doesn't call next(), breaking chain **Solution**: Always call await next() unless returning early

// ❌ Wrong - chain broken
app.use('*', (c) => {
  console.log('Log')
  // Missing await next()!
})

// ✅ Correct
app.use('*', async (c, next) => {
  console.log('Log')
  await next()
})

Error #4: Context Variable Type Inference

**Problem**: c.get() and c.set() not typed **Solution**: Define Variables type in Hono constructor

// ❌ Wrong - no types
const app = new Hono()
c.set('user', { id: '123' }) // Not typed
const user = c.get('user') // any

// ✅ Correct - typed
type Variables = {
  user: { id: string; name: string }
}
const app = new Hono<{ Variables: Variables }>()
c.set('user', { id: '123', name: 'Alice' })
const user = c.get('user') // Fully typed!

Error #5: RPC Type Inference Not Working

**Problem**: Client doesn't have types from server routes **Solution**: Export AppType and use hc<AppType>

// Server
const routes = app.get('/users', (c) => c.json([]))
export type AppType = typeof routes // Export this!

// Client
import { hc } from 'hono/client'
import type { AppType } from './server'

const client = hc<AppType>('http://localhost:8787') // Fully typed!

**Load `references/top-errors.md` for all 12 er

Read more
Ships withsecondsky-claude-skills

145 production-ready skills for Claude Code CLI 🔌 Platform / Harness Support These plugins ship as Claude Code marketplace plugins (.claude-plugin/ manifests) and Codex CLI plugins (.codex-plugin/ manifests).

Get the whole plugin

Other skills on secondsky-claude-skills.