Hono
Mount better-push on Hono - four lines, and nothing is adapted.
Hono speaks web standards, and so does better-push. c.req.raw is already a
Request and push.handler already returns a Response, so this integration
unwraps a context and stops.
import { Hono } from "hono";
import { toHonoHandler } from "@better-push/core/hono";
import { push } from "./push";
const app = new Hono();
app.all("/api/push/*", toHonoHandler(push));
export default app;That is the file this project's conformance suite boots and asserts against -
including the Server-Sent Events case, which streams here because the runtime
under Hono already streams a Response body.
basePath in the better-push config must match the mount path: the router
matches on the full pathname, not on what Hono stripped.
No hono dependency is added to your app by better-push. The context is typed
structurally as { req: { raw: Request } }.
Any runtime Hono runs on
Because nothing is adapted, better-push runs wherever Hono does - as long as the rest of your configuration does too:
| Runtime | Works | Caveat |
|---|---|---|
Node (@hono/node-server) | Yes | The reference setup. |
| Bun, Deno | Yes | pg and firebase-admin need Node APIs; check your driver and providers. |
| Cloudflare Workers, Vercel Edge | No | postgresAdapter needs pg, and apns() needs node:http2. |
Edge is a deliberate non-goal rather than an oversight: better-push talks to Postgres and to APNs over HTTP/2, and both want Node.
Mounting under a base path
const api = new Hono();
api.all("/push/*", toHonoHandler(push));
const app = new Hono();
app.route("/api", api);basePath is still /api/push here - the path the client requests - because
that is what the router sees.