hono – Coding skill for AI agents
Build ultra-fast web APIs and full-stack apps with Hono — runs on Cloudflare Workers, Deno, Bun, Node.js, and any WinterCG-compatible runtime.
Install the hono skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/hono-7af60.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /hono – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/hono-7af60.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $hono – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/hono-7af60.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /hono – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/hono-7af60.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /hono – then describe the task you want done.
SKILL.md content
Hono Web Framework
Overview
Hono (炎, "flame" in Japanese) is a small, ultrafast web framework built on Web Standards (Request/Response/fetch). It runs anywhere: Cloudflare Workers, Deno Deploy, Bun, Node.js, AWS Lambda, and any WinterCG-compatible runtime — with the same code. Hono's router is one of the fastest available, and its middleware system, built-in JSX support, and RPC client make it a strong choice for edge APIs, BFFs, and lightweight full-stack apps.
When to Use This Skill
- Use when building a REST or RPC API for edge deployment (Cloudflare Workers, Deno Deploy)
- Use when you need a minimal but type-safe server framework for Bun or Node.js
- Use when building a Backend for Frontend (BFF) layer with low latency requirements
- Use when migrating from Express but wanting better TypeScript support and edge compatibility
- Use when the user asks about Hono routing, middleware,
c.req,c.json, orhc()RPC client
How It Works
Step 1: Project Setup
Cloudflare Workers (recommended for edge):
npm create hono@latest my-api
# Select: cloudflare-workers
cd my-api
npm install
npm run dev # Wrangler local dev
npm run deploy # Deploy to CloudflareBun / Node.js:
mkdir my-api && cd my-api
bun init
bun add hono// src/index.ts (Bun)
import { Hono } from 'hono';
const app = new Hono();
app.get('/', c => c.text('Hello Hono!'));
export default {
port: 3000,
fetch: app.fetch,
};Step 2: Routing
import { Hono } from 'hono';
const app = new Hono();
// Basic methods
app.get('/posts', c => c.json({ posts: [] }));
app.post('/posts', c => c.json({ created: true }, 201));
app.put('/posts/:id', c => c.json({ updated: true }));
app.delete('/posts/:id', c => c.json({ deleted: true }));
// Route params and query strings
app.get('/posts/:id', async c => {
const id = c.req.param('id');
const format = c.req.query('format') ?? 'json';
return c.json({ id, format });
});
// Wildcard
app.get('/static/*', c => c.text('static file'));
export default app;Chained routing:
app
.get('/users', listUsers)
.post('/users', createUser)
.get('/users/:id', getUser)
.patch('/users/:id', updateUser)
.delete('/users/:id', deleteUser);Step 3: Middleware
Hono middleware works exactly like fetch interceptors — before and after handlers:
import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { cors } from 'hono/cors';
import { bearerAuth } from 'hono/bearer-auth';
const app = new Hono<{ Variables: { requestId: string } }>();
// Built-in middleware
app.use('*', logger());
app.use('/api/*', cors({ origin: 'https://myapp.com' }));
app.use('/api/admin/*', bearerAuth({ token: process.env.API_TOKEN! }));
// Custom middleware
app.use('*', async (c, next) => {
c.set('requestId', crypto.randomUUID());
await next();
c.header('X-Request-Id', c.get('requestId'));
});Available built-in middleware: logger, cors, csrf, etag, cache, basicAuth, bearerAuth, jwt, compress, bodyLimit, timeout, prettyJSON, secureHeaders.
The following lists alternative parsing/response methods, not a sequential handler: parse a body once according to Content-Type, validate it at runtime and return exactly one response. Import getCookie from hono/cookie. JSON generics do not validate input. Validate/authorize D1 and post mutations, limit body sizes, return only approved public fields and handle errors. Bearer/JWT snippets need a configured strong secret and algorithm, claims/expiry/audience/issuer checks appropriate to the deployment; verify exact APIs for the installed Hono major. Use c.env bindings in Workers instead of the Node process.env sketches. CORS is not authorization; scaffold deploy commands publish live resources and need an approved account/route.
Step 4: Request and Response Helpers
app.post('/submit', async c => {
// Parse body
const body = await c.req.json<{ name: string; email: string }>();
const form = await c.req.formData();
const text = await c.req.text();
// Headers and cookies
const auth = c.req.header('authorization');
const token = getCookie(c, 'session');
// Responses
return c.json({ ok: true }); // JSON
return c.text('hello'); // plain text
return c.html('<h1>Hello</h1>'); // HTML
return c.redirect('/dashboard', 302); // redirect
return new Response(stream, { status: 200 }); // raw Response
});Step 5: Zod Validator Middleware
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
const createPostSchema = z.object({
title: z.string().min(1).max(200),
body: z.string().min(1),
tags: z.array(z.string()).default([]),
});
app.post(
'/posts',
zValidator('json', createPostSchema),
async c => {
const data = c.req.valid('json'); // fully typed
const post = await db.post.create({ data });
return c.json(post, 201);
}
);Step 6: Route Groups and App Composition
// src/routes/posts.ts
import { Hono } from 'hono';
const posts = new Hono();
posts.get('/', async c => { /* list posts */ });
posts.post('/', async c => { /* create post */ });
posts.get('/:id', async c => { /* get post */ });
export default posts;// src/index.ts
import { Hono } from 'hono';
import posts from './routes/posts';
import users from './routes/users';
const app = new Hono().basePath('/api');
app.route('/posts', posts);
app.route('/users', users);
export default app;Step 7: RPC Client (End-to-End Type Safety)
Hono's RPC mode exports route types that the hc client consumes — similar to tRPC but using fetch conventions:
// server: src/routes/posts.ts
import { Hono } from 'hono';
import { zValidator } from '@hono/zod-validator';
import { z } from 'zod';
const posts = new Hono()
.get('/', c => c.json({ posts: [{ id: '1', title: 'Hello' }] }))
.post(
'/',
zValidator('json', z.object({ title: z.string() })),
async c => {
const { title } = c.req.valid('json');
return c.json({ id: '2', title }, 201);
}
);
export default posts;
export type PostsType = typeof posts;// client: src/client.ts
import { hc } from 'hono/client';
import type { PostsType } from '../server/routes/posts';
const client = hc<PostsType>('/api/posts');
// Fully typed — autocomplete on routes, params, and responses
const response = await client.$get();
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { posts } = await response.json();
const created = await client.$post({ json: { title: 'New Post' } });
const newPost = await created.json();Examples
Example 1: JWT Auth Middleware
import { Hono } from 'hono';
import { jwt, sign } from 'hono/jwt';
const app = new Hono();
const SECRET = process.env.JWT_SECRET!;
app.post('/login', async c => {
const { email, password } = await c.req.json();
const user = await validateUser(email, password);
if (!user) return c.json({ error: 'Invalid credentials' }, 401);
const token = await sign({ sub: user.id, exp: Math.floor(Date.now() / 1000) + 3600 }, SECRET);
return c.json({ token });
});
app.use('/api/*', jwt({ secret: SECRET }));
app.get('/api/me', async c => {
const payload = c.get('jwtPayload');
const user = await getUserById(payload.sub);
return c.json(user);
});
export default app;Example 2: Cloudflare Workers with D1 Database
// src/index.ts
import { Hono } from 'hono';
type Bindings = {
DB: D1Database;
API_TOKEN: string;
};
const app = new Hono<{ Bindings: Bindings }>();
app.get('/users', async c => {
const { results } = await c.env.DB.prepare('SELECT * FROM users LIMIT 50').all();
return c.json(results);
});
app.post('/users', async c => {
const { name, email } = await c.req.json();
await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
.bind(name, email)
.run();
return c.json({ created: true }, 201);
});
export default app;Example 3: Streaming Response
import { stream, streamText } from 'hono/streaming';
app.get('/stream', c =>
streamText(c, async stream => {
for (const chunk of ['Hello', ' ', 'World']) {
await stream.write(chunk);
await stream.sleep(100);
}
})
);Best Practices
- ✅ Use route groups (sub-apps) to keep handlers in separate files —
app.route('/users', usersRouter) - ✅ Use
zValidatorfor all request body, query, and param validation - ✅ Type Cloudflare Workers bindings with the
Bindingsgeneric:new Hono<{ Bindings: Env }>() - ✅ Use the RPC client (
hc) when your frontend and backend share the same repo - ✅ Prefer returning
c.json()/c.text()overnew Response()for cleaner code - ❌ Don't use Node.js-specific AP
… (full content is in the download package)
Related skills
- html-injection-testing – Identify and exploit HTML injection vulnerabilities that allow attackers to inject…
- http-status-code-tester – HTTP Status Code Tester. Use when working with one or more HTTP(S) URLs.
- hubspot-integration – Expert patterns for HubSpot CRM integration including OAuth authentication, CRM objects…
- hugging-face-cli – Hugging Face Hub CLI (`hf`) for downloading, uploading, and managing models, datasets…
- hugging-face-community-evals – Run evaluations for Hugging Face Hub models using inspect-ai and lighteval on local…
- hugging-face-gradio – Build Gradio web UIs and demos in Python. Use when creating or editing Gradio apps…
- hugging-face-papers – Look up and read Hugging Face paper pages in markdown, and use the papers API for…
- hugging-face-tool-builder – Your purpose is now is to create reusable command line scripts and utilities for using…