Back to Rivet

Cloudflare Workers Quickstart

website/src/content/docs/actors/quickstart/cloudflare.mdx

2.3.35.2 KB
Original Source

Set up a Rivet project locally that runs on Cloudflare Workers. The @rivetkit/cloudflare-workers package wires the WebAssembly runtime for you.

<Note> Prefer to start from a complete project? See the runnable [`hello-world-cloudflare-workers`](https://github.com/rivet-dev/rivet/tree/main/examples/hello-world-cloudflare-workers) example (with [Hono](https://github.com/rivet-dev/rivet/tree/main/examples/hello-world-cloudflare-workers-hono) and [raw router](https://github.com/rivet-dev/rivet/tree/main/examples/hello-world-cloudflare-workers-raw) variants). </Note>

Steps

<Steps> <Step title="Install Packages">
sh
npm install rivetkit @rivetkit/cloudflare-workers
npm install --save-dev wrangler
</Step> <Step title="Configure Wrangler">
toml
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.

</Step> <Step title="Create the Worker">

createHandler serves the Rivet manager API on /api/rivet. Pick how you want to handle your own routes:

  • Default: Rivet handles everything.
  • Hono: Mount a Hono app for your routes (npm install hono).
  • Raw: Provide a fetch and route requests yourself.
<CodeGroup>
ts
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 } });
ts
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 });
ts
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 });
  },
});
</CodeGroup> </Step> <Step title="Run Locally">

Start Rivet. The CLI runs the local engine and spawns wrangler dev for you:

sh
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:

<Tabs> <Tab title="TypeScript"> <CodeSnippet file="examples/docs/actors-quickstart-cloudflare/client.ts" title="client.ts" />

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>