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" + /> + +
+ ); +} +``` + +
+ +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

+
+
+
+
+ +
+
+
+

Realtime

+
+
+

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";
*/} - {/* -
-
-
-

Realtime

-
-
-

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.

@@ -116,10 +116,6 @@ TypeScript TypeScript - - Python - Python - Rust Rust @@ -161,7 +157,7 @@ LiveStore LiveStore - Available In June + Available In July ZeroSync @@ -182,129 +178,4 @@
- -
- -
-
-

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" + /> + +
+ ); +} + +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" + /> + +
+ ); +} ```
- +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);