Claude-skill-registry hono
Builds APIs with Hono including routing, middleware, validation, and edge deployment. Use when creating fast APIs, building edge functions, or developing serverless applications.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/hono" ~/.claude/skills/majiayu000-claude-skill-registry-hono && rm -rf "$T"
manifest:
skills/data/hono/SKILL.mdsource content
Hono
Ultrafast web framework for the edge, built on Web Standards.
Quick Start
Install:
npm install hono
Create project:
npm create hono@latest my-app
Basic Server
// src/index.ts import { Hono } from 'hono'; const app = new Hono(); app.get('/', (c) => { return c.text('Hello Hono!'); }); app.get('/json', (c) => { return c.json({ message: 'Hello' }); }); export default app;
Routing
Basic Routes
import { Hono } from 'hono'; const app = new Hono(); // HTTP methods app.get('/users', (c) => c.json({ users: [] })); app.post('/users', (c) => c.json({ created: true })); app.put('/users/:id', (c) => c.json({ updated: true })); app.delete('/users/:id', (c) => c.json({ deleted: true })); app.patch('/users/:id', (c) => c.json({ patched: true })); // All methods app.all('/any', (c) => c.text('Any method'));
Path Parameters
app.get('/users/:id', (c) => { const id = c.req.param('id'); return c.json({ id }); }); // Multiple params app.get('/posts/:postId/comments/:commentId', (c) => { const { postId, commentId } = c.req.param(); return c.json({ postId, commentId }); }); // Optional params app.get('/posts/:id?', (c) => { const id = c.req.param('id'); return c.json({ id: id || 'all' }); }); // Wildcard app.get('/files/*', (c) => { const path = c.req.path; return c.text(`File: ${path}`); });
Query Parameters
app.get('/search', (c) => { const query = c.req.query('q'); const page = c.req.query('page') || '1'; // Multiple values const tags = c.req.queries('tags'); return c.json({ query, page, tags }); });
Route Groups
const app = new Hono(); // Group routes const api = new Hono(); api.get('/users', (c) => c.json({ users: [] })); api.get('/posts', (c) => c.json({ posts: [] })); app.route('/api/v1', api); // Chaining app.basePath('/api').get('/users', (c) => c.json([]));
Request Handling
Request Body
// JSON body app.post('/users', async (c) => { const body = await c.req.json(); return c.json(body); }); // Form data app.post('/upload', async (c) => { const formData = await c.req.formData(); const name = formData.get('name'); return c.text(`Name: ${name}`); }); // Text body app.post('/text', async (c) => { const text = await c.req.text(); return c.text(text); }); // Array buffer app.post('/binary', async (c) => { const buffer = await c.req.arrayBuffer(); return c.text(`Size: ${buffer.byteLength}`); });
Headers
app.get('/headers', (c) => { const auth = c.req.header('Authorization'); const contentType = c.req.header('Content-Type'); return c.json({ auth, contentType }); });
Response
Response Types
// Text app.get('/text', (c) => c.text('Hello')); // JSON app.get('/json', (c) => c.json({ message: 'Hello' })); // HTML app.get('/html', (c) => c.html('<h1>Hello</h1>')); // Redirect app.get('/redirect', (c) => c.redirect('/new-path')); // Custom status app.get('/error', (c) => { return c.json({ error: 'Not found' }, 404); }); // With headers app.get('/custom', (c) => { return c.json( { data: 'value' }, 200, { 'X-Custom-Header': 'value' } ); });
Streaming
import { streamText } from 'hono/streaming'; app.get('/stream', (c) => { return streamText(c, async (stream) => { for (let i = 0; i < 5; i++) { await stream.write(`data: ${i}\n`); await stream.sleep(1000); } }); });
Middleware
Built-in Middleware
import { Hono } from 'hono'; import { cors } from 'hono/cors'; import { logger } from 'hono/logger'; import { prettyJSON } from 'hono/pretty-json'; import { secureHeaders } from 'hono/secure-headers'; import { compress } from 'hono/compress'; import { etag } from 'hono/etag'; const app = new Hono(); app.use('*', logger()); app.use('*', cors()); app.use('*', prettyJSON()); app.use('*', secureHeaders()); app.use('*', compress()); app.use('*', etag());
Custom Middleware
import { Hono, Context, Next } from 'hono'; // Simple middleware const timing = async (c: Context, next: Next) => { const start = Date.now(); await next(); const ms = Date.now() - start; c.header('X-Response-Time', `${ms}ms`); }; app.use('*', timing); // Middleware with options const auth = (secret: string) => { return async (c: Context, next: Next) => { const token = c.req.header('Authorization'); if (token !== `Bearer ${secret}`) { return c.json({ error: 'Unauthorized' }, 401); } await next(); }; }; app.use('/api/*', auth('my-secret'));
Route-specific Middleware
app.get('/protected', auth('secret'), (c) => { return c.json({ protected: true }); }); // Multiple middleware app.post('/data', logger(), auth('secret'), validate(), (c) => { return c.json({ success: true }); });
Validation
Zod Validator
npm install @hono/zod-validator
import { Hono } from 'hono'; import { zValidator } from '@hono/zod-validator'; import { z } from 'zod'; const app = new Hono(); const userSchema = z.object({ name: z.string().min(1), email: z.string().email(), age: z.number().min(0).optional(), }); app.post( '/users', zValidator('json', userSchema), (c) => { const user = c.req.valid('json'); return c.json({ user }); } ); // Query validation const querySchema = z.object({ page: z.string().transform(Number).default('1'), limit: z.string().transform(Number).default('10'), }); app.get( '/users', zValidator('query', querySchema), (c) => { const { page, limit } = c.req.valid('query'); return c.json({ page, limit }); } ); // Param validation const paramSchema = z.object({ id: z.string().uuid(), }); app.get( '/users/:id', zValidator('param', paramSchema), (c) => { const { id } = c.req.valid('param'); return c.json({ id }); } );
Context Variables
import { Hono } from 'hono'; type Variables = { user: { id: string; name: string }; }; const app = new Hono<{ Variables: Variables }>(); // Set variable in middleware app.use('*', async (c, next) => { c.set('user', { id: '123', name: 'John' }); await next(); }); // Access in handler app.get('/me', (c) => { const user = c.get('user'); return c.json(user); });
Error Handling
import { Hono, HTTPException } from 'hono'; const app = new Hono(); // Throw HTTP exception app.get('/error', (c) => { throw new HTTPException(404, { message: 'Not found' }); }); // Global error handler app.onError((err, c) => { if (err instanceof HTTPException) { return c.json({ error: err.message }, err.status); } console.error(err); return c.json({ error: 'Internal Server Error' }, 500); }); // Not found handler app.notFound((c) => { return c.json({ error: 'Not Found' }, 404); });
RPC Mode
// server.ts import { Hono } from 'hono'; import { zValidator } from '@hono/zod-validator'; import { z } from 'zod'; const app = new Hono() .get('/users', (c) => { return c.json([{ id: 1, name: 'John' }]); }) .post( '/users', zValidator('json', z.object({ name: z.string() })), (c) => { const { name } = c.req.valid('json'); return c.json({ id: 2, name }); } ); export type AppType = typeof app; export default app; // client.ts import { hc } from 'hono/client'; import type { AppType } from './server'; const client = hc<AppType>('http://localhost:3000'); // Type-safe client calls const users = await client.users.$get(); const data = await users.json(); const newUser = await client.users.$post({ json: { name: 'Jane' }, });
Deployment
Cloudflare Workers
// src/index.ts import { Hono } from 'hono'; type Bindings = { KV: KVNamespace; DB: D1Database; }; const app = new Hono<{ Bindings: Bindings }>(); app.get('/kv/:key', async (c) => { const key = c.req.param('key'); const value = await c.env.KV.get(key); return c.json({ value }); }); export default app;
Vercel
// api/index.ts import { Hono } from 'hono'; import { handle } from 'hono/vercel'; const app = new Hono().basePath('/api'); app.get('/hello', (c) => c.json({ message: 'Hello from Vercel' })); export const GET = handle(app); export const POST = handle(app);
Node.js
import { serve } from '@hono/node-server'; import { Hono } from 'hono'; const app = new Hono(); app.get('/', (c) => c.text('Hello Node.js!')); serve({ fetch: app.fetch, port: 3000, });
Bun
import { Hono } from 'hono'; const app = new Hono(); app.get('/', (c) => c.text('Hello Bun!')); export default { port: 3000, fetch: app.fetch, };
JSX
import { Hono } from 'hono'; import { html } from 'hono/html'; const app = new Hono(); const Layout = ({ children }: { children: any }) => html` <!DOCTYPE html> <html> <head> <title>My App</title> </head> <body> ${children} </body> </html> `; app.get('/', (c) => { return c.html( <Layout> <h1>Hello, World!</h1> </Layout> ); });
Best Practices
- Use validators - Validate all inputs
- Type your bindings - For edge environments
- Handle errors globally - Use onError
- Use middleware - Reusable logic
- Export types for RPC - Type-safe clients
Common Mistakes
| Mistake | Fix |
|---|---|
| Forgetting async | Use async/await for body |
| Wrong content type | Use c.json(), c.text() etc. |
| Missing error handling | Add onError handler |
| Not validating | Use zValidator |
| Blocking event loop | Keep handlers fast |
Reference Files
- references/middleware.md - Middleware patterns
- references/deployment.md - Platform guides
- references/rpc.md - RPC client setup