1

Install Dependencies

npm install @rivetkit/actor @rivetkit/react
2

Create Backend Actor

Create your actor registry on the backend:

backend/registry.ts
import { actor, setup } from "@rivetkit/actor";

export const counter = actor({
	state: { count: 0 },
	actions: {
		increment: (c, amount: number = 1) => {
			c.state.count += amount;
			c.broadcast("countChanged", c.state.count);
			return c.state.count;
		},
		getCount: (c) => c.state.count,
	},
});

export const registry = setup({
	use: { counter },
});
3

Setup Backend Server

Start a server to run your actors:

backend/server.ts
import { registry } from "./registry";
registry.runServer();
4

Create React Frontend

Set up your React application:

frontend/App.tsx
import { useState } from "react";
import { createClient, createRivetKit } from "@rivetkit/react";
import type { registry } from "../backend/registry";

// Create typed client
const client = createClient<typeof registry>("http://localhost:8080");
const { useActor } = createRivetKit(client);

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

	// Connect to the counter actor
	const counter = useActor({
		name: "counter",
		key: [counterName],
	});

	// Listen for real-time count updates
	counter.useEvent("countChanged", (newCount: number) => {
		setCount(newCount);
	});

	const increment = async () => {
		// Call actor action through the connection
		await counter.connection?.increment(1);
	};

	const incrementBy = async (amount: number) => {
		await counter.connection?.increment(amount);
	};

	return (
		<div style={{ padding: "2rem" }}>
			<h1>RivetKit Counter</h1>
			<h2>Count: {count}</h2>
			
			<div style={{ marginBottom: "1rem" }}>
				<label>
					Counter Name:
					<input
						type="text"
						value={counterName}
						onChange={(e) => setCounterName(e.target.value)}
						style={{ marginLeft: "0.5rem", padding: "0.25rem" }}
					/>
				</label>
			</div>

			<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
				<button onClick={increment}>
					+1
				</button>
				<button onClick={() => incrementBy(5)}>
					+5
				</button>
				<button onClick={() => incrementBy(10)}>
					+10
				</button>
			</div>

			<div style={{ marginTop: "1rem", fontSize: "0.9rem", color: "#666" }}>
				<p>Connection Status: {counter.isConnected ? "Connected" : "Disconnected"}</p>
				<p>Try opening multiple tabs to see real-time sync.</p>
			</div>
		</div>
	);
}

export default App;
5

Setup Vite Configuration

Configure Vite for development:

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
  },
})
6

Run Your Application

Start both the backend and frontend:

Terminal 1: Start the backend

Backend
npx tsx --watch backend/server.ts

Terminal 2: Start the frontend

Frontend
npx vite

Open http://localhost:5173 in your browser. Try opening multiple tabs to see real-time sync in action.

7

Deploy

By default, RivetKit stores actor state on the local file system and will not scale in production.

The following providers let you deploy & scale RivetKit:

Rivet provides open-source infrastructure to deploy & scale RivetKit. To deploy to Rivet, provide this config:

rivet.json
{
  "rivetkit": {
    "registry": "src/registry.ts",
    "server": "src/server.ts"
  }
}

And deploy with:

npx rivet-cli deploy

Your endpoint will be available at your Rivet project URL.

Configuration Options

Add Your Own Backend Endpoints

Add custom HTTP endpoints alongside your actors to handle additional business logic, authentication, and integrations with external services.

See backend quickstart for more information.