hono-api-scaffolder

Add structured API routes to an existing Cloudflare Workers project. This skill runs AFTER the project shell exists (via cloudflare-worker-builder or vite-flare-starter) and produces route files, middleware, and endpoint documentation.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "hono-api-scaffolder" with this command: npx skills add jezweb/claude-skills/jezweb-claude-skills-hono-api-scaffolder

Hono API Scaffolder

Add structured API routes to an existing Cloudflare Workers project. This skill runs AFTER the project shell exists (via cloudflare-worker-builder or vite-flare-starter) and produces route files, middleware, and endpoint documentation.

Workflow

Step 1: Gather Endpoints

Determine what the API needs. Either ask the user or infer from the project description. Group endpoints by resource:

Users: GET /api/users, GET /api/users/:id, POST /api/users, PUT /api/users/:id, DELETE /api/users/:id Posts: GET /api/posts, GET /api/posts/:id, POST /api/posts, PUT /api/posts/:id Auth: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me

Step 2: Create Route Files

One file per resource group. Use the template from assets/route-template.ts:

// src/routes/users.ts import { Hono } from 'hono' import { zValidator } from '@hono/zod-validator' import { z } from 'zod' import type { Env } from '../types'

const app = new Hono<{ Bindings: Env }>()

// GET /api/users app.get('/', async (c) => { const db = c.env.DB const { results } = await db.prepare('SELECT * FROM users').all() return c.json({ users: results }) })

// GET /api/users/:id app.get('/:id', async (c) => { const id = c.req.param('id') const user = await db.prepare('SELECT * FROM users WHERE id = ?').bind(id).first() if (!user) return c.json({ error: 'Not found' }, 404) return c.json({ user }) })

// POST /api/users const createUserSchema = z.object({ name: z.string().min(1), email: z.string().email(), })

app.post('/', zValidator('json', createUserSchema), async (c) => { const body = c.req.valid('json') // ... insert logic return c.json({ user }, 201) })

export default app

Step 3: Add Middleware

Based on project needs, add from assets/middleware-template.ts:

Auth middleware — protect routes requiring authentication:

import { createMiddleware } from 'hono/factory' import type { Env } from '../types'

export const requireAuth = createMiddleware<{ Bindings: Env }>(async (c, next) => { const token = c.req.header('Authorization')?.replace('Bearer ', '') if (!token) return c.json({ error: 'Unauthorized' }, 401) // Validate token... await next() })

CORS — use Hono's built-in:

import { cors } from 'hono/cors' app.use('/api/*', cors({ origin: ['https://example.com'] }))

Step 4: Wire Routes

Mount all route groups in the main entry point:

// src/index.ts import { Hono } from 'hono' import type { Env } from './types' import users from './routes/users' import posts from './routes/posts' import auth from './routes/auth' import { errorHandler } from './middleware/error-handler'

const app = new Hono<{ Bindings: Env }>()

// Global error handler app.onError(errorHandler)

// Mount routes app.route('/api/users', users) app.route('/api/posts', posts) app.route('/api/auth', auth)

// Health check app.get('/api/health', (c) => c.json({ status: 'ok' }))

export default app

Step 5: Create Types

// src/types.ts export interface Env { DB: D1Database KV: KVNamespace // if needed R2: R2Bucket // if needed API_SECRET: string // secrets }

Step 6: Generate API_ENDPOINTS.md

Document all endpoints. See references/endpoint-docs-template.md for the format:

POST /api/users

Create a new user.

  • Auth: Required (Bearer token)
  • Body: { name: string, email: string }
  • Response 201: { user: User }
  • Response 400: { error: string, details: ZodError }

Key Patterns

Zod Validation

Always validate request bodies with @hono/zod-validator :

import { zValidator } from '@hono/zod-validator' app.post('/', zValidator('json', schema), async (c) => { const body = c.req.valid('json') // fully typed })

Install: pnpm add @hono/zod-validator zod

Error Handling

Use the standard error handler from assets/error-handler.ts:

export const errorHandler = (err: Error, c: Context) => { console.error(err) return c.json({ error: err.message }, 500) }

API routes must return JSON errors, not redirects. fetch() follows redirects silently, then the client tries to parse HTML as JSON.

RPC Type Safety

For end-to-end type safety between Worker and client:

// Worker: export the app type export type AppType = typeof app

// Client: use hc (Hono Client) import { hc } from 'hono/client' import type { AppType } from '../worker/src/index'

const client = hc<AppType>('https://api.example.com') const res = await client.api.users.$get() // fully typed

Route Groups vs Single File

Project size Structure

< 10 endpoints Single index.ts with all routes

10-30 endpoints Route files per resource (routes/users.ts )

30+ endpoints Route files + shared middleware + typed context

Reference Files

When Read

Hono patterns, middleware, RPC references/hono-patterns.md

API_ENDPOINTS.md format references/endpoint-docs-template.md

Assets

File Purpose

assets/route-template.ts Starter route file with CRUD + Zod

assets/middleware-template.ts Auth middleware template

assets/error-handler.ts Standard JSON error handler

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

tailwind-v4-shadcn

No summary provided by upstream source.

Repository SourceNeeds Review
2.7K-jezweb
General

tanstack-query

No summary provided by upstream source.

Repository SourceNeeds Review
2.5K-jezweb
General

fastapi

No summary provided by upstream source.

Repository SourceNeeds Review
General

zustand-state-management

No summary provided by upstream source.

Repository SourceNeeds Review
1.2K-jezweb