Skip to main content
skill CX Codex

bun-hono-integration — Claude Code skill: Hono APIs on Bun

A skill that tells the agent how to build Hono APIs on Bun: routes, middleware, Zod validation, RPC client. Useful when your project already runs on Bun.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add secondsky/claude-skills --skill bun-hono-integration -a claude-code
Open on GitHub

What bun-hono-integration does

The skill hands the agent a working reference for Hono, the lightweight web framework built for Bun. It covers routes with path parameters and wildcards, route groups via app.route() and basePath(), and request parsing for JSON, text and formData.

Middleware gets its own sections: custom handlers plus the built-ins cors, logger, basicAuth, bearerAuth, compress, etag and secureHeaders. Validation runs through zValidator with Zod schemas, context variables are typed with c.set and c.get, and errors go through HTTPException and onError. There is also RPC mode: export AppType from the server and the hc client gives you typed calls.

Quick start is bun create hono my-app, then bun install and bun run dev. Validation needs the @hono/zod-validator package alongside zod. The common-errors section in the document cuts off mid-table, so do not count on it for debugging — keep the official Hono docs within reach.

What it helps with

  • stand up a REST API on Hono over Bun
  • define routes with path parameters and wildcards
  • wire in CORS, logging and security headers
  • validate request bodies with a Zod schema
  • get a typed client through RPC mode

Example prompts for the agent

  • add a POST /users route with zValidator and a Zod body schema
  • set up cors and logger middleware for every request
  • create a typed Hono client with hc and AppType

How to install bun-hono-integration

1Skills CLI (Vercel)

npx skills add secondsky/claude-skills --skill bun-hono-integration -a claude-code

2Manually: put the files in place

~/.claude/skills/bun-hono-integration/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/bun-hono-integration/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about bun-hono-integration

How do I install bun-hono-integration in Claude?

Run npx skills add secondsky/claude-skills --skill bun-hono-integration -a claude-code. The skill lands at ~/.claude/skills/bun-hono-integration/SKILL.md.

What does bun-hono-integration do?

It gives the agent a Hono-on-Bun reference: routing, middleware, Zod validation, context variables, error handling and the RPC client.

What do I need for this skill to work?

A Bun project with Hono installed. Validation requires the @hono/zod-validator and zod packages.

Source text

SKILL.md · MIT
---
name: bun-hono-integration
description: Use when building APIs with Hono framework on Bun, including routing, middleware, REST APIs, context handling, or web framework features.
metadata:
  version: "1.0.0"
license: MIT
---

# Bun Hono Integration

Hono is a fast, lightweight web framework optimized for Bun.

## Quick Start

```bash
bun create hono my-app
cd my-app
bun install
bun run dev
```

## Basic Setup

```typescript
import { Hono } from "hono";

const app = new Hono();

app.get("/", (c) => c.text("Hello Hono!"));

app.get("/json", (c) => c.json({ message: "Hello" }));

export default app;
```

## Routing

```typescript
import { Hono } from "hono";

const app = new Hono();

// HTTP methods
app.get("/users", (c) => c.json([]));
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 }));

// 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 parameters
app.get("/posts/:postId/comments/:commentId", (c) => {
  const { postId, commentId } = c.req.param();
  return c.json({ postId, commentId });
});

// Wildcards
app.get("/files/*", (c) => {
  const path = c.req.path;
  return c.text(`File: ${path}`);
});

// Regex-like patterns
app.get("/user/:id{[0-9]+}", (c) => c.json({ id: c.req.param("id") }));

export default app;
```

## Route Groups

```typescript
import { Hono } from "hono";

const app = new Hono();

// Group routes
const api = new Hono();
api.get("/users", (c) => c.json([]));
api.get("/posts", (c) => c.json([]));

app.route("/api/v1", api);

// Basepath
const app2 = new Hono().basePath("/api/v2");
app2.get("/users", (c) => c.json([])); // /api/v2/users

export default app;
```

## Request Handling

```typescript
app.post("/submit", async (c) => {
  // URL and method
  console.log(c.req.url);
  console.log(c.req.method);

  // Headers
  const auth = c.req.header("Authorization");

  // Query params
  const page = c.req.query("page");
  const { limit, offset } = c.req.query();

  // Body parsing
  const json = await c.req.json();
  const text = await c.req.text();
  const form = await c.req.formData();
  const arrayBuffer = await c.req.arrayBuffer();

  // Parsed body (with validator)
  const body = c.req.valid("json");

  return c.json({ received: true });
});
```

## Response Types

```typescript
app.get("/responses", (c) => {
  // Text
  return c.text("Hello");

  // JSON
  return c.json({ data: "value" });

  // HTML
  return c.html("<h1>Hello</h1>");

  // Redirect
  return c.redirect("/other", 302);

  // Not Found
  return c.notFound();

  // Custom response
  return c.body("Raw body", 200, {
    "Content-Type": "text/plain",
  });

  // Status
  return c.json({ error: "Not found" }, 404);

  // Headers
  c.header("X-Custom", "value");
  return c.json({ ok: true });
});
```

## Middleware

```typescript
import { Hono } from "hono";

const app = new Hono();

// Global middleware
app.use("*", async (c, next) => {
  console.log(`${c.req.method} ${c.req.url}`);
  await next();
});

// Path-specific middleware
app.use("/api/*", async (c, next) => {
  const auth = c.req.header("Authorization");
  if (!auth) {
    return c.json({ error: "Unauthorized" }, 401);
  }
  await next();
});

// Multiple middleware
app.use("/admin/*", authMiddleware, adminMiddleware);

app.get("/api/data", (c) => c.json({ data: "protected" }));

export default app;
```

## Built-in Middleware

```typescript
import { Hono } from "hono";
import { cors } from "hono/cors";
import { logger } from "hono/logger";
import { basicAuth } from "hono/basic-auth";
import { bearerAuth } from "hono/bearer-auth";
import { compress } from "hono/compress";
import { etag } from "hono/etag";
import { secureHeaders } from "hono/secure-headers";

const app = new Hono();

// CORS
app.use("*", cors());
app.use("/api/*", cors({
  origin: "https://example.com",
  allowMethods: ["GET", "POST"],
}));

// Logger
app.use("*", logger());

// Basic Auth
app.use("/admin/*", basicAuth({
  username: "admin",
  password: "secret",
}));

// Bearer Token
app.use("/api/*", bearerAuth({
  token: "my-token",
}));

// Compression
app.use("*", compress());

// ETag
app.use("*", etag());

// Security headers
app.use("*", secureHeaders());

export default app;
```

## Validation with Zod

```typescript
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.email(),
  age: z.number().min(0).optional(),
});

app.post(
  "/users",
  zValidator("json", userSchema),
  (c) => {
    const user = c.req.valid("json");
    // user is typed and validated
    return c.json({ created: user });
  }
);

// Query validation
const querySchema = z.object({
  page: z.string().regex(/^\d+$/).optional(),
  limit: z.string().regex(/^\d+$/).optional(),
});

app.get(
  "/items",
  zValidator("query", querySchema),
  (c) => {
    const { page, limit } = c.req.valid("query");
    return c.json({ page, limit });
  }
);

export default app;
```

## Context Variables

```typescript
import { Hono } from "hono";

type Variables = {
  userId: string;
  isAdmin: boolean;
};

const app = new Hono<{ Variables: Variables }>();

app.use("*", async (c, next) => {
  c.set("userId", "123");
  c.set("isAdmin", true);
  await next();
});

app.get("/profile", (c) => {
  const userId = c.get("userId");
  const isAdmin = c.get("isAdmin");
  return c.json({ userId, isAdmin });
});

export default app;
```

## Error Handling

```typescript
import { Hono } from "hono";
import { HTTPException } from "hono/http-exception";

const app = new Hono();

// Throw HTTP error
app.get("/error", (c) => {
  throw new HTTPException(401, { message: "Unauthorized" });
});

// Global error handler
app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return err.getResponse();
  }
  console.error(err);
  return c.json({ error: "Internal Server Error" }, 500);
});

// Not found handler
app.notFound((c) => {
  return c.json({ error: "Not Found" }, 404);
});

export default app;
```

## RPC Mode (Type-safe Client)

```typescript
// server.ts
import { Hono } from "hono";
import { hc } from "hono/client";

const app = new Hono()
  .get("/users", (c) => c.json([{ id: 1, name: "Alice" }]))
  .post("/users", async (c) => {
    const body = await c.req.json();
    return c.json({ created: body });
  });

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 calls
const res = await client.users.$get();
const users = await res.json(); // Typed!

const created = await client.users.$post({
  json: { name: "Bob" },
});
```

## Common Errors

| Error | Cause | Fix |
|-------|-------|-----|
| `Route not found` | Wrong path | Check route registration |
| `Body already read` | Double parsing | Read body once |
| `Validator error` | Invalid input | Check schema definition |
| `Middleware order` | Wrong execution | Register middleware first |

## When to Load References

Load `references/middleware-list.md` when:
- Complete middleware reference
- Custom middleware patterns

Load `references/openapi.md` when:
- OpenAPI/Swagger integration
- API documentation generation

© secondsky · MIT · secondsky/claude-skills

Similar skills

All skills for Backend and APIs →

From the same set94

ml-model-training A skill that walks the agent through the full model training cycle: data prep, splitting, training and evaluation. Useful when you need a classifier or regressor without skipping steps. CX Codex +1 457installs payment-gateway-integration A skill for wiring Stripe, PayPal or Square into your app: payment intents, subscriptions, webhooks and refunds. Useful when you build checkout or billing. CX Codex +1 454installs api-reference-documentation Turns an OpenAPI spec into a developer-facing API reference: endpoints, auth, request and response examples. Useful for SDK docs and developer portals. CX Codex +1 454installs csrf-protection A skill that walks your agent through CSRF protection: synchronizer tokens, double-submit cookies and SameSite attributes. CX Codex +1 453installs interaction-design A skill for designing interface feedback: loading states, errors, empty screens, animation timing and accessibility. Useful when you need to plan how UI behaves, not just how it looks. CX Codex +1 441installs api-error-handling The skill sets a standard error response shape, an ApiError class and a circuit breaker. Useful once your API hits production. CX Codex +1 440installs security-headers-configuration Sets up HTTP security headers against XSS, clickjacking and MIME sniffing. Useful when hardening an app or preparing for an audit. CX Codex +1 438installs mutation-testing Mutates your code and reruns the tests to see which ones notice. Surviving mutants point at assertions that would let a real bug through. CX Codex +1 432installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor