From db06d08de17cd7e2f6207b09b383ba9e2475d781 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Fri, 12 Jun 2026 13:17:09 -0700 Subject: [PATCH 1/3] [SLOP(claude-opus-4-8-medium)] fix(rivetkit-wasm): add missing inspector_tabs field to ActorConfigInput conversion --- rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs b/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs index 187ce756d8..b0ce74520b 100644 --- a/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs +++ b/rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs @@ -239,6 +239,9 @@ impl From for ActorConfigInput { .map(|action| rivetkit_core::ActionDefinition { name: action.name }) .collect() }), + // Custom inspector tabs serve assets from a filesystem `root`, which is a + // native/server feature that has no meaning in a browser wasm host. + inspector_tabs: None, } } } From a75f1c023634c132cabca9427c843b9b4d9a5327 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Fri, 12 Jun 2026 13:19:59 -0700 Subject: [PATCH 2/3] [SLOP(claude-opus-4-8-medium)] docs(quickstart): clean up rust quickstart to import shared actor and auto-download engine --- .../content/docs/actors/quickstart/rust.mdx | 126 +++++++++--------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/website/src/content/docs/actors/quickstart/rust.mdx b/website/src/content/docs/actors/quickstart/rust.mdx index e411f7ef60..dc106d5859 100644 --- a/website/src/content/docs/actors/quickstart/rust.mdx +++ b/website/src/content/docs/actors/quickstart/rust.mdx @@ -7,7 +7,7 @@ skill: true import { Hosting } from "@/components/docs/Hosting"; -Rust support is in preview. The supported public Rust API is `rivetkit` and `rivetkit-client`; lower-level crates are internal implementation details and do not carry a stability guarantee. +Rust support is in preview. The supported public Rust API is `rivetkit` and `rivetkit-client`; lower-level crates are internal implementation details and do not carry a stability guarantee. See the full API reference on [docs.rs/rivetkit](https://docs.rs/rivetkit). ## Steps @@ -15,7 +15,7 @@ Rust support is in preview. The supported public Rust API is `rivetkit` and `riv -Add the `rivetkit` crate: +Add the `rivetkit` crate and its companions: ```sh cargo add rivetkit@2.3.0-rc.12 anyhow async-trait @@ -25,11 +25,11 @@ cargo add tokio --features full - + -An actor is a type that implements `Actor`, plus one `Handles` implementation for each action. Persisted state lives in `type State`; ephemeral runtime state is just fields on your actor struct. +Put the actor in `src/lib.rs` so both your server and your client can share the same types. An actor is a type that implements `Actor`, plus one `Handles` implementation for each action. Persisted state lives in `type State`; ephemeral runtime state is just fields on your actor struct. -```rust src/main.rs +```rust src/lib.rs use std::{future::Future, pin::Pin, sync::Arc}; use async_trait::async_trait; @@ -38,16 +38,16 @@ use serde::{Deserialize, Serialize}; type BoxFuture = Pin> + Send>>; -struct Counter; +pub struct Counter; #[derive(Default, Serialize, Deserialize)] -struct CounterState { - count: i64, +pub struct CounterState { + pub count: i64, } #[derive(Serialize, Deserialize)] -struct Increment { - amount: i64, +pub struct Increment { + pub amount: i64, } impl Action for Increment { @@ -57,8 +57,8 @@ impl Action for Increment { } #[derive(Serialize, Deserialize)] -struct NewCount { - count: i64, +pub struct NewCount { + pub count: i64, } impl Event for NewCount { @@ -101,27 +101,44 @@ impl Handles for Counter { } } -#[tokio::main] -async fn main() -> Result<()> { +pub fn registry() -> Registry { let mut registry = Registry::new(); registry.register_actor::("counter"); - registry.start().await + registry +} +``` + + + + + +Your `src/main.rs` just starts the registry from the library: + +```rust src/main.rs +#[tokio::main] +async fn main() -> anyhow::Result<()> { + counter::registry().start().await } ``` +Replace `counter` with your crate name (the package `name` in `Cargo.toml`, with dashes as underscores). + -The Rust runtime connects to the Rivet Engine. Build the engine binary once, then start your server. `RIVET_ENGINE_BINARY_PATH` tells the runtime where to find the engine; it spawns or reuses a local engine at `http://localhost:6420`. +The Rust runtime connects to the Rivet Engine. Setting `RIVETKIT_ENGINE_AUTO_DOWNLOAD=1` lets the runtime download and cache a matching engine binary the first time you run, so there is nothing else to install: ```sh -cargo build -p rivet-engine -RIVET_ENGINE_BINARY_PATH=./target/debug/rivet-engine cargo run +RIVETKIT_ENGINE_AUTO_DOWNLOAD=1 cargo run ``` Your server now connects to the Rivet Engine on `http://localhost:6420`. Clients connect directly to the engine on this port. + +Already have an engine binary? Set `RIVET_ENGINE_BINARY_PATH=/path/to/rivet-engine` to point at it instead. If you are working inside the [Rivet monorepo](https://github.com/rivet-dev/rivet), a local `cargo build -p rivet-engine` is discovered automatically from `target/debug`. + + @@ -132,55 +149,15 @@ This code can run either in your frontend or within your backend: -```rust src/client.rs -use anyhow::Result; +Add a `src/bin/client.rs` that imports the same actor types from your library. There is no need to redefine the actor on the client. + +```rust src/bin/client.rs +use counter::{Counter, Increment, NewCount}; use rivetkit::{ - client::{Client, ClientConfig, GetOrCreateOptions}, + client::{Client, ClientConfig}, prelude::*, TypedClientExt, }; -use serde::{Deserialize, Serialize}; - -struct Counter; - -#[derive(Serialize, Deserialize)] -struct Increment { - amount: i64, -} - -impl Action for Increment { - type Output = i64; - - const NAME: &'static str = "increment"; -} - -#[derive(Serialize, Deserialize)] -struct NewCount { - count: i64, -} - -impl Event for NewCount { - const NAME: &'static str = "newCount"; -} - -impl Actor for Counter { - type State = (); - type Input = (); - type Actions = (Increment,); - type Events = (NewCount,); - type Queue = (); - type ConnParams = (); - type ConnState = (); - type Action = action::Raw; -} - -impl Handles for Counter { - type Future = std::future::Ready>; - - fn handle(self: std::sync::Arc, _ctx: Ctx, _action: Increment) -> Self::Future { - unreachable!("client-only type marker") - } -} #[tokio::main] async fn main() -> Result<()> { @@ -200,6 +177,12 @@ async fn main() -> Result<()> { } ``` +With the server still running, start the client in another terminal: + +```sh +cargo run --bin client +``` + See the [`hello-world-rust`](https://github.com/rivet-dev/rivet/tree/main/examples/hello-world-rust) example for a complete runnable counter. @@ -276,3 +259,20 @@ See the [React documentation](/docs/clients/react) for more information. + +## Next Steps + + + + Full `rivetkit` crate documentation on docs.rs. + + + Define the RPC surface clients call on your actor. + + + Persist and load actor state across sleeps and restarts. + + + Broadcast realtime updates to connected clients. + + From 8a4114fcd2bfa76b966af67d01dacdd1ea4a5139 Mon Sep 17 00:00:00 2001 From: Nathan Flurry Date: Fri, 12 Jun 2026 13:22:35 -0700 Subject: [PATCH 3/3] [SLOP(claude-opus-4-8-medium)] docs(inspector-tabs): mark illustrative type-shape snippets as @nocheck --- website/src/content/docs/actors/inspector-tabs.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/website/src/content/docs/actors/inspector-tabs.mdx b/website/src/content/docs/actors/inspector-tabs.mdx index 3d21060889..1c31a56533 100644 --- a/website/src/content/docs/actors/inspector-tabs.mdx +++ b/website/src/content/docs/actors/inspector-tabs.mdx @@ -105,7 +105,7 @@ Each entry in `inspector.tabs[]` is either a **custom tab** or a ### Custom tab -```ts +```ts @nocheck { id: string, // URL-safe id: /^[A-Za-z0-9_-]+$/ label: string, // Shown in the tab strip @@ -125,7 +125,7 @@ Each entry in `inspector.tabs[]` is either a **custom tab** or a ### Hide a built-in tab -```ts +```ts @nocheck { id: "workflow" | "database" | "state" | "queue" | "connections" | "console", hidden: true, @@ -154,7 +154,7 @@ The dashboard sends an `init` message on load and again whenever the inspector token rotates. Always overwrite the cached token when it arrives. -```ts +```ts @nocheck { type: "init", v: 1, @@ -168,7 +168,7 @@ arrives. For tabs with sub-views, the dashboard also sends `set-active-tab` when the user switches: -```ts +```ts @nocheck { type: "set-active-tab", v: 1, tab: string } ``` @@ -176,7 +176,7 @@ when the user switches: Send `ready` once your message listener is registered: -```ts +```ts @nocheck { type: "ready", v: 1 } ``` @@ -184,7 +184,7 @@ If a fetch returns 401, the token has rotated. Ask the dashboard for a fresh one and wait for the next `init` — don't retry with the stale token: -```ts +```ts @nocheck { type: "token-refresh-needed", v: 1 } ```