Hono template
The hono template generates a TypeScript backend built on Hono. It is the only backend template that can be promoted to Cloudflare Workers, and it runs in a container locally exactly like any other service.
blissful-infra service add orders --type backend --template honoWhy this template exists
Section titled “Why this template exists”Cloudflare Workers execute Web-standard fetch handlers on a V8 isolate. There is no JVM and no CPython, so spring-boot and lambda-python can never run there. If you want a service that rehearses locally and ships to production, this is the template.
One source, two homes
Section titled “One source, two homes”The source is split so the same application runs under Node in a container and on Workers:
| File | Role |
|---|---|
src/app.ts | The application. Imports nothing from node:*, which is what makes it portable |
src/server.ts | Node entry via @hono/node-server, listening on 8080 to match the Rollout’s containerPort. This is what the container image runs |
src/worker.ts | Default-exports the app, which is already a Workers fetch handler |
The node:* constraint on app.ts is the whole trick. Keep your application logic there and it stays deployable to both. Anything that genuinely needs Node APIs belongs in server.ts.
Layout
Section titled “Layout”<service>/├── package.json├── tsconfig.json├── wrangler.jsonc # Workers config├── Dockerfile # container image for compose / kubernetes└── src/ ├── app.ts # the application (no node:* imports) ├── app.test.ts # vitest ├── server.ts # Node entry, port 8080 └── worker.ts # Workers entryRoutes it ships with
Section titled “Routes it ships with”| Route | Purpose |
|---|---|
GET /health | Probed by the Argo Rollout and the Docker healthcheck |
GET / | Service identity JSON |
GET /api/hello?name= | A trivial example handler |
Note the health path is /health, not /actuator/health. The Rollout manifest renders the probe path per template, so this is wired correctly without any action from you.
Scripts
Section titled “Scripts”npm run dev # tsx watch on src/server.ts (Node)npm run dev:worker # wrangler dev (Workers runtime locally)npm run build # tscnpm test # vitestnpm run typecheck # tsc --noEmitdev:worker is worth knowing about: it runs your service on the actual Workers runtime locally, which catches node:* leakage before a deploy does.
Running locally
Section titled “Running locally”Same as any other service, on either runtime:
blissful-infra service up ordersblissful-infra service logs ordersOn a --runtime kubernetes project, service up delegates to deploy and the service goes through a canary rollout like anything else.
Promoting to Cloudflare
Section titled “Promoting to Cloudflare”npm install -g wrangler@latestwrangler loginblissful-infra deploy orders --target cloudflareThe worker name defaults to <project>-<service>. Configuration is optional; to override it or to declare D1 and KV bindings, add a deploy.cloudflare block to service.yaml.
What changes in production
Section titled “What changes in production”A promoted service is not in your project’s Docker network, so:
- No Kafka. The project’s event bus is unreachable from Workers.
- No shared Postgres. Use D1 instead, declared as
d1Databaseinservice.yaml. - No progressive delivery. Pages and Workers deploys are not canaried; rollback is
wrangler rollback.
The data layer therefore differs between the local rehearsal and production, and nothing migrates schemas between them. Worth designing around rather than discovering later.
See also
Section titled “See also”deploy: both deploy targetsservice: adding and running services- Templates overview