[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M718WRY4NNYRQC2BFC1CERMK":3,"skill-same:01M718WRY4NNYRQC2BFC1CERMK":76},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":14,"repositoryHtmlUrl":59,"repositoryHomepageUrl":6,"ownerHtmlUrl":60,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":61,"install":62,"resources":75},"01M718WRY4NNYRQC2BFC1CERMK","hono",null,"Build ultra-fast web APIs and full-stack apps with Hono — runs on Cloudflare Workers, Deno, Bun, Node.js, and any WinterCG-compatible runtime.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Fhono\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",[5,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"cloudflare workers","2026","ultra","apps","runtime","full","web-standards","cloudflare-workers","community","standards","safe","deno","node","stack","api","edge","cloudflare","gemini","typescript","2026-11-10 10:12:30",false,"---\nname: hono\ndescription: \"Build ultra-fast web APIs and full-stack apps with Hono — runs on Cloudflare Workers, Deno, Bun, Node.js, and any WinterCG-compatible runtime.\"\ncategory: backend\nrisk: safe\nsource: community\ndate_added: \"2026-03-18\"\nauthor: suhaibjanjua\ntags: [hono, edge, cloudflare-workers, bun, deno, api, typescript, web-standards]\ntools: [claude, cursor, gemini]\n---\n\n# Hono Web Framework\n\n## Overview\n\nHono (炎, \"flame\" in Japanese) is a small, ultrafast web framework built on Web Standards (`Request`\u002F`Response`\u002F`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.\n\n## When to Use This Skill\n\n- Use when building a REST or RPC API for edge deployment (Cloudflare Workers, Deno Deploy)\n- Use when you need a minimal but type-safe server framework for Bun or Node.js\n- Use when building a Backend for Frontend (BFF) layer with low latency requirements\n- Use when migrating from Express but wanting better TypeScript support and edge compatibility\n- Use when the user asks about Hono routing, middleware, `c.req`, `c.json`, or `hc()` RPC client\n\n## How It Works\n\n### Step 1: Project Setup\n\n**Cloudflare Workers (recommended for edge):**\n```bash\nnpm create hono@latest my-api\n# Select: cloudflare-workers\ncd my-api\nnpm install\nnpm run dev    # Wrangler local dev\nnpm run deploy # Deploy to Cloudflare\n```\n\n**Bun \u002F Node.js:**\n```bash\nmkdir my-api && cd my-api\nbun init\nbun add hono\n```\n\n```typescript\n\u002F\u002F src\u002Findex.ts (Bun)\nimport { Hono } from 'hono';\n\nconst app = new Hono();\n\napp.get('\u002F', c => c.text('Hello Hono!'));\n\nexport default {\n  port: 3000,\n  fetch: app.fetch,\n};\n```\n\n### Step 2: Routing\n\n```typescript\nimport { Hono } from 'hono';\n\nconst app = new Hono();\n\n\u002F\u002F Basic methods\napp.get('\u002Fposts', c => c.json({ posts: [] }));\napp.post('\u002Fposts', c => c.json({ created: true }, 201));\napp.put('\u002Fposts\u002F:id', c => c.json({ updated: true }));\napp.delete('\u002Fposts\u002F:id', c => c.json({ deleted: true }));\n\n\u002F\u002F Route params and query strings\napp.get('\u002Fposts\u002F:id', async c => {\n  const id = c.req.param('id');\n  const format = c.req.query('format') ?? 'json';\n  return c.json({ id, format });\n});\n\n\u002F\u002F Wildcard\napp.get('\u002Fstatic\u002F*', c => c.text('static file'));\n\nexport default app;\n```\n\n**Chained routing:**\n```typescript\napp\n  .get('\u002Fusers', listUsers)\n  .post('\u002Fusers', createUser)\n  .get('\u002Fusers\u002F:id', getUser)\n  .patch('\u002Fusers\u002F:id', updateUser)\n  .delete('\u002Fusers\u002F:id', deleteUser);\n```\n\n### Step 3: Middleware\n\nHono middleware works exactly like `fetch` interceptors — before and after handlers:\n\n```typescript\nimport { Hono } from 'hono';\nimport { logger } from 'hono\u002Flogger';\nimport { cors } from 'hono\u002Fcors';\nimport { bearerAuth } from 'hono\u002Fbearer-auth';\n\nconst app = new Hono();\n\n\u002F\u002F Built-in middleware\napp.use('*', logger());\napp.use('\u002Fapi\u002F*', cors({ origin: 'https:\u002F\u002Fmyapp.com' }));\napp.use('\u002Fapi\u002Fadmin\u002F*', bearerAuth({ token: process.env.API_TOKEN! }));\n\n\u002F\u002F Custom middleware\napp.use('*', async (c, next) => {\n  c.set('requestId', crypto.randomUUID());\n  await next();\n  c.header('X-Request-Id', c.get('requestId'));\n});\n```\n\n**Available built-in middleware:** `logger`, `cors`, `csrf`, `etag`, `cache`, `basicAuth`, `bearerAuth`, `jwt`, `compress`, `bodyLimit`, `timeout`, `prettyJSON`, `secureHeaders`.\n\n### Step 4: Request and Response Helpers\n\n```typescript\napp.post('\u002Fsubmit', async c => {\n  \u002F\u002F Parse body\n  const body = await c.req.json\u003C{ name: string; email: string }>();\n  const form = await c.req.formData();\n  const text = await c.req.text();\n\n  \u002F\u002F Headers and cookies\n  const auth = c.req.header('authorization');\n  const token = getCookie(c, 'session');\n\n  \u002F\u002F Responses\n  return c.json({ ok: true });                        \u002F\u002F JSON\n  return c.text('hello');                             \u002F\u002F plain text\n  return c.html('\u003Ch1>Hello\u003C\u002Fh1>');                    \u002F\u002F HTML\n  return c.redirect('\u002Fdashboard', 302);              \u002F\u002F redirect\n  return new Response(stream, { status: 200 });       \u002F\u002F raw Response\n});\n```\n\n### Step 5: Zod Validator Middleware\n\n```typescript\nimport { zValidator } from '@hono\u002Fzod-validator';\nimport { z } from 'zod';\n\nconst createPostSchema = z.object({\n  title: z.string().min(1).max(200),\n  body: z.string().min(1),\n  tags: z.array(z.string()).default([]),\n});\n\napp.post(\n  '\u002Fposts',\n  zValidator('json', createPostSchema),\n  async c => {\n    const data = c.req.valid('json'); \u002F\u002F fully typed\n    const post = await db.post.create({ data });\n    return c.json(post, 201);\n  }\n);\n```\n\n### Step 6: Route Groups and App Composition\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fposts.ts\nimport { Hono } from 'hono';\n\nconst posts = new Hono();\n\nposts.get('\u002F', async c => { \u002F* list posts *\u002F });\nposts.post('\u002F', async c => { \u002F* create post *\u002F });\nposts.get('\u002F:id', async c => { \u002F* get post *\u002F });\n\nexport default posts;\n```\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport { Hono } from 'hono';\nimport posts from '.\u002Froutes\u002Fposts';\nimport users from '.\u002Froutes\u002Fusers';\n\nconst app = new Hono().basePath('\u002Fapi');\n\napp.route('\u002Fposts', posts);\napp.route('\u002Fusers', users);\n\nexport default app;\n```\n\n### Step 7: RPC Client (End-to-End Type Safety)\n\nHono's RPC mode exports route types that the `hc` client consumes — similar to tRPC but using fetch conventions:\n\n```typescript\n\u002F\u002F server: src\u002Froutes\u002Fposts.ts\nimport { Hono } from 'hono';\nimport { zValidator } from '@hono\u002Fzod-validator';\nimport { z } from 'zod';\n\nconst posts = new Hono()\n  .get('\u002F', c => c.json({ posts: [{ id: '1', title: 'Hello' }] }))\n  .post(\n    '\u002F',\n    zValidator('json', z.object({ title: z.string() })),\n    async c => {\n      const { title } = c.req.valid('json');\n      return c.json({ id: '2', title }, 201);\n    }\n  );\n\nexport default posts;\nexport type PostsType = typeof posts;\n```\n\n```typescript\n\u002F\u002F client: src\u002Fclient.ts\nimport { hc } from 'hono\u002Fclient';\nimport type { PostsType } from '..\u002Fserver\u002Froutes\u002Fposts';\n\nconst client = hc\u003CPostsType>('\u002Fapi\u002Fposts');\n\n\u002F\u002F Fully typed — autocomplete on routes, params, and responses\nconst { posts } = await client.$get().json();\nconst newPost = await client.$post({ json: { title: 'New Post' } }).json();\n```\n\n## Examples\n\n### Example 1: JWT Auth Middleware\n\n```typescript\nimport { Hono } from 'hono';\nimport { jwt, sign } from 'hono\u002Fjwt';\n\nconst app = new Hono();\nconst SECRET = process.env.JWT_SECRET!;\n\napp.post('\u002Flogin', async c => {\n  const { email, password } = await c.req.json();\n  const user = await validateUser(email, password);\n  if (!user) return c.json({ error: 'Invalid credentials' }, 401);\n\n  const token = await sign({ sub: user.id, exp: Math.floor(Date.now() \u002F 1000) + 3600 }, SECRET);\n  return c.json({ token });\n});\n\napp.use('\u002Fapi\u002F*', jwt({ secret: SECRET }));\napp.get('\u002Fapi\u002Fme', async c => {\n  const payload = c.get('jwtPayload');\n  const user = await getUserById(payload.sub);\n  return c.json(user);\n});\n\nexport default app;\n```\n\n### Example 2: Cloudflare Workers with D1 Database\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport { Hono } from 'hono';\n\ntype Bindings = {\n  DB: D1Database;\n  API_TOKEN: string;\n};\n\nconst app = new Hono\u003C{ Bindings: Bindings }>();\n\napp.get('\u002Fusers', async c => {\n  const { results } = await c.env.DB.prepare('SELECT * FROM users LIMIT 50').all();\n  return c.json(results);\n});\n\napp.post('\u002Fusers', async c => {\n  const { name, email } = await c.req.json();\n  await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')\n    .bind(name, email)\n    .run();\n  return c.json({ created: true }, 201);\n});\n\nexport default app;\n```\n\n### Example 3: Streaming Response\n\n```typescript\nimport { stream, streamText } from 'hono\u002Fstreaming';\n\napp.get('\u002Fstream', c =>\n  streamText(c, async stream => {\n    for (const chunk of ['Hello', ' ', 'World']) {\n      await stream.write(chunk);\n      await stream.sleep(100);\n    }\n  })\n);\n```\n\n## Best Practices\n\n- ✅ Use route groups (sub-apps) to keep handlers in separate files — `app.route('\u002Fusers', usersRouter)`\n- ✅ Use `zValidator` for all request body, query, and param validation\n- ✅ Type Cloudflare Workers bindings with the `Bindings` generic: `new Hono\u003C{ Bindings: Env }>()`\n- ✅ Use the RPC client (`hc`) when your frontend and backend share the same repo\n- ✅ Prefer returning `c.json()`\u002F`c.text()` over `new Response()` for cleaner code\n- ❌ Don't use Node.js-specific APIs (`fs`, `path`, `process`) if you want edge portability\n- ❌ Don't add heavy dependencies — Hono's value is its tiny footprint on edge runtimes\n- ❌ Don't skip middleware typing — use generics (`Variables`, `Bindings`) to keep `c.get()` type-safe\n\n## Security & Safety Notes\n\n- Always validate input with `zValidator` before using data from requests.\n- Use Hono's built-in `csrf` middleware on mutation endpoints when serving HTML\u002Fforms.\n- For Cloudflare Workers, store secrets in `wrangler.toml` `[vars]` (non-secret) or `wrangler secret put` (secret) — never hardcode them in source.\n- When using `bearerAuth` or `jwt`, ensure tokens are validated server-side — do not trust client-provided user IDs.\n- Rate-limit sensitive endpoints (auth, password reset) with Cloudflare Rate Limiting or a custom middleware.\n\n## Common Pitfalls\n\n- **Problem:** Handler returns `undefined` — response is empty\n  **Solution:** Always `return` a response from handlers: `return c.json(...)` not just `c.json(...)`.\n\n- **Problem:** Middleware runs after the response is sent\n  **Solution:** Call `await next()` before post-response logic; Hono runs code after `next()` as the response travels back up the chain.\n\n- **Problem:** `c.env` is undefined on Node.js\n  **Solution:** Cloudflare `env` bindings only exist in Workers. Use `process.env` on Node.js.\n\n- **Problem:** Route not matching — gets a 404\n  **Solution:** Check that `app.route('\u002Fprefix', subRouter)` uses the same prefix your client calls. Sub-routers should **not** repeat the prefix in their own routes.\n\n## Related Skills\n\n- `@cloudflare-workers-expert` — Deep dive into Cloudflare Workers platform specifics\n- `@trpc-fullstack` — Alternative RPC approach for TypeScript full-stack apps\n- `@zod-validation-expert` — Detailed Zod schema patterns used with `@hono\u002Fzod-validator`\n- `@nodejs-backend-patterns` — When you need a Node.js-specific backend (not edge)\n","# Hono Web Framework\n\n## Overview\n\nHono (炎, \"flame\" in Japanese) is a small, ultrafast web framework built on Web Standards (`Request`\u002F`Response`\u002F`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.\n\n## When to Use This Skill\n\n- Use when building a REST or RPC API for edge deployment (Cloudflare Workers, Deno Deploy)\n- Use when you need a minimal but type-safe server framework for Bun or Node.js\n- Use when building a Backend for Frontend (BFF) layer with low latency requirements\n- Use when migrating from Express but wanting better TypeScript support and edge compatibility\n- Use when the user asks about Hono routing, middleware, `c.req`, `c.json`, or `hc()` RPC client\n\n## How It Works\n\n### Step 1: Project Setup\n\n**Cloudflare Workers (recommended for edge):**\n```bash\nnpm create hono@latest my-api\n# Select: cloudflare-workers\ncd my-api\nnpm install\nnpm run dev    # Wrangler local dev\nnpm run deploy # Deploy to Cloudflare\n```\n\n**Bun \u002F Node.js:**\n```bash\nmkdir my-api && cd my-api\nbun init\nbun add hono\n```\n\n```typescript\n\u002F\u002F src\u002Findex.ts (Bun)\nimport { Hono } from 'hono';\n\nconst app = new Hono();\n\napp.get('\u002F', c => c.text('Hello Hono!'));\n\nexport default {\n  port: 3000,\n  fetch: app.fetch,\n};\n```\n\n### Step 2: Routing\n\n```typescript\nimport { Hono } from 'hono';\n\nconst app = new Hono();\n\n\u002F\u002F Basic methods\napp.get('\u002Fposts', c => c.json({ posts: [] }));\napp.post('\u002Fposts', c => c.json({ created: true }, 201));\napp.put('\u002Fposts\u002F:id', c => c.json({ updated: true }));\napp.delete('\u002Fposts\u002F:id', c => c.json({ deleted: true }));\n\n\u002F\u002F Route params and query strings\napp.get('\u002Fposts\u002F:id', async c => {\n  const id = c.req.param('id');\n  const format = c.req.query('format') ?? 'json';\n  return c.json({ id, format });\n});\n\n\u002F\u002F Wildcard\napp.get('\u002Fstatic\u002F*', c => c.text('static file'));\n\nexport default app;\n```\n\n**Chained routing:**\n```typescript\napp\n  .get('\u002Fusers', listUsers)\n  .post('\u002Fusers', createUser)\n  .get('\u002Fusers\u002F:id', getUser)\n  .patch('\u002Fusers\u002F:id', updateUser)\n  .delete('\u002Fusers\u002F:id', deleteUser);\n```\n\n### Step 3: Middleware\n\nHono middleware works exactly like `fetch` interceptors — before and after handlers:\n\n```typescript\nimport { Hono } from 'hono';\nimport { logger } from 'hono\u002Flogger';\nimport { cors } from 'hono\u002Fcors';\nimport { bearerAuth } from 'hono\u002Fbearer-auth';\n\nconst app = new Hono();\n\n\u002F\u002F Built-in middleware\napp.use('*', logger());\napp.use('\u002Fapi\u002F*', cors({ origin: 'https:\u002F\u002Fmyapp.com' }));\napp.use('\u002Fapi\u002Fadmin\u002F*', bearerAuth({ token: process.env.API_TOKEN! }));\n\n\u002F\u002F Custom middleware\napp.use('*', async (c, next) => {\n  c.set('requestId', crypto.randomUUID());\n  await next();\n  c.header('X-Request-Id', c.get('requestId'));\n});\n```\n\n**Available built-in middleware:** `logger`, `cors`, `csrf`, `etag`, `cache`, `basicAuth`, `bearerAuth`, `jwt`, `compress`, `bodyLimit`, `timeout`, `prettyJSON`, `secureHeaders`.\n\n### Step 4: Request and Response Helpers\n\n```typescript\napp.post('\u002Fsubmit', async c => {\n  \u002F\u002F Parse body\n  const body = await c.req.json\u003C{ name: string; email: string }>();\n  const form = await c.req.formData();\n  const text = await c.req.text();\n\n  \u002F\u002F Headers and cookies\n  const auth = c.req.header('authorization');\n  const token = getCookie(c, 'session');\n\n  \u002F\u002F Responses\n  return c.json({ ok: true });                        \u002F\u002F JSON\n  return c.text('hello');                             \u002F\u002F plain text\n  return c.html('\u003Ch1>Hello\u003C\u002Fh1>');                    \u002F\u002F HTML\n  return c.redirect('\u002Fdashboard', 302);              \u002F\u002F redirect\n  return new Response(stream, { status: 200 });       \u002F\u002F raw Response\n});\n```\n\n### Step 5: Zod Validator Middleware\n\n```typescript\nimport { zValidator } from '@hono\u002Fzod-validator';\nimport { z } from 'zod';\n\nconst createPostSchema = z.object({\n  title: z.string().min(1).max(200),\n  body: z.string().min(1),\n  tags: z.array(z.string()).default([]),\n});\n\napp.post(\n  '\u002Fposts',\n  zValidator('json', createPostSchema),\n  async c => {\n    const data = c.req.valid('json'); \u002F\u002F fully typed\n    const post = await db.post.create({ data });\n    return c.json(post, 201);\n  }\n);\n```\n\n### Step 6: Route Groups and App Composition\n\n```typescript\n\u002F\u002F src\u002Froutes\u002Fposts.ts\nimport { Hono } from 'hono';\n\nconst posts = new Hono();\n\nposts.get('\u002F', async c => { \u002F* list posts *\u002F });\nposts.post('\u002F', async c => { \u002F* create post *\u002F });\nposts.get('\u002F:id', async c => { \u002F* get post *\u002F });\n\nexport default posts;\n```\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport { Hono } from 'hono';\nimport posts from '.\u002Froutes\u002Fposts';\nimport users from '.\u002Froutes\u002Fusers';\n\nconst app = new Hono().basePath('\u002Fapi');\n\napp.route('\u002Fposts', posts);\napp.route('\u002Fusers', users);\n\nexport default app;\n```\n\n### Step 7: RPC Client (End-to-End Type Safety)\n\nHono's RPC mode exports route types that the `hc` client consumes — similar to tRPC but using fetch conventions:\n\n```typescript\n\u002F\u002F server: src\u002Froutes\u002Fposts.ts\nimport { Hono } from 'hono';\nimport { zValidator } from '@hono\u002Fzod-validator';\nimport { z } from 'zod';\n\nconst posts = new Hono()\n  .get('\u002F', c => c.json({ posts: [{ id: '1', title: 'Hello' }] }))\n  .post(\n    '\u002F',\n    zValidator('json', z.object({ title: z.string() })),\n    async c => {\n      const { title } = c.req.valid('json');\n      return c.json({ id: '2', title }, 201);\n    }\n  );\n\nexport default posts;\nexport type PostsType = typeof posts;\n```\n\n```typescript\n\u002F\u002F client: src\u002Fclient.ts\nimport { hc } from 'hono\u002Fclient';\nimport type { PostsType } from '..\u002Fserver\u002Froutes\u002Fposts';\n\nconst client = hc\u003CPostsType>('\u002Fapi\u002Fposts');\n\n\u002F\u002F Fully typed — autocomplete on routes, params, and responses\nconst { posts } = await client.$get().json();\nconst newPost = await client.$post({ json: { title: 'New Post' } }).json();\n```\n\n## Examples\n\n### Example 1: JWT Auth Middleware\n\n```typescript\nimport { Hono } from 'hono';\nimport { jwt, sign } from 'hono\u002Fjwt';\n\nconst app = new Hono();\nconst SECRET = process.env.JWT_SECRET!;\n\napp.post('\u002Flogin', async c => {\n  const { email, password } = await c.req.json();\n  const user = await validateUser(email, password);\n  if (!user) return c.json({ error: 'Invalid credentials' }, 401);\n\n  const token = await sign({ sub: user.id, exp: Math.floor(Date.now() \u002F 1000) + 3600 }, SECRET);\n  return c.json({ token });\n});\n\napp.use('\u002Fapi\u002F*', jwt({ secret: SECRET }));\napp.get('\u002Fapi\u002Fme', async c => {\n  const payload = c.get('jwtPayload');\n  const user = await getUserById(payload.sub);\n  return c.json(user);\n});\n\nexport default app;\n```\n\n### Example 2: Cloudflare Workers with D1 Database\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport { Hono } from 'hono';\n\ntype Bindings = {\n  DB: D1Database;\n  API_TOKEN: string;\n};\n\nconst app = new Hono\u003C{ Bindings: Bindings }>();\n\napp.get('\u002Fusers', async c => {\n  const { results } = await c.env.DB.prepare('SELECT * FROM users LIMIT 50').all();\n  return c.json(results);\n});\n\napp.post('\u002Fusers', async c => {\n  const { name, email } = await c.req.json();\n  await c.env.DB.prepare('INSERT INTO users (name, email) VALUES (?, ?)')\n    .bind(name, email)\n    .run();\n  return c.json({ created: true }, 201);\n});\n\nexport default app;\n```\n\n### Example 3: Streaming Response\n\n```typescript\nimport { stream, streamText } from 'hono\u002Fstreaming';\n\napp.get('\u002Fstream', c =>\n  streamText(c, async stream => {\n    for (const chunk of ['Hello', ' ', 'World']) {\n      await stream.write(chunk);\n      await stream.sleep(100);\n    }\n  })\n);\n```\n\n## Best Practices\n\n- ✅ Use route groups (sub-apps) to keep handlers in separate files — `app.route('\u002Fusers', usersRouter)`\n- ✅ Use `zValidator` for all request body, query, and param validation\n- ✅ Type Cloudflare Workers bindings with the `Bindings` generic: `new Hono\u003C{ Bindings: Env }>()`\n- ✅ Use the RPC client (`hc`) when your frontend and backend share the same repo\n- ✅ Prefer returning `c.json()`\u002F`c.text()` over `new Response()` for cleaner code\n- ❌ Don't use Node.js-specific APIs (`fs`, `path`, `process`) if you want edge portability\n- ❌ Don't add heavy dependencies — Hono's value is its tiny footprint on edge runtimes\n- ❌ Don't skip middleware typing — use generics (`Variables`, `Bindings`) to keep `c.get()` type-safe\n\n## Security & Safety Notes\n\n- Always validate input with `zValidator` before using data from requests.\n- Use Hono's built-in `csrf` middleware on mutation endpoints when serving HTML\u002Fforms.\n- For Cloudflare Workers, store secrets in `wrangler.toml` `[vars]` (non-secret) or `wrangler secret put` (secret) — never hardcode them in source.\n- When using `bearerAuth` or `jwt`, ensure tokens are validated server-side — do not trust client-provided user IDs.\n- Rate-limit sensitive endpoints (auth, password reset) with Cloudflare Rate Limiting or a custom middleware.\n\n## Common Pitfalls\n\n- **Problem:** Handler returns `undefined` — response is empty\n  **Solution:** Always `return` a response from handlers: `return c.json(...)` not just `c.json(...)`.\n\n- **Problem:** Middleware runs after the response is sent\n  **Solution:** Call `await next()` before post-response logic; Hono runs code after `next()` as the response travels back up the chain.\n\n- **Problem:** `c.env` is undefined on Node.js\n  **Solution:** Cloudflare `env` bindings only exist in Workers. Use `process.env` on Node.js.\n\n- **Problem:** Route not matching — gets a 404\n  **Solution:** Check that `app.route('\u002Fprefix', subRouter)` uses the same prefix your client calls. Sub-routers should **not** repeat the prefix in their own routes.\n\n## Related Skills\n\n- `@cloudflare-workers-expert` — Deep dive into Cloudflare Workers platform specifics\n- `@trpc-fullstack` — Alternative RPC approach for TypeScript full-stack apps\n- `@zod-validation-expert` — Detailed Zod schema patterns used with `@hono\u002Fzod-validator`\n- `@nodejs-backend-patterns` — When you need a Node.js-specific backend (not edge)\n",{"name":5,"risk":34,"tags":48,"tools":50,"author":53,"source":32,"category":54,"date_added":55,"description":7},[5,39,31,49,35,38,42,30],"bun",[51,52,41],"claude","cursor","suhaibjanjua","backend","2026-03-18","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fglobal\u002Fhono","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":63,"prompt":73,"zipAvailable":74},[64,67,70],{"tool":65,"command":66},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill hono",{"tool":68,"command":69},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill hono",{"tool":71,"command":72},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill hono","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fglobal\u002Fhono\u002FSKILL.md",true,[],[77,101,126,136,149,166],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":88,"publishedAt":43},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[83],{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[89,90,91,92,93,94,95,96,97,98,99,100],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":107,"publishedAt":43},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[108,109,110,111,112,113,91,114,115,116,117,118,119,120,121,122,123,124,125,38],"trend","trend tap","tap","api keys","Bash","time","trending","hacker","aggregator","do","when","brew","live","data","google","install","read","across",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":132,"publishedAt":43},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[133,134,108,119,120,121,122,112,91,124,135,125,38,118,116,115,114,123,113,111],"trend radar","radar","pulse",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":142,"publishedAt":43},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[143,144,145,146,147,148],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":153,"categories":154,"keywords":158,"publishedAt":43},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[155],{"categoryNo":156,"categoryName":157,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000021","资料检索与研究",[151,97,159,160,161,100,119,162,163,164,110,165,123],"Audio","cli","youtube","images","https","files","pdfs",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":172,"publishedAt":43},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[168,173,174,175,123,176,163,177,178,179,180,181],"status","play","go","latest","github","discover","control","cmd","volume"]