Skip to content

RoninForge/roninforge-hono

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

roninforge-hono

License: MIT

Cursor plugin for Hono v4 (TypeScript edge web framework) + TypeScript. Pinned to hono ^4.12.19, @hono/zod-validator ^0.8.0, @hono/zod-openapi ^1.4.0 (peer zod ^4.x), @hono/node-server ^2.0.3 (Node 20+). Teaches the v4 APIs that LLMs trained on pre-2024 data do not know (c.json() always typed, validator throws HTTPException, getCookie/setCookie from hono/cookie, c.env as property, streamText from hono/streaming, showRoutes from hono/dev, getRuntimeKey from hono/adapter, fire(app) from hono/service-worker, Workers Static Assets binding instead of deprecated serveStatic, JSR @hono/hono for Deno). Catches 50+ LLM regressions with BAD / CORRECT TypeScript pairs.

No Hono v5 exists. Latest stable is v4.12.19. Any "v5" in generated code is hallucination.

The Problem

Hono's own maintainers filed Issue #3906 ("llm.txt file") and Issue #4812 ("Official AI Agent Skill for Hono") explicitly because "LLMs have basically no knowledge of how the latest Hono works." Pre-2025 training data is v3-era. LLMs emit:

v3 -> v4 removed APIs

  • c.jsonT() instead of c.json() (always typed since v4.0.0)
  • c.stream() / c.streamText() as Context methods (moved to hono/streaming in v4)
  • c.env() function form (now property; runtime detection via getRuntimeKey() from hono/adapter)
  • c.req.cookie() (removed; use getCookie(c) from hono/cookie)
  • app.showRoutes(), app.routerName (moved to hono/dev)
  • addEventListener('fetch') + app.handleEvent() (Service Worker syntax; use export default { fetch: app.fetch })
  • app.head(...) routes (HEAD auto-derived from GET in v4)
  • hono/nextjs import (use hono/vercel)
  • hono/middleware barrel import (use per-middleware subpath)
  • c.req.headers() / c.req.body() / c.req.signal() accessor methods (use c.req.raw.*)
  • FC with implicit children (use PropsWithChildren<P>)
  • app.fire() (deprecated v4.8.0; use fire(app) from hono/service-worker)
  • import { Hono } from 'https://deno.land/x/hono/mod.ts' on Deno (stale since v4.4.0; use jsr:@hono/hono)

Express / Koa / Fastify leakage (the biggest class)

  • Missing return on c.json() (resolves to undefined; v4 throws "Context is not finalized")
  • res.json() / res.send() instead of c.json() (no res in Hono)
  • (req, res, next) middleware signature (use (c, next))
  • (err, req, res, next) error middleware (use app.onError + HTTPException)
  • app.use(express.json()) body parser (Hono parses on demand via c.req.json())
  • import cors from 'cors' from npm (use hono/cors)
  • supertest for tests (use app.request() / testClient(app))
  • c.req.body as already parsed (it's a ReadableStream)
  • c.req.parseBody() for JSON (only form / multipart)
  • c.req.text() then c.req.json() (body consumed twice)
  • c.userId = ... inline assignment (use c.set('userId', ...) with typed Variables)

TypeScript / RPC inference mistakes

  • new Hono() without Bindings / Variables generics (c.env is {})
  • Routes defined as statements (app.get(...) then app.post(...)) - drops RPC types
  • Sub-app app.route() calls as statements - same rule
  • Rails-style controllers passing Context around (loses path-param inference, per Hono Best Practices)
  • app.use('/path', zValidator(...)) instead of as route arg (TS error: 'json' not assignable to 'never')
  • c.notFound() in RPC-consumed routes (cannot type on client)
  • new Response(JSON.stringify(...)) in RPC routes (client sees unknown)
  • hc<AppType>('/') relative URL (throws on $url())
  • Value-import of server app into client bundle (drags drizzle-orm, fs, native deps - the #1 RPC bundle-bloat pitfall)
  • Middleware without createMiddleware<Env> (Variables types do not propagate)

Cloudflare Workers gotchas

  • process.env.X in Workers code (undefined; use c.env.X with typed Bindings)
  • fs / path imports in Workers (no filesystem)
  • compatibility_flags: ["node_compat"] legacy flag (use nodejs_compat)
  • Deprecated serveStatic from hono/cloudflare-workers (since v4.3.0; use asset binding)
  • Missing c.executionCtx.waitUntil() for fire-and-forget
  • Truthy-check if (c.executionCtx) (getter throws on Bun and Next.js App Router)
  • Unawaited D1 .run() / .first() / .all() (insert cancelled when worker terminates)
  • WebSocket upgrade without Durable Object forwarding (state vanishes)

Security / production gaps

  • No secureHeaders() middleware
  • No csrf() on cookie-authenticated mutations
  • cors({ origin: '*', credentials: true }) (browsers silently drop; AJAX fails)
  • Missing bodyLimit() on POST / PUT routes and pin hono >= 4.9.7 for CVE-2025-59139
  • Cookies without httpOnly / secure / sameSite / path
  • sameSite: 'None' without secure: true (silently dropped)
  • Body-logging middleware without redaction (passwords / tokens / PII leak)
  • No etag() / cache() on static GETs
  • Hard-coded JWT secret string (leaks via bundle)
  • Building large JSON in memory instead of streamText (Workers 128MB cap)

Routing / structural bugs

  • Sub-app notFound handler (dead code; only top-level fires)
  • Trailing-slash inconsistency (/users vs /users/ are different routes by default)
  • await next() more than once (doubles downstream work)
  • app.use(prefix, mw) + app.route(prefix, subApp) overlap (middleware fires twice)
  • app.basePath('/api') as statement (prefix is thrown away from the type)

Runtime quietly-wrong

  • serve(app) on @hono/node-server (use serve({ fetch: app.fetch }))
  • export default app on Workers (use export default { fetch: app.fetch })
  • Bun.serve({ fetch: app }) (use app.fetch)

Smaller real issues

  • c.req.query() with no arg when expecting single value
  • c.req.param('id') in global middleware (undefined where :id isn't in path)
  • Hand-rolled OpenAPI without @hono/zod-openapi
  • cors() mounted AFTER routes (never matches)

Why this plugin (vs the existing community Hono rules)

A handful of Hono rules already live on cursor.directory and in awesome-cursorrules (PR #152): they cover c.json() returns, zValidator + Zod, c.env for Workers, chained routes for RPC, and app.fetch Workers export. They have three structural problems this plugin fixes:

  1. They do NOT cover the v3 -> v4 removed APIs. LLMs continue to emit c.jsonT, c.stream, c.env(), c.req.cookie, app.showRoutes, the hono/middleware barrel, and app.handleEvent - all removed in v4.0.0 (2024-02). Existing rules silently allow them.
  2. They omit the Express-leakage class. (req, res, next), (err, req, res, next), npm cors, app.use(express.json()), supertest, missing return on c.json - all happen constantly in LLM-generated Hono code. Existing rules treat them as one-offs.
  3. They miss security defaults and the CVE pin. None enforce secureHeaders() / csrf(); none mention bodyLimit CVE-2025-59139 (fix in v4.9.7); none address RPC client pitfalls (relative URL, value-import leakage, c.notFound typing).

This plugin ships:

  • 10 MDC rules with proper globs so the routes / RPC checks fire on src/routes/**, Workers checks on wrangler.{toml,jsonc} + Worker entry, security checks on middleware files, etc.
  • 59 documented anti-patterns with BAD / CORRECT TypeScript pairs
  • 5 skills: /hono-new-route, /hono-rpc-setup, /hono-cloudflare-workers-setup, /hono-migrate-to-v4, /hono-validate
  • 1 reviewer agent with severity grouping (CRITICAL / ERROR / WARN / NIT) and per-file checks
  • 2 fixture projects: correct-sample (gold-standard Hono 4.12.19 + Workers + D1 + Drizzle + Zod) and anti-pattern-sample (Hono v3 hangover with 25+ tracked violations)

Install

Copy the rules, skills, and agent into your project's Cursor configuration. Back up your existing files first; cp -r will overwrite same-named rules.

git clone https://github.com/RoninForge/roninforge-hono.git

# Use -n to avoid clobbering an existing customised rule of the same name.
cp -rn roninforge-hono/rules/*  your-project/.cursor/rules/
cp -rn roninforge-hono/skills/* your-project/.cursor/skills/
cp -rn roninforge-hono/agents/* your-project/.cursor/agents/

Or vendor the whole repo as a git submodule under your-project/.cursor/plugins/. Refer to the Cursor plugin docs for the current global-install path on your Cursor version.

What's Included

Rules (10 files)

Rule Scope (globs) What it does
hono-anti-patterns **/*.ts,**/*.js,**/*.tsx,**/*.jsx,wrangler.{toml,jsonc,json} 59 LLM regressions with BAD / CORRECT pairs, organized A-H by category (Express leakage, v3-era APIs, TypeScript / RPC, CF Workers, security, routing, runtime, smaller issues)
hono-core **/*.ts,**/*.tsx,**/*.js,**/*.jsx (alwaysApply) App init with typed Bindings + Variables, Context API, request accessors, middleware signature, built-in middleware list, cookie helpers, runtime detection
hono-routing-and-rpc src/**/*.ts,src/routes/**/*,src/api/**/*,src/server/**/*,src/client/**/*,routes/**/* Chained routes, sub-app composition, basePath immutability, double-execution overlap fix, sub-app notFound dead code, hc<AppType> setup, import type rule, typed base URL, $path(), TanStack Query / SWR integration, factory.createHandlers, RPC at 30+ routes mitigation
hono-validators src/**/*.ts,routes/**/*.ts,api/**/*.ts,handlers/**/*.ts @hono/zod-validator placement, c.req.valid() accessor, validator-throws-on-failure, @hono/zod-openapi (zod ^4 peer gotcha), @hono/standard-validator, @hono/valibot-validator, built-in hono/validator, decision tree
hono-cloudflare-workers src/**/*.ts,worker/**/*.ts,workers/**/*.ts,wrangler.{toml,jsonc,json},**/cloudflare-env.d.ts,**/worker-configuration.d.ts wrangler.jsonc canonical shape, compatibility flag rules, wrangler types, typed Bindings, c.env vs process.env, c.executionCtx.waitUntil + portability, Static Assets binding, D1 awaits, Drizzle + D1 stack, Hyperdrive + Prisma adapter gotcha, Durable Objects for WebSockets, hono/cache custom-domain rule, ES Module Worker export
hono-security src/**/*.ts,src/**/*.tsx,src/middleware/**/*.ts,src/auth/**/*.ts,src/index.ts,src/app.ts secureHeaders(), csrf(), CORS allow-list, bodyLimit() + CVE-2025-59139 pin floor 4.9.7, cookie defaults, JWT secret from c.env, logging without PII leaks, etag() + cache(), IP restriction, timeouts, request ID, auth library decision (Lucia deprecated; Better Auth / Clerk recommended), @sentry/hono over @hono/sentry
hono-error-handling src/**/*.ts,routes/**/*.ts,api/**/*.ts,middleware/**/*.ts,src/index.ts,src/app.ts HTTPException canonical throw, app.onError global handler, app.notFound top-level only, typed RPC errors via discriminated unions, validator throws, Sentry via @sentry/hono, structured logging with pino redaction, error response shape convention
hono-jsx **/*.tsx,**/*.jsx,**/jsx-runtime.ts,src/components/**/*,src/views/**/*,src/islands/**/*,app/islands/**/* hono/jsx server-side, tsconfig setup, FC does NOT include children, jsxRenderer middleware for layouts, hono/jsx/streaming with Suspense, hono/jsx/dom client components, HonoX islands, htmx integration, JSX SSR security pin floor 4.12.18
hono-testing **/*.test.ts,**/*.test.tsx,**/*.spec.ts,**/*.spec.tsx,vitest.config.{ts,js},**/test/**/*.ts,**/tests/**/*.ts,**/__tests__/**/*.ts app.request() universal pattern, testClient(app) typed RPC tests, Vitest + @cloudflare/vitest-pool-workers for real-runtime D1, applyD1Migrations fixture, Bun + bun:test, snapshot testing, middleware / validator / waitUntil testing, NEVER supertest
hono-deployment wrangler.{toml,jsonc,json},deno.json,deno.jsonc,package.json,Dockerfile,fly.toml,vercel.json,netlify.toml,**/serverless.yml,**/template.yaml Cloudflare Workers (wrangler.jsonc + compatibility flags), Bun.serve, Deno + JSR, @hono/node-server v2 (Node 20+), AWS Lambda + Lambda@Edge, Vercel Edge, Netlify, build pipelines, pin floors, common deployment mistakes

Skills (5 commands)

Skill Command What it does
New route /hono-new-route Scaffold a chained sub-app with zValidator as route argument, c.req.valid() typed access, c.json({ ... } as const, status) for typed RPC responses, Bindings + Variables generics, sub-app exported as typeof users, wired into parent with chained .route(). Refuses Rails-style controllers, c.notFound() in RPC routes, raw new Response().
RPC setup /hono-rpc-setup Scaffold the hc<AppType> client with import type (the load-bearing rule), absolute base URL, typed shared api module, TanStack Query / SWR integration via InferRequestType / InferResponseType, parseResponse utility, $path() method, IDE-slowdown mitigations for 30+ routes.
Workers setup /hono-cloudflare-workers-setup Scaffold a fresh Hono + Workers project with wrangler.jsonc (NOT .toml), nodejs_compat, typed Bindings generated from wrangler types, D1 + Drizzle middleware pattern, secureHeaders + cors + csrf + bodyLimit stack, Vitest config for @cloudflare/vitest-pool-workers.
Migrate to v4 /hono-migrate-to-v4 Stage-by-stage v3 -> v4 migration: bump pins (CVE-2025-59139 floor), replace c.jsonT / c.stream / c.env() / c.req.cookie / app.showRoutes / app.handleEvent, drop hono/middleware barrel, switch Deno to JSR, @hono/node-server v2 + Node 20+, register app.onError for validator throws.
Validate /hono-validate Run validate-plugin.sh + tsc --noEmit + tests + grep audit for syntactic anti-patterns the type checker won't catch (c.jsonT, c.req.cookie, process.env, node_compat, serveStatic from hono/cloudflare-workers, hard-coded JWT secret, sameSite:'None' without secure, missing bodyLimit, value-import on hc client).

Agent (1 subagent)

Agent What it does
hono-reviewer Reviews Hono v4 + TypeScript code by severity. CRITICAL: hono < 4.9.7 (CVE), v5 references (hallucination), cors wildcard + credentials, sameSite:'None' without secure, hard-coded JWT secret, process.env in Workers, missing bodyLimit, no csrf on cookie-auth, deprecated serveStatic, JSX SSR on < 4.12.18. ERROR: missing return on c.json, Express middleware shapes, all v3-era removed APIs, unchained routes / sub-apps, Rails controllers, zValidator placement, c.notFound/raw Response in RPC, relative URL hc(), value-import server app, unawaited D1, runtime export shapes. WARN: cookie defaults, secureHeaders, body-logging without redaction, app.onError, sub-app notFound, c.executionCtx truthy-check, no Bindings generic, cors after routes, middleware overlap, basePath statement, trailing slashes, hono/middleware barrel, wrangler.toml on greenfield, Lucia, @hono/sentry. NIT: missing satisfies ExportedHandler<Env>, hand-rolled OpenAPI, missing observability.enabled.

Fixtures

tests/fixtures/correct-sample/ is a slim Hono 4.12.19 + Cloudflare Workers + D1 + Drizzle + Zod project demonstrating the gold-standard shape: chained routes, typed RPC, zValidator as route arg, c.json({ ... } as const, status) typed responses, secureHeaders + cors + csrf + bodyLimit stack, app.onError + app.notFound at top-level, export default { fetch: app.fetch } satisfies ExportedHandler<Env>.

tests/fixtures/anti-pattern-sample/ is the inverse. Every file violates a numbered anti-pattern. package.json pins hono ^3.12.0 + cors ^2.8.5 + supertest ^6.3.0 + @hono/sentry ^1.0.0 + lucia ^3.2.0 on purpose - the v3 era is the LLM-training-data baseline for most pre-2025 models, plus deprecated companions that LLMs still recommend. Tracked violations include: missing return on c.json (#1), (req, res) Express handler shape (#2), (req, res, next) middleware (#3), (err, req, res, next) (#4), npm cors (#6), supertest (#12), c.jsonT (#13), addEventListener('fetch') + app.handleEvent (#15), c.req.cookie (#16), c.env() function call (#17), hono/middleware barrel (#20), app.head() (#23), no Bindings/Variables (#24), c.notFound in RPC route (#29), process.env in Workers (#34), node_compat flag (#36), serveStatic from hono/cloudflare-workers (#37), unawaited D1 (#40), cors * + credentials (#43), cookie without httpOnly/secure/sameSite/path (#45), sameSite:'None' without secure:true (#46), hard-coded JWT secret (#48), sub-app notFound (#50), basePath as statement (#53), export default app on Workers (#55), deprecated @hono/sentry + lucia references.

Versioning

Rules target hono ^4.12.19 with Node 20+ (when on Node), Bun latest, Deno latest, Wrangler ^4.0.0. Most patterns work back to Hono 4.0.0 (Feb 2024) with the deltas called out inline. Pin floors:

  • hono >= 4.9.7 mandatory - CVE-2025-59139 / GHSA-92vj-g62v-jqhh bodyLimit bypass fix
  • hono >= 4.12.18 mandatory if rendering JSX SSR - tag-name, attribute-name, CSS-injection hardening
  • @hono/node-server >= 2.0.0 requires Node 20+
  • @hono/zod-openapi >= 1.0.0 requires zod ^4.0.0 (peer is ^4.0.0 ONLY, not ^3.x)
  • compatibility_date >= "2024-09-23" required for nodejs_compat to imply nodejs_compat_v2

Where the rule cites a version (c.json() always typed since v4.0.0, c.text() typed since v4.3.0, JSR for Deno since v4.4.0, secureHeaders Permissions-Policy since v4.6.0, Standard Schema validator since v4.7.0, fire(app) since v4.8.0, JSR parseResponse since v4.9.0, typed base URL on hc since v4.11.0, $path() method since v4.12.0), verify against the changelog for the version you have installed before adopting.

License

MIT - see LICENSE

Links

About

Cursor plugin for Hono v4 (TypeScript edge web framework). 59 LLM regressions with BAD/CORRECT pairs. Pinned to hono ^4.12.19 (>= 4.9.7 for CVE-2025-59139). Covers Express middleware leakage, v3-era removed APIs, RPC inference traps, Cloudflare Workers gotchas, security defaults, JSX SSR hardening.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages