# Hono Typescript

> Guidelines for building edge-first, high-performance APIs with Hono and TypeScript for Cloudflare Workers, Deno, Bun, and Node.js

- Skill: `itechmeat/hono-typescript` (Agent Skill)
- Install (CLI): `npx skillmds@latest add itechmeat/hono-typescript`
- Raw SKILL.md: https://api.skillmd.com/api/skills/itechmeat/hono-typescript/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: itechmeat (https://skillmd.com/u/itechmeat)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/itechmeat/hono-typescript

---


# Hono TypeScript Development

You are an expert in Hono and TypeScript development with deep knowledge of building ultrafast, edge-first APIs that run on Cloudflare Workers, Deno, Bun, and Node.js.

## TypeScript General Guidelines

### Basic Principles

- Use English for all code and documentation
- Always declare types for variables and functions (parameters and return values)
- Avoid using `any` type - create necessary types instead
- Use JSDoc to document public classes and methods
- Write concise, maintainable, and technically accurate code
- Use functional and declarative programming patterns; avoid classes
- Prefer iteration and modularization to adhere to DRY principles

### Nomenclature

- Use PascalCase for types and interfaces
- Use camelCase for variables, functions, and methods
- Use kebab-case for file and directory names
- Use UPPERCASE for environment variables
- Use descriptive variable names with auxiliary verbs: `isLoading`, `hasError`, `canDelete`
- Start each function with a verb

### Functions

- Write short functions with a single purpose
- Use arrow functions for handlers and middleware
- Prefer the RO-RO pattern: Receive an Object, Return an Object
- Use default parameters instead of null checks

### Types and Interfaces

- Prefer interfaces over types for object shapes
- Avoid enums; use maps or const objects instead for better type safety
- Use Zod for runtime validation with inferred types
- Use `readonly` for immutable properties
- Use `import type` for type-only imports

## Hono-Specific Guidelines

### Project Structure

```
src/
  routes/
    {resource}/
      index.ts
      handlers.ts
      validators.ts
  middleware/
    auth.ts
    cors.ts
    logger.ts
  services/
    {domain}Service.ts
  types/
    index.ts
  utils/
  config/
  index.ts
```

### App Initialization

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

// Type your environment bindings
type Bindings = {
  DB: D1Database;
  KV: KVNamespace;
  JWT_SECRET: string;
};

type Variables = {
  user: User;
};

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

### Routing

- Use method chaining for clean route definitions
- Group related routes with `app.route()`
- Use route parameters with proper typing

```typescript
const users = new Hono<{ Bindings: Bindings }>();

users.get("/", listUsers);
users.get("/:id", getUser);
users.post("/", zValidator("json", createUserSchema), createUser);
users.put("/:id", zValidator("json", updateUserSchema), updateUser);
users.delete("/:id", deleteUser);

app.route("/api/users", users);
```

### Middleware

- Use Hono's built-in middleware where available
- Create typed middleware for custom logic
- Chain middleware for composability

```typescript
import { cors } from "hono/cors";
import { logger } from "hono/logger";
import { jwt } from "hono/jwt";

app.use("*", logger());
app.use("/api/*", cors());
app.use("/api/*", jwt({ secret: "your-secret" }));

// Custom middleware
const authMiddleware = async (c: Context, next: Next) => {
  const user = await validateUser(c);
  c.set("user", user);
  await next();
};
```

### Request Validation with Zod

- Use `@hono/zod-validator` for request validation
- Define schemas for all request inputs
- Infer types from Zod schemas

```typescript
import { z } from "zod";
import { zValidator } from "@hono/zod-validator";

const createUserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
  role: z.enum(["user", "admin"]).default("user"),
});

type CreateUserInput = z.infer<typeof createUserSchema>;

app.post("/users", zValidator("json", createUserSchema), async (c) => {
  const data = c.req.valid("json");
  // data is typed as CreateUserInput
});
```

### Context and Response Handling

- Use typed context for better type safety
- Use helper methods for responses: `c.json()`, `c.text()`, `c.html()`
- Access environment bindings through context

```typescript
app.get("/users/:id", async (c) => {
  const id = c.req.param("id");
  const db = c.env.DB;

  const user = await db.prepare("SELECT * FROM users WHERE id = ?").bind(id).first();

  if (!user) {
    return c.json({ error: "User not found" }, 404);
  }

  return c.json(user);
});
```

### Error Handling

- Use Hono's `HTTPException` for expected errors
- Create global error handler middleware
- Return consistent error responses

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

// Throwing errors
if (!user) {
  throw new HTTPException(404, { message: "User 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);
});
```

### Cloudflare Workers Integration

- Use Workers KV for key-value storage
- Use D1 for SQL databases
- Use R2 for object storage
- Use Durable Objects for stateful applications

```typescript
// D1 Database
const result = await c.env.DB.prepare("SELECT * FROM users").all();

// KV Storage
await c.env.KV.put("key", "value");
const value = await c.env.KV.get("key");

// R2 Storage
await c.env.BUCKET.put("file.txt", content);
```

### Testing

- Use Hono's test client for integration tests
- Use Vitest or Jest as test runner
- Test handlers and middleware separately

```typescript
import { testClient } from "hono/testing";
import { describe, it, expect } from "vitest";

describe("User API", () => {
  const client = testClient(app);

  it("should list users", async () => {
    const res = await client.api.users.$get();
    expect(res.status).toBe(200);
    const data = await res.json();
    expect(Array.isArray(data)).toBe(true);
  });
});
```

### Performance

- Hono is ultrafast with minimal overhead
- Use streaming responses for large data
- Leverage edge caching with Cache API
- Use `hono/tiny` preset for minimal bundle size

### Security

- Use `hono/secure-headers` middleware
- Implement rate limiting
- Validate all inputs with Zod
- Use JWT for authentication
- Enable CORS appropriately

### Multi-Runtime Support

Hono runs on multiple runtimes. Configure appropriately:

```typescript
// Cloudflare Workers
export default app;

// Node.js
import { serve } from "@hono/node-server";
serve(app);

// Bun
export default app;

// Deno
Deno.serve(app.fetch);
```

