Hono Integration
The @bext/hono package provides a Hono middleware that injects bext services into your request context, plus a standalone client for use outside of request handlers.
Installation#
npm install @bext/hono
# or
bun add @bext/hono
Peer dependencies: hono >= 4.0.0
Middleware#
Add the middleware to inject c.var.bext into all handlers:
import { Hono } from "hono";
import { bextMiddleware, type BextEnv } from "@bext/hono";
const app = new Hono<BextEnv>();
// Add bext services to all routes
app.use(bextMiddleware());
app.post("/api/products", async (c) => {
const product = await createProduct(c.req.json());
// Invalidate cached product pages
await c.var.bext.cache.invalidateTag("products");
// Notify connected clients
await c.var.bext.realtime.publish("products", { action: "created", product });
return c.json(product, 201);
});
export default app;
Custom Configuration#
app.use(bextMiddleware({
baseUrl: "http://127.0.0.1:3061", // SDK sidecar URL
appId: "my-app", // App identifier for multi-app isolation
}));
Standalone Client#
For use outside of request handlers (scripts, workers, etc.):
import { createBextClient } from "@bext/hono";
const bext = createBextClient();
// Same API as c.var.bext
await bext.cache.invalidateTag("products");
await bext.realtime.publish("updates", { type: "deploy" });
await bext.kv.set("config:feature-flags", { darkMode: true });
API Reference#
BextClient#
interface BextClient {
cache: BextCache;
realtime: BextRealtime;
kv: BextKv;
queue: BextQueue;
tasks: BextTasks;
}
Cache#
interface BextCache {
invalidateTag(tag: string): Promise<void>;
invalidatePath(path: string): Promise<void>;
}
Real-Time#
interface BextRealtime {
publish(topic: string, data: unknown): Promise<void>;
}
KV Store#
interface BextKv {
get<T = unknown>(key: string): Promise<T | null>;
set(key: string, value: unknown, opts?: { ttl?: number }): Promise<void>;
delete(key: string): Promise<void>;
}
Queues#
interface BextQueue {
push(name: string, payload: unknown, opts?: { delay?: number }): Promise<void>;
pull<T = unknown>(name: string): Promise<QueueMessage<T> | null>;
ack(name: string, id: string): Promise<void>;
}
interface QueueMessage<T = unknown> {
id: string;
data: T;
attempts: number;
}
Tasks#
interface BextTasks {
register(name: string, definition: { cron: string; command: string }): Promise<void>;
list(): Promise<TaskInfo[]>;
cancel(name: string): Promise<void>;
}
interface TaskInfo {
name: string;
cron: string;
command: string;
registeredAt: number;
lastRun: number | null;
}
Example: Full CRUD with Caching#
import { Hono } from "hono";
import { bextMiddleware, type BextEnv } from "@bext/hono";
const app = new Hono<BextEnv>();
app.use(bextMiddleware());
// List products (ISR-cached by bext, invalidated on mutation)
app.get("/api/products", async (c) => {
const products = await db.products.findMany();
return c.json(products);
});
// Create product — invalidate cache + push event
app.post("/api/products", async (c) => {
const data = await c.req.json();
const product = await db.products.create(data);
await c.var.bext.cache.invalidateTag("products");
await c.var.bext.realtime.publish("products", { action: "created", id: product.id });
return c.json(product, 201);
});
// Delete product — invalidate + event + queue cleanup job
app.delete("/api/products/:id", async (c) => {
const id = c.req.param("id");
await db.products.delete(id);
await c.var.bext.cache.invalidateTag("products");
await c.var.bext.cache.invalidatePath(`/products/${id}`);
await c.var.bext.realtime.publish("products", { action: "deleted", id });
await c.var.bext.queue.push("cleanup", { type: "product-assets", productId: id });
return c.json({ deleted: true });
});
export default app;
<div class="callout callout-tip"><div class="callout-label">Tip</div><div class="callout-body"><p><code>c.var.bext</code> is only available inside routes that run after <code>bextMiddleware()</code>. For scripts or background workers outside a request context, use <code>createBextClient()</code> instead.</p>
</div></div>
## Related
- [Frameworks overview](/frameworks/overview) — auto-detection rules and when to pick Hono vs PRISM
- [Express integration](/frameworks/express) — same services via `req.bext` middleware
- [Caching](/guides/caching) — how `invalidateTag` / `invalidatePath` interact with bext's edge cache
- [Durable flows](/guides/durable-flows) — orchestrating multi-step work via the queue
- [Scheduled tasks](/capabilities/scheduled) — registering cron tasks from Hono handlers
## Links
- [hono.dev](https://hono.dev) — Hono framework documentation