Skip to content
This repository was archived by the owner on Oct 22, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,14 @@
"group": "Workers",
"pages": [
"workers/overview",
{
"group": "Quickstart",
"icon": "forward",
"pages": [
"workers/quickstart",
"workers/quickstart-frontend"
]
},
"workers/state",
"workers/actions",
"workers/events",
Expand Down Expand Up @@ -82,6 +89,7 @@
{
"group": "Integrations",
"pages": [
"integrations/better-auth",
{
"group": "Frameworks",
"pages": [
Expand Down
303 changes: 303 additions & 0 deletions docs/integrations/better-auth.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
---
title: Better Auth
---

<Steps>
<Step title="Install">

```sh
npm install better-auth
```

</Step>

<Step title="Update server">

<CodeGroup>

```ts Hono
import { registry } from "./registry";
import { Hono } from "hono";

// Start RivetKit
//
// State is stored in memory, this can be configured later
const { client, hono } = registry.run();

// Setup server
const app = new Hono();

// Expose RivetKit to the frontend (optional)
app.route("/registry", hono);

app.post("/increment/:name", async (c) => {
const name = c.req.param("name");

// Communicate with actor
const counter = client.counter.getOrCreate(name);
const newCount = await counter.increment(1);

return c.text(`New Count: ${newCount}`);
});

// app.fetch will be used to run the server
export { registry, default: app.fetch };
```

```ts Express.js
TODO
```

```ts Elysia.js
TODO
```

</CodeGroup>

<Info>
TODO: Exporting `registry` and `app.fetch` (as `default`) is important.
</Info>

_If you want to run without export fetch (i.e. standalone Node.js), see below._

</Step>

<Step title="Integrate with RivetKit">

<CodeGroup>

```ts Worker
import { worker, setup } from "@rivetkit/worker";

export const counter = worker({
onAuth: () => { ... },
state: { count: 0 },
actions: {
increment: (c, x: number) => {
c.state.count += x;
return c.state.count;
},
},
});

export const registry = setup({
workers: { counter },
});
```

```ts Workflow
```

</CodeGroup>

</Step>

<Step title="Run server">

<CodeGroup>

```sh Node.js
npx serve-fetch src/server.ts
```

```sh Bun
bun serve src/server.ts
```

</CodeGroup>

</Step>

<Step title="Connect to backend">

<CodeGroup>

```ts fetch
const res = await fetch("http://localhost:8080/increment/foo", {
method: "POST"
});
console.log("Output:", await res.text());
```

```sh curl
curl -X POST localhost:8080/increment/foo
```

</CodeGroup>


</Step>

<Step title="Deploy">

<Tabs>

<Tab title="Rivet">

```sh
npx rivet-cli deploy src/server.ts
```

Your endpoint is now TODO

Test it with TODO

</Tab>

<Tab title="Cloudflare Workers">
TODO
</Tab>

<Tab title="Redis">

```sh
npm install @rivetkit/redis
```

```ts server.ts
import { registry } from "./registry";
import { createRedisDriver } from "@rivetkit/redis";

// Start RivetKit
const { client, hono } = registry.run({
driver: createRedisDriver({
host: "127.0.0.1",
port: 6379,
}),
});

// ...rest of code...
```

</Tab>

<Tab title="File System">

```sh
npm install @rivetkit/file-system
```

```ts server.ts
import { registry } from "./registry";
import { createFileSystemDriver } from "@rivetkit/file-system";

// Start RivetKit
const { client, hono } = registry.run({
driver: createFileSystemDriver(),
});

// ...rest of code...
```

</Tab>

</Tabs>

</Step>

</Steps>

## Configuration Options

### Connect your frontend to the Rivet Worker

TODO: Quick summary of why you would want to connect your frontend

Connect your frontend:

<CodeGroup>

```ts JavaScript
import { createClient } from "@rivetkit/worker/client";
import type { registry } from "./registry.js";

const client = createClient<typeof registry>("http://localhost:8080/registry");

const result = await client.myWorker.getOrCreate().myAction("Hello, world!");
```

```ts React
import { useState } from "react";
import { createClient, createRivetKit } from "@@rivetkit/worker/react";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There appears to be a typo in the import path - it contains an extra @ character. The import should be:

import { createClient, createRivetKit } from "@rivetkit/worker/react";

instead of:

import { createClient, createRivetKit } from "@@rivetkit/worker/react";

This would cause module resolution errors when running the code.

Suggested change
import { createClient, createRivetKit } from "@@rivetkit/worker/react";
import { createClient, createRivetKit } from "@rivetkit/worker/react";

Spotted by Diamond

Is this helpful? React 👍 or 👎 to let us know.

import type { registry } from "./registry";

const client = createClient<typeof registry>(`http://localhost:8080/registry`);
const { useWorker } = createRivetKit(client);

function App() {
const [count, setCount] = useState(0);
const [counterName, setCounterName] = useState("test-counter");

const counter = useWorker({
name: "counter",
key: [counterName],
});

counter.useEvent("newCount", (x: number) => setCount(x));

const increment = async () => {
await counter.connection?.increment(1);
};

return (
<div>
<h1>Counter: {count}</h1>
<input
type="text"
value={counterName}
onChange={(e) => setCounterName(e.target.value)}
placeholder="Counter name"
/>
<button onClick={increment}>Increment</button>
</div>
);
}
```

</CodeGroup>

TODO: Learn more under the XXXX docs

<Note>
TODO: Link to onAuth docs
</Note>

<Note>
TODO: Note that `/registry` must be exposed
</Note>

### Run as standalone server (no fetch handler)

TODO: Intro

```ts
import { registry } from "./registry";
import { Hono } from "hono";
import { serve } from "@hono/node-server";

// Start RivetKit
const { client, hono } = registry.run();

// Setup server
const app = new Hono();

// ...setup routes...

serve({ fetch: app.fetch, port: 8080 }, (x) =>
console.log("Listening at http://localhost:8080"),
);
```

IMPORTANT: You'll need to do special stuff to support deploying to Rivet or Cloudflare Workers

## Next Steps

TODO

<CardGroup>
<Card title="Overview" href="/concepts/overview" icon="square-plus" horizontal={true} />
<Card title="Interacting with Workers" href="/concepts/interacting-with-workers" icon="square-plus" horizontal={true} />
<Card title="Actions" href="/concepts/actions" icon="bolt" horizontal={true} />
<Card title="State" href="/concepts/state" icon="floppy-disk" horizontal={true} />
</CardGroup>

Loading
Loading