# Hono

> Mount the pipedog WebRTC offer and WebSocket endpoints in a Hono app on Bun.

Source: https://polvallverdu.github.io/pipedog/docs/frameworks/hono/



Hono routes the offer, and upgrades `/ws` with its own WebSocket helper and pipedog's Hono adapter,
`honoWebsocket`. This snippet runs on Bun.

## Install [#install]

```bash
bun add @pipedog/core @pipedog/asyncio @pipedog/transport-smallwebrtc @pipedog/transport-websocket @pipedog/serializer-protobuf @pipedog/openai @pipedog/audio-silero @pipedog/audio-smart-turn hono
```

`@pipedog/audio-smart-turn` isn't imported anywhere: the default turn strategies load it. To run
the snippet from a checkout instead, see [Installation](https://polvallverdu.github.io/pipedog/docs/installation/#from-source).

## Files [#files]

The endpoints come from the shared module on the [overview](https://polvallverdu.github.io/pipedog/docs/frameworks/#the-two-endpoints).
`voice.ts` re-exports it:

```ts title="voice.ts"
export { offer, runSocketAgent, socket } from "../shared/voice.ts";

```

```ts title="app.ts"
import { honoWebsocket } from "@pipedog/transport-websocket/hono";
import { Hono } from "hono";
import { upgradeWebSocket, websocket } from "hono/bun";
import { offer, runSocketAgent } from "./voice.ts";

const app = new Hono();

app.post("/api/offer", (c) => offer(c.req.raw));
app.get(
  "/ws",
  upgradeWebSocket(() => honoWebsocket(runSocketAgent)),
);

// Bun serves the app; on Node, use @hono/node-server with the same routes.
export default { fetch: app.fetch, websocket };

```

## Run it [#run-it]

```bash
OPENAI_API_KEY=sk-... bun app.ts
```

Bun serves the default export on port 3000, or on `$PORT`. The offer is at `POST /api/offer` and the
WebSocket at `/ws`.

## Other runtimes [#other-runtimes]

* **Node.** Serve the app with `@hono/node-server`, with the same routes. `hono/bun`'s
  `upgradeWebSocket` is Bun only, so use Hono's Node WebSocket helper (`@hono/node-ws`) with
  `honoWebsocket` for `/ws`, or serve `socket` on its own with `serveFetch(socket, { port })` from
  `@pipedog/transport-websocket/serve`, which upgrades on Node with the `ws` package.
* **Cloudflare Workers.** `socket` is a fetch handler that Workers can upgrade, so mount it directly,
  without the Bun helper: `app.get("/ws", (c) => socket(c.req.raw))`. Leave the offer, and the
  WebRTC transport, out of a Workers build: Workers have no UDP. A session that should outlive one
  request belongs in a Durable Object; see [Cloudflare Workers](https://polvallverdu.github.io/pipedog/docs/frameworks/cloudflare-workers.md).

## Deploy [#deploy]

Run it as a long-lived Bun process. The offer's media runs over UDP, so a serverless host can't carry
it.

## Authentication [#authentication]

Neither route has auth. Wrap `offer` and the socket route with a session check before they run, as
in [Authentication](https://polvallverdu.github.io/pipedog/docs/frameworks/#authentication). Hono middleware on both routes works too.
