Cloudflare server in production
@rpgjs/server/cloudflare runs the same framework-agnostic server module as the
Node adapter. Each Signe namespace and room id is routed deterministically to a
Durable Object. WebSockets remain attached during hibernation, while persisted
room state lets RPGJS rebuild a new in-memory instance when the object wakes.
If this is your first deployment, complete the shared project and publisher
setup in Put an MMORPG online first. This page serves the
built browser client and the room Worker from the same public Cloudflare URL.
Mental model
The Worker is the public HTTP and WebSocket entry point. It routes each RPGJS room id to one deterministic Durable Object:1. Install Wrangler
Install the current Wrangler CLI in your starter project:2. Create the Worker entry
Createsrc/entries/cloudflare.ts:
3. Configure the Durable Object and browser assets
ConfigureRPGJS_ROOMS as a SQLite Durable Object class in wrangler.jsonc and
export RpgServerDurableObject from the Worker entry:
wrangler types.
Keep the existing migration tags after deployment; add a new migration rather
than rewriting an already deployed one. Cloudflare documents the available
Durable Object migration operations.
The binding name in wrangler.jsonc, the Env interface, and
createRpgServerWorker() must all be exactly RPGJS_ROOMS. SQLite-backed
Durable Objects persist authoritative room state between Worker instances.
Maps and worlds are published externally
The Worker does not read project files from a filesystem and the browser client is not trusted to configure authoritative maps. An editor, Vite development server, CI job, or administrative backend publishes them with the following server-only flow:
Both endpoints accept the same administration token:
createRpgServerWorker() fails closed for map and world updates when this secret
is missing. A map room can be created by a trusted update before its first player
connects. RPGJS awaits the Durable Object storage write before acknowledging
either update.
createStudioMapUpdatePayload() includes runtime-ready worldUpdates metadata.
The RPGJS Vite publisher and the Studio seed command consume it automatically:
they publish the selected map, then fan the topology out to every map room in
the world. If you build a custom publisher or call the HTTP API directly, you
must reproduce both steps. Sending only /map/update does not refresh the world
manager of a player who is currently on another map.
Local Vite and Wrangler workflow
Configure the Vite plugin with a remote development server:/parties to Wrangler. It uses a
server-only publisher to send the configured maps on startup and after HMR. If
the resolved payload contains worldUpdates, the same publisher also calls the
world update endpoint for every referenced map room.
See samples/cloudflare-mmorpg for the complete setup.
For sources that need asynchronous preparation, use resolveMapPayload. This is
particularly important for Studio because the publisher must fetch and normalize
the complete v2 map before the room compiles its private authoritative state and
public chunks:
VITE_-prefixed secret. The browser receives only nearby render and physics
chunks; event rules, project data, the database, and the complete collision model
remain in the Durable Object. Renderable media URLs remain public.
The Studio playground contains a local Wrangler entry, integration test, fixture,
and authenticated seed command:
RPG_TYPE=mmorpg alone keeps the normal Node.js room hosted by Vite and does
not require RPGJS_MAP_UPDATE_TOKEN. The playground’s dev:cloudflare and
build:cloudflare scripts additionally set RPGJS_SERVER_ADAPTER=cloudflare;
only that adapter enables remote publication and requires the shared secret.
It also documents the equivalent curl request and how to publish a real Studio
project and map. Studio MMORPG streaming accepts v2 maps; v1 maps remain available
to the standalone loader.
First production deployment
The following sequence deploys the browser client and Worker, configures the secret, publishes the starter map, and verifies the live game.-
Authenticate and confirm which Cloudflare account Wrangler uses:
-
Build the MMORPG client and validate the Worker configuration:
-
Deploy the Worker. Wrangler prints its public
workers.devURL: -
Create the administration secret through Wrangler’s interactive prompt. Do
not put the value on the command line:
-
Create an uncommitted
.env.publisherfile on your trusted development or CI machine. Use the URL printed bywrangler deployand the same secret: -
Run the publisher created in the beginner guide:
A
Published map: simplemapmessage confirms that the map and its world updates were accepted. The Durable Object persists them before acknowledging the request. -
Inspect logs while opening the public URL in two independent browsers:
v1
migration tag; append a new migration if a future Durable Object class changes.
Direct HTTP publication
Prefer the Vite publisher, the Studio seed command, or a trusted backend because they perform the world fan-out. To inspect the HTTP contract manually, a complete publication uses the same secret for both requests:prepared-world.json can be either { "id": "<world-id>", "maps": [...] }
or the maps array itself. Repeat the second request for every map id contained in
that world. A successful 2xx response means the target room updated its live
world manager and persisted the topology.
Production checklist
These commands use the top-level Worker configuration shown above. If you add a named Wrangler environment, append the same--env <name> option to every
secret, deploy, and tail command.
-
Authenticate Wrangler with
npx wrangler loginor configure the appropriate CI API token. - Build the MMORPG client and Worker entry.
-
Verify the binding and the
new_sqlite_classesmigration inwrangler.jsonc. -
Deploy the Worker and note its public URL:
-
Configure the secret for that Worker through the interactive prompt:
- Point the trusted publisher at the deployed Worker URL and publish the start map. For Studio worlds, confirm that it reports successful world publication for every map room.
-
Open two clients, change maps in both directions, and inspect production logs
with
npx wrangler tail.
RPGJS_MAP_UPDATE_TOKEN in browser code, a VITE_ variable, a
committed .env file, or a public build artifact.