diff --git a/docs/docs.json b/docs/docs.json
index 743cc1ff5..c4bb8e139 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -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",
@@ -82,6 +89,7 @@
{
"group": "Integrations",
"pages": [
+ "integrations/better-auth",
{
"group": "Frameworks",
"pages": [
diff --git a/docs/integrations/better-auth.mdx b/docs/integrations/better-auth.mdx
new file mode 100644
index 000000000..c9711fedc
--- /dev/null
+++ b/docs/integrations/better-auth.mdx
@@ -0,0 +1,303 @@
+---
+title: Better Auth
+---
+
+
+
+
+```sh
+npm install better-auth
+```
+
+
+
+
+
+
+
+```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
+```
+
+
+
+
+ TODO: Exporting `registry` and `app.fetch` (as `default`) is important.
+
+
+_If you want to run without export fetch (i.e. standalone Node.js), see below._
+
+
+
+
+
+
+
+```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
+```
+
+
+
+
+
+
+
+
+
+```sh Node.js
+npx serve-fetch src/server.ts
+```
+
+```sh Bun
+bun serve src/server.ts
+```
+
+
+
+
+
+
+
+
+
+```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
+```
+
+
+
+
+
+
+
+
+
+
+
+
+```sh
+npx rivet-cli deploy src/server.ts
+```
+
+Your endpoint is now TODO
+
+Test it with TODO
+
+
+
+
+TODO
+
+
+
+
+```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...
+```
+
+
+
+
+
+```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...
+```
+
+
+
+
+
+
+
+
+
+## Configuration Options
+
+### Connect your frontend to the Rivet Worker
+
+TODO: Quick summary of why you would want to connect your frontend
+
+Connect your frontend:
+
+
+
+```ts JavaScript
+import { createClient } from "@rivetkit/worker/client";
+import type { registry } from "./registry.js";
+
+const client = createClient("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";
+import type { registry } from "./registry";
+
+const client = createClient(`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 (
+
+
Counter: {count}
+ setCounterName(e.target.value)}
+ placeholder="Counter name"
+ />
+ Increment
+
+ );
+}
+```
+
+
+
+TODO: Learn more under the XXXX docs
+
+
+ TODO: Link to onAuth docs
+
+
+
+ TODO: Note that `/registry` must be exposed
+
+
+### 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
+
+
+
+
+
+
+
+
diff --git a/docs/introduction.mdx b/docs/introduction.mdx
index 3d533c106..286ff6df4 100644
--- a/docs/introduction.mdx
+++ b/docs/introduction.mdx
@@ -25,8 +25,8 @@ import FAQ from "/snippets/landing-faq.mdx";
- Simply install one package to get up and running.
- Connect your database and scale to production.
+ Install one package to get up and running.
+ Scale seamlessly to production.
**Just a library, no SaaS.**
@@ -55,7 +55,7 @@ import FAQ from "/snippets/landing-faq.mdx";
*/}
-
+
@@ -63,8 +63,21 @@ import FAQ from "/snippets/landing-faq.mdx";
Workers
-
Stateful worker model for building reliable, scalable, and maintainable backend services.
-
Replaces Durable Objects , Orelans , or Akka
+
Long running tasks with state persistence, hibernation, and realtime
+
Replaces Durable Objects , Orleans , or Akka
+
+
+
+
+
+
+
+
+
Low-latency realtime collaboration for multiplayer experiences and collaborative apps powered by CRDT
+
Replaces Firebase Realtime , PartyKit , or Liveblocks
@@ -76,7 +89,7 @@ import FAQ from "/snippets/landing-faq.mdx";
Workflows
-
Distributed workflow engine for durable business processes.
+
Workflow library for durable, multi-step execution
Replaces Cloudflare Workflows , Temporal , or AWS Step Functions
@@ -95,19 +108,6 @@ import FAQ from "/snippets/landing-faq.mdx";
*/}
- {/*
-
-
-
-
Low-latency real-time communication for multiplayer experiences and collaborative apps.
-
Replaces Socket.IO , Pusher , or Firebase
-
-
-
- */}
{/*
@@ -122,7 +122,7 @@ import FAQ from "/snippets/landing-faq.mdx";
Durable State Without a Database
-
Your code's state is saved automatically—no database, ORM, or config needed. Just use regular JavaScript objects or SQLite (available in June).
+
Your code's state is saved automatically—no database, ORM, or config needed. Just use regular JavaScript objects or SQLite (available in July).
@@ -232,7 +232,7 @@ import FAQ from "/snippets/landing-faq.mdx";
Reconsider What Your Backend Can Do
-
Build powerful applications with RivetKit's comprehensive feature set.
+
Build powerful applications with RivetKit's libraries
diff --git a/docs/snippets/landing-snippets.mdx b/docs/snippets/landing-snippets.mdx
index 6de6fe579..f3ce0b059 100644
--- a/docs/snippets/landing-snippets.mdx
+++ b/docs/snippets/landing-snippets.mdx
@@ -91,7 +91,7 @@ import RateReact from "/snippets/examples/rate-react.mdx";
State
JavaScript
-
SQLiteAvailable In June
+
SQLiteAvailable In July
@@ -587,8 +587,4 @@ import RateReact from "/snippets/examples/rate-react.mdx";
-
-
- We're working on publishing full examples related to these snippets. If you find an error, please
create an issue .
-
diff --git a/docs/snippets/landing-tech.mdx b/docs/snippets/landing-tech.mdx
index ef94c894c..cdf1da552 100644
--- a/docs/snippets/landing-tech.mdx
+++ b/docs/snippets/landing-tech.mdx
@@ -1,9 +1,9 @@
-
Runs On Your Stack
-
Deploy RivetKit anywhere - from serverless platforms to your own infrastructure with our flexible runtime options.
-
Don't see the runtime you want? Add your own .
+
Runs Anywhere
+
Deploy RivetKit anywhere - from serverless platforms to your own infrastructure with RivetKit's flexible runtime options.
+
Don't see the runtime you want? Add your own .
-
-
-
-
-
-
Roadmap For 2025
-
We ship fast, so we want to share what you can expect to see before the end of the year.
-
Help shape our roadmap by creating issues and joining our Discord .
-
-
-
-
-
- SQLite Support
-
-
- SQLite in Studio
-
-
- Local-First Extensions
-
-
- Auth Extensions
-
-
- Workflows
-
-
- Queues
-
-
- MCP
-
-
- Worker-Worker Actions
-
-
- Cancellable Schedules
-
-
- Cron Jobs
-
-
- Drizzle Support
-
-
- Prisma v7 Support
-
-
- Read Replicas
-
-
- Middleware
-
-
- Schema Validation
-
-
- Vite Integration
-
-
- OpenTelemetry
-
-
- More Examples
-
-
- Studio
-
-
-
- File system driver
-
-
-
- Redis driver
-
-
-
- Bun support
-
-
-
- P2P topology
-
-
-
- React client
-
-
-
- Rust client
-
-
-
- Python client
-
-
-
- Resend Integration
-
-
-
- Vitest Integration
-
-
-
- Non-serialized state
-
-
-
- create-worker
-
-
-
- rivetkit dev
-
-
-
- Hono Integration
-
-
-
-
-
diff --git a/docs/workers/overview.mdx b/docs/workers/overview.mdx
index ae23ef28b..50b0a61c5 100644
--- a/docs/workers/overview.mdx
+++ b/docs/workers/overview.mdx
@@ -9,6 +9,13 @@ import CreateWorkerCli from "/snippets/create-worker-cli.mdx";
Workers combine compute and storage into unified entities for simplified architecture. Workers seamlessly integrate with your existing infrastructure or can serve as a complete standalone solution.
+## Quickstart
+
+
+
+
+
+
## Concepts
The core concepts that power Rivet Worker applications:
diff --git a/docs/workers/quickstart-frontend.mdx b/docs/workers/quickstart-frontend.mdx
new file mode 100644
index 000000000..f0e98d32b
--- /dev/null
+++ b/docs/workers/quickstart-frontend.mdx
@@ -0,0 +1,140 @@
+---
+title: React
+icon: react
+---
+
+
+
+
+```sh
+npm install rivetkit
+```
+
+
+
+
+```ts registry.ts
+import { worker, setup } from "rivetkit";
+
+export const counter = worker({
+ state: { count: 0 },
+ actions: {
+ increment: (c, x: number) => {
+ c.state.count += x;
+ return c.state.count;
+ },
+ },
+});
+
+export const registry = setup({
+ workers: { counter },
+});
+```
+
+TODO: important registry name
+
+
+
+
+
+```sh
+npx rivet-cli dev src/registry.ts
+```
+
+TODO: If you want to set up a custom backend server, see other quickstart
+
+
+
+
+
+```tsx
+import { useState } from "react";
+import { createClient, createRivetKit } from "@rivetkit/react";
+import type { Registry } from "../backend/registry";
+
+const client = createClient(`http://localhost:6420/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 (
+
+
Counter: {count}
+ setCounterName(e.target.value)}
+ placeholder="Counter name"
+ />
+ Increment
+
+ );
+}
+
+export default App;
+```
+
+
+
+
+
+
+
+
+
+```sh
+npx rivet-cli deploy src/registry.ts --frontend
+```
+
+Your endpoint is now TODO
+
+Test it with TODO
+
+
+
+
+TODO
+
+
+
+
+
+
+
+
+## Configuration options
+
+### Configure storage driver
+
+TODO: See backend
+
+### Add your own endpoints
+
+TODO: See backend & integrate with frontend
+
+### Run standalone server (no dev CLI)
+
+TODO: See backend
+
+## Next Steps
+
+
+
+
+
+
+
+
diff --git a/docs/workers/quickstart.mdx b/docs/workers/quickstart.mdx
index a74a812d1..6cc30d1db 100644
--- a/docs/workers/quickstart.mdx
+++ b/docs/workers/quickstart.mdx
@@ -1,170 +1,303 @@
---
-title: Quickstart
-icon: forward
-description: Start building awesome documentation in under 5 minutes
+title: Node.js & Bun
+icon: node-js
---
+
+
+
+```sh
+npm install @rivetkit/worker
+```
+
+
+
+
```ts registry.ts
-import { setup } from "rivetkit";
-import { worker } from "rivetkit/worker";
+import { worker, setup } from "@rivetkit/worker";
-const counter = worker({
- onAuth: async () => {
- // Allow public access
- },
- state: {
- count: 0,
- },
+export const counter = worker({
+ state: { count: 0 },
actions: {
- foo: (c) => c.state.count++,
+ increment: (c, x: number) => {
+ c.state.count += x;
+ return c.state.count;
+ },
},
});
-const myWorkflow = workflow({
- run: () => {}
+export const registry = setup({
+ workers: { counter },
});
+```
-const myRealtime = realtime({
- run: () => {}
-});
+
-const registry = setup({
- registry: { counter, myWorkflow, myRealtime },
-});
-export type Registry = typeof registry;
-```
+
-```ts server.ts
-// With router
+
+
+```ts Hono
import { registry } from "./registry";
+import { Hono } from "hono";
+import { serve } from "@hono/node-server";
+
+// Start RivetKit
+//
+// State is stored in memory, this can be configured later
+const { client, hono } = registry.run();
+// Setup server
const app = new Hono();
-app.route("/registry", c => registry.handler(c.req.raw));
-serve(app);
-// Without router
-import { serve } from "@rivetkit/node";
+// Expose RivetKit to the frontend (optional)
+app.route("/registry", hono);
-serve(registry);
-```
+app.post("/increment/:name", async (c) => {
+ const name = c.req.param("name");
-```ts client.ts
-import { createClient } from "rivetkit/client";
-import type { Registry } from "./registry";
+ // Communicate with actor
+ const counter = client.counter.getOrCreate(name);
+ const newCount = await counter.increment(1);
-const client = createClient("http://localhost:8080");
-```
+ return c.text(`New Count: ${newCount}`);
+});
-
-
+serve({ fetch: app.fetch, port: 8080 }, (x) =>
+ console.log("Listening at http://localhost:8080"),
+);
+```
-```sh
-npm install rivetkit/worker
+```ts Express.js
+TODO
```
-
-
+```ts Elysia.js
+TODO
+```
-```ts
-import { worker, setup } from "rivetkit";
+
-const myWorker = worker({
+
+ TODO: Exporting `registry` and `app.fetch` (as `default`) is important.
+
-});
-```
+_If you want to run without export fetch (i.e. standalone Node.js), see below._
-
+
-```ts Rivet
-// TODO:
-```
-```ts Cloudflare Workers
-// TODO:
+```sh Node.js
+npx serve-fetch src/server.ts
```
-```ts Redis
-// TODO:
+```sh Bun
+bun serve src/server.ts
```
-```ts Postgres
-// TODO:
-```
-
+
-```ts Hono
-const registry = new Hono();
-app.route("rivetkit", setup({ myWf, myWorker }));
-serve(registry);
+```ts fetch
+const res = await fetch("http://localhost:8080/increment/foo", {
+ method: "POST"
+});
+console.log("Output:", await res.text());
```
-```ts Express.js
-const registry = new Hono();
-app.route("rivetkit", setup({ myWf, myWorker }));
-serve(registry);
+```sh curl
+curl -X POST localhost:8080/increment/foo
```
+
-
+
+
+
+
+
+
+```json
+{
+ "rivetkit": {
+ "registry": "src/registry.ts",
+ "server": "src/server.ts"
+ }
+}
+```
```sh
-node src/server.ts
+npx rivet-cli deploy
```
-
+Your endpoint is now TODO
-
+Test it with TODO
-
+
+
+
+TODO
+
-```ts Node.js
-const client = createClient();
-client.myWf.getOrCreate().sendEvent("foo");
+
+
+```sh
+npm install @rivetkit/redis
```
-```ts React
-const client = createClient();
-client.myWf.getOrCreate().sendEvent("foo");
+```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...
```
-
+
+
+
+
+```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...
+```
+
+
+
+
-
+
+
+## Configuration Options
+
+### Connect your frontend to the Rivet Worker
+
+TODO: Quick summary of why you would want to connect your frontend
+
+Connect your frontend:
-```sh Rivet
-rivet deploy
+```ts JavaScript
+import { createClient } from "@rivetkit/worker/client";
+import type { registry } from "./registry.js";
+
+const client = createClient("http://localhost:8080/registry");
+
+const result = await client.myWorker.getOrCreate().myAction("Hello, world!");
```
-```sh Cloudflare Workers
-rivet deploy
+```ts React
+import { useState } from "react";
+import { createClient, createRivetKit } from "@@rivetkit/worker/react";
+import type { registry } from "./registry";
+
+const client = createClient(`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 (
+
+
Counter: {count}
+ setCounterName(e.target.value)}
+ placeholder="Counter name"
+ />
+ Increment
+
+ );
+}
```
-
+TODO: Learn more under the XXXX docs
-
+
+ TODO: Link to onAuth docs
+
+
+
+ TODO: Note that `/registry` must be exposed
+
+
+### 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
+
diff --git a/examples/rivet/rivet.json b/examples/rivet/rivet.json
index b821d3b1c..e6fb3275c 100644
--- a/examples/rivet/rivet.json
+++ b/examples/rivet/rivet.json
@@ -1,6 +1,6 @@
{
"rivetkit": {
"registry": "./src/registry.ts",
- "dockerfile": "Dockerfile"
+ "server": "./src/server.ts"
}
}
diff --git a/examples/rivet/scripts/client.ts b/examples/rivet/scripts/client.ts
index a8d79bf05..ce52868f5 100644
--- a/examples/rivet/scripts/client.ts
+++ b/examples/rivet/scripts/client.ts
@@ -1,13 +1,13 @@
import { createClient } from "rivetkit/client";
import { execSync } from "node:child_process";
-import type { Registry } from "../src/registry.js";
+import type { registry } from "../src/registry.js";
// Get endpoint from rivet kit
const endpoint = execSync("rivet kit endpoint", { encoding: "utf8" }).trim();
console.log("🔗 Using endpoint:", endpoint);
// Create RivetKit client
-const client = createClient(endpoint);
+const client = createClient(endpoint);
async function main() {
console.log("🚀 Rivet Client Demo");
@@ -39,4 +39,4 @@ async function main() {
}
}
-main().catch(console.error);
\ No newline at end of file
+main().catch(console.error);