website/src/content/docs/actors/quickstart/cloudflare.mdx
Set up a Rivet project locally that runs on Cloudflare Workers. The @rivetkit/cloudflare-workers package wires the WebAssembly runtime for you.
npm install rivetkit @rivetkit/cloudflare-workers
npm install --save-dev wrangler
name = "rivetkit-cloudflare"
main = "src/index.ts"
compatibility_date = "2025-04-01"
compatibility_flags = ["nodejs_compat"]
The nodejs_compat flag is required so the runtime can read its connection config from process.env.
createHandler serves the Rivet manager API on /api/rivet. Pick how you want to handle your own routes:
npm install hono).fetch and route requests yourself.import { actor } from "rivetkit";
import { createHandler } from "@rivetkit/cloudflare-workers";
const counter = actor({
state: { count: 0 },
actions: {
increment: (c, amount = 1) => {
c.state.count += amount;
return c.state.count;
},
},
});
export default createHandler({ use: { counter } });
import { actor } from "rivetkit";
import { createClient } from "rivetkit/client";
import { createHandler, setup } from "@rivetkit/cloudflare-workers";
import { Hono } from "hono";
const counter = actor({
state: { count: 0 },
actions: {
increment: (c, amount = 1) => {
c.state.count += amount;
return c.state.count;
},
},
});
// `setup` returns a typed registry, so the client below is fully typed.
const registry = setup({ use: { counter } });
const app = new Hono();
app.get("/", (c) => c.text("Hello from Hono + Rivet Actors!"));
app.post("/increment/:name", async (c) => {
// `createClient` reads RIVET_ENDPOINT from the environment (passed by `rivet
// dev`, or set as a Worker secret in production).
const client = createClient<typeof registry>();
const count = await client.counter.getOrCreate(c.req.param("name")).increment(1);
return c.json({ count });
});
// Rivet keeps `/api/rivet`; Hono handles everything else.
export default createHandler(registry, { fetch: app.fetch });
import { actor } from "rivetkit";
import { createClient } from "rivetkit/client";
import { createHandler, setup } from "@rivetkit/cloudflare-workers";
const counter = actor({
state: { count: 0 },
actions: {
increment: (c, amount = 1) => {
c.state.count += amount;
return c.state.count;
},
},
});
// `setup` returns a typed registry, so the client below is fully typed.
const registry = setup({ use: { counter } });
// Rivet keeps `/api/rivet`; your `fetch` handles everything else.
export default createHandler(registry, {
fetch: async (request: Request) => {
const url = new URL(request.url);
if (url.pathname === "/") {
return new Response("Hello from a raw Rivet Worker router!");
}
const increment = url.pathname.match(/^\/increment\/(.+)$/);
if (request.method === "POST" && increment) {
// `createClient` reads RIVET_ENDPOINT from the environment (passed by
// `rivet dev`, or set as a Worker secret in production).
const client = createClient<typeof registry>();
const count = await client.counter.getOrCreate(increment[1]).increment(1);
return Response.json({ count });
}
return new Response("Not found", { status: 404 });
},
});
Start Rivet. The CLI runs the local engine and spawns wrangler dev for you:
npx @rivetkit/cli dev --provider cloudflare
Visit http://localhost:6420 in your browser (or point your AI agent at it) to open the Rivet developer tools and inspect your actors live.
</Step> <Step title="Connect To The Rivet Actor">This code can run either in your frontend or within your backend. It connects directly to the local engine on http://localhost:6420:
See the JavaScript client documentation for more information.
</Tab> <Tab title="React"> <CodeSnippet file="examples/docs/actors-quickstart-cloudflare/Counter.tsx" title="Counter.tsx" />See the React documentation for more information.
</Tab> </Tabs> </Step> <Step title="Deploy">Ready to ship? See Deploying to Cloudflare Workers.
</Step> </Steps>