diff --git a/examples/hono-bun/README.md b/examples/hono-bun/README.md index 8fed209f0..9638b7bde 100644 --- a/examples/hono-bun/README.md +++ b/examples/hono-bun/README.md @@ -1,6 +1,6 @@ # Hono + Bun Integration for RivetKit -Example project demonstrating Hono web framework with Bun runtime integration with [RivetKit](https://rivetkit.org). +Example project demonstrating Hono web framework with Bun runtime and React frontend integration with [RivetKit](https://rivetkit.org). [Learn More →](https://github.com/rivet-dev/rivetkit) @@ -26,7 +26,11 @@ npm install npm run dev ``` -Test the server by running: +This will start both the backend server (on port 8080) and the frontend dev server (on port 5173). + +Open your browser to [http://localhost:5173](http://localhost:5173) to see the counter application. + +You can also test the server directly by running: ```sh curl -X POST http://localhost:8080/increment/test diff --git a/examples/hono-bun/package.json b/examples/hono-bun/package.json index 474191500..51a39776f 100644 --- a/examples/hono-bun/package.json +++ b/examples/hono-bun/package.json @@ -4,17 +4,29 @@ "private": true, "type": "module", "scripts": { - "dev": "bun --watch src/server.ts", + "dev": "concurrently \"npm run dev:backend\" \"npm run dev:frontend\"", + "dev:backend": "bun --watch src/backend/server.ts", + "dev:frontend": "vite", + "build": "vite build", "check-types": "tsc --noEmit", "connect": "tsx scripts/connect.ts" }, "devDependencies": { "@types/bun": "^1.1.15", + "@types/react": "^18.2.0", + "@types/react-dom": "^18.2.0", + "@vitejs/plugin-react": "^4.2.0", + "concurrently": "^8.2.2", "rivetkit": "workspace:*", - "typescript": "^5.5.2" + "tsx": "^3.12.7", + "typescript": "^5.5.2", + "vite": "^5.0.0" }, "dependencies": { - "hono": "^4.7.0" + "@rivetkit/react": "workspace:*", + "hono": "^4.7.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" }, "keywords": [ "rivetkit", diff --git a/examples/hono-bun/src/registry.ts b/examples/hono-bun/src/backend/registry.ts similarity index 85% rename from examples/hono-bun/src/registry.ts rename to examples/hono-bun/src/backend/registry.ts index 3e3d61c37..4afe732a3 100644 --- a/examples/hono-bun/src/registry.ts +++ b/examples/hono-bun/src/backend/registry.ts @@ -5,6 +5,7 @@ export const counter = actor({ actions: { increment: (c, x: number) => { c.state.count += x; + c.broadcast("newCount", c.state.count); return c.state.count; }, }, diff --git a/examples/hono-bun/src/server.ts b/examples/hono-bun/src/backend/server.ts similarity index 84% rename from examples/hono-bun/src/server.ts rename to examples/hono-bun/src/backend/server.ts index 0cb8ffa96..77cc48b7e 100644 --- a/examples/hono-bun/src/server.ts +++ b/examples/hono-bun/src/backend/server.ts @@ -1,5 +1,6 @@ import { Hono } from "hono"; import { upgradeWebSocket, websocket } from "hono/bun"; +import { cors } from "hono/cors"; import { registry } from "./registry"; const { client, fetch } = registry.start({ @@ -10,11 +11,22 @@ const { client, fetch } = registry.start({ overrideServerAddress: "http://localhost:8080/rivet", // Specify Hono-specific upgradeWebSocket getUpgradeWebSocket: () => upgradeWebSocket, + cors: { + origin: "http://localhost:5173", + }, }); // Setup router const app = new Hono(); +app.use( + "*", + cors({ + origin: "http://localhost:5173", + credentials: true, + }), +); + app.use("/rivet/*", async (c) => { return await fetch(c.req.raw, c.env); }); diff --git a/examples/hono-bun/src/frontend/App.tsx b/examples/hono-bun/src/frontend/App.tsx new file mode 100644 index 000000000..dd797ab90 --- /dev/null +++ b/examples/hono-bun/src/frontend/App.tsx @@ -0,0 +1,37 @@ +import { createClient, createRivetKit } from "@rivetkit/react"; +import { useState } from "react"; +import type { registry } from "../backend/registry"; + +const client = createClient("http://localhost:8080/rivet"); +const { useActor } = createRivetKit(client); + +function App() { + const [count, setCount] = useState(0); + const [counterName, setCounterName] = useState("test-counter"); + + const counter = useActor({ + name: "counter", + key: [counterName], + }); + + counter.useEvent("newCount", (x: number) => setCount(x)); + + const increment = async () => { + await counter.connection?.increment(1); + }; + + return ( +
+

Counter: {count}

+ setCounterName(e.target.value)} + placeholder="Counter name" + /> + +
+ ); +} + +export default App; diff --git a/examples/hono-bun/src/frontend/index.html b/examples/hono-bun/src/frontend/index.html new file mode 100644 index 000000000..991f099ab --- /dev/null +++ b/examples/hono-bun/src/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + Hono Bun Counter + + +
+ + + diff --git a/examples/hono-bun/src/frontend/main.tsx b/examples/hono-bun/src/frontend/main.tsx new file mode 100644 index 000000000..6d0ba7949 --- /dev/null +++ b/examples/hono-bun/src/frontend/main.tsx @@ -0,0 +1,9 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/examples/hono-bun/vite.config.ts b/examples/hono-bun/vite.config.ts new file mode 100644 index 000000000..2abc7c6f8 --- /dev/null +++ b/examples/hono-bun/vite.config.ts @@ -0,0 +1,13 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react()], + root: "src/frontend", + build: { + outDir: "../../dist", + }, + server: { + host: "0.0.0.0", + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 687978838..d31d3ed7e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -621,19 +621,46 @@ importers: examples/hono-bun: dependencies: + '@rivetkit/react': + specifier: workspace:* + version: link:../../packages/react hono: specifier: 4.9.8 version: 4.9.8 + react: + specifier: ^18.3 + version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) devDependencies: '@types/bun': specifier: ^1.1.15 - version: 1.2.23(@types/react@19.1.8) + version: 1.2.23(@types/react@18.3.23) + '@types/react': + specifier: ^18.2.0 + version: 18.3.23 + '@types/react-dom': + specifier: ^18.2.0 + version: 18.3.7(@types/react@18.3.23) + '@vitejs/plugin-react': + specifier: ^4.2.0 + version: 4.5.2(vite@5.4.19(@types/node@24.6.2)(lightningcss@1.30.2)(terser@5.44.0)) + concurrently: + specifier: ^8.2.2 + version: 8.2.2 rivetkit: specifier: workspace:* version: link:../../packages/rivetkit + tsx: + specifier: ^3.12.7 + version: 3.14.0 typescript: specifier: ^5.5.2 version: 5.8.3 + vite: + specifier: ^5.0.0 + version: 5.4.19(@types/node@24.6.2)(lightningcss@1.30.2)(terser@5.44.0) examples/hono-react: dependencies: @@ -10162,9 +10189,9 @@ snapshots: '@types/connect': 3.4.38 '@types/node': 22.15.32 - '@types/bun@1.2.23(@types/react@19.1.8)': + '@types/bun@1.2.23(@types/react@18.3.23)': dependencies: - bun-types: 1.2.23(@types/react@19.1.8) + bun-types: 1.2.23(@types/react@18.3.23) transitivePeerDependencies: - '@types/react' @@ -10894,10 +10921,16 @@ snapshots: node-gyp-build: 4.8.4 optional: true + bun-types@1.2.23(@types/react@18.3.23): + dependencies: + '@types/node': 22.15.32 + '@types/react': 18.3.23 + bun-types@1.2.23(@types/react@19.1.8): dependencies: '@types/node': 22.15.32 '@types/react': 19.1.8 + optional: true bundle-require@5.1.0(esbuild@0.25.5): dependencies: