Summary
After PR #90 migrated the cloudflare-* templates from @cloudflare/workers-types to wrangler's dynamic wrangler types (which I think was the right call — config-aware types are genuinely more accurate), users who rely on Hono's type vending features hit immediate type errors after scaffolding, because worker-configuration.d.ts doesn't exist until wrangler types is manually run.
The README mentions cf-typegen, but missing this step results in silent breakage that's hard to diagnose, and easy to skip.
Reproduction
Using cloudflare-workers+vite (same applies to cloudflare-workers and cloudflare-pages):
pnpm create hono@latest hono-temp
# → choose cloudflare-workers+vite
cd hono-temp && pnpm install
pnpm add -D typescript
Replace src/index.tsx with a minimal type-vending example:
import { Hono } from 'hono'
import type { ExtractSchema } from 'hono/types'
const app = new Hono().get('/api/users', (c) => c.json({ users: [] }))
type AppSchema = ExtractSchema<typeof app>
const schemaCheck: { '/api/users': unknown } = {} as AppSchema
export default app
Run typecheck:
$ pnpm exec tsc --noEmit
src/index.tsx:8:7 - error TS2741: Property '"/api/users"' is missing in type 'BlankSchema'
but required in type '{ "/api/users": unknown; }'.
Hono's chain inference produces BlankSchema because no global Response/Request type is available in the project — tsconfig.json has only lib: ["ESNext"] and types: ["vite/client"].
Fix verification
$ pnpm cf-typegen
✨ Types written to worker-configuration.d.ts
$ pnpm exec tsc --noEmit
(no output, exit 0)
Once worker-configuration.d.ts is generated, type vending works as expected.
Why this matters
Real-world users who would hit this:
- Anyone using
hc<typeof app>() RPC client → client types resolve to unknown
- Anyone using
@hono/inertia's PageProps<'Foo'> → fails with Type 'X' does not satisfy the constraint 'never'
- Anyone running
tsc --noEmit in CI → CI fails on a fresh scaffold
For comparison, sibling templates handle this seamlessly out-of-the-box:
bun: @types/bun in devDependencies
nodejs / vercel: @types/node + types: ["node"]
cloudflare-*: nothing — relies on the user knowing to run cf-typegen
Possible approaches
I understand the rationale for PR #90 (config-aware types via wrangler types is more accurate), so I'm not suggesting reverting it. Instead, options to close the UX gap:
A. Add postinstall to template package.json
"scripts": {
"postinstall": "wrangler types --env-interface CloudflareBindings"
}
Pros:
- Covers initial install, teammate clones, CI environments, and
wrangler.jsonc updates
- Works across all package managers (npm/pnpm/yarn/bun)
- Smallest change — template-only, no
create-hono CLI changes
Cons:
postinstall failures abort install (e.g., on Node < 22)
B. Run wrangler types from create-hono CLI after install
Add a hook that runs wrangler types for cloudflare templates after install.
Pros:
Cons:
- Doesn't help when teammates clone and run
pnpm install
- Doesn't help when
wrangler.jsonc changes
- Requires changes to
create-hono itself
C. Hybrid: A + predev/prebuild
Combine A with predev/prebuild to also keep types fresh on every dev/build run.
Personally I lean toward A as the simplest fix with the broadest coverage. Happy to open a PR once direction is decided.
Side note: an additional UX gotcha during reproduction — wrangler types itself requires Node 22+. Users on Node 20 hit a secondary error (Wrangler requires at least Node.js v22.0.0) when manually running cf-typegen. Worth keeping in mind for the postinstall approach (postinstall would surface this earlier).
cc @yusukebe @Thomascogez (referencing PR #90 context)
Summary
After PR #90 migrated the
cloudflare-*templates from@cloudflare/workers-typesto wrangler's dynamicwrangler types(which I think was the right call — config-aware types are genuinely more accurate), users who rely on Hono's type vending features hit immediate type errors after scaffolding, becauseworker-configuration.d.tsdoesn't exist untilwrangler typesis manually run.The README mentions
cf-typegen, but missing this step results in silent breakage that's hard to diagnose, and easy to skip.Reproduction
Using
cloudflare-workers+vite(same applies tocloudflare-workersandcloudflare-pages):Replace
src/index.tsxwith a minimal type-vending example:Run typecheck:
Hono's chain inference produces
BlankSchemabecause no globalResponse/Requesttype is available in the project —tsconfig.jsonhas onlylib: ["ESNext"]andtypes: ["vite/client"].Fix verification
Once
worker-configuration.d.tsis generated, type vending works as expected.Why this matters
Real-world users who would hit this:
hc<typeof app>()RPC client → client types resolve tounknown@hono/inertia'sPageProps<'Foo'>→ fails withType 'X' does not satisfy the constraint 'never'tsc --noEmitin CI → CI fails on a fresh scaffoldFor comparison, sibling templates handle this seamlessly out-of-the-box:
bun:@types/bunin devDependenciesnodejs/vercel:@types/node+types: ["node"]cloudflare-*: nothing — relies on the user knowing to runcf-typegenPossible approaches
I understand the rationale for PR #90 (config-aware types via
wrangler typesis more accurate), so I'm not suggesting reverting it. Instead, options to close the UX gap:A. Add
postinstallto templatepackage.jsonPros:
wrangler.jsoncupdatescreate-honoCLI changesCons:
postinstallfailures abort install (e.g., on Node < 22)B. Run
wrangler typesfromcreate-honoCLI after installAdd a hook that runs
wrangler typesfor cloudflare templates after install.Pros:
package.jsoncleanCons:
pnpm installwrangler.jsoncchangescreate-honoitselfC. Hybrid: A +
predev/prebuildCombine A with
predev/prebuildto also keep types fresh on every dev/build run.Personally I lean toward A as the simplest fix with the broadest coverage. Happy to open a PR once direction is decided.
Side note: an additional UX gotcha during reproduction —
wrangler typesitself requires Node 22+. Users on Node 20 hit a secondary error (Wrangler requires at least Node.js v22.0.0) when manually runningcf-typegen. Worth keeping in mind for the postinstall approach (postinstall would surface this earlier).cc @yusukebe @Thomascogez (referencing PR #90 context)