Deliverable #6 · 2026-08-03

Play it in your browser — the multiplayer world, live

epic: server-architecture delivered due with server-architecture/007

▶ Play it in your browser

Delivered 2026-08-03. The Stage 3 web client is live on lor-game-server-01, connected to a real, running director and world instances on that droplet — not a local stand-in.

Reading note: the button above is the link to use (HTTPS, since 2026-08-04 — see the update section near the bottom). The sections between here and there are the original 2026-08-03 record and quote the old plain-HTTP 209.38.29.22 link, which real browsers refuse to run the Godot canvas from (no Secure Context). Historical prose left as written, per the log’s conventions.

What this will be

A tap/click from this site straight into the actual multiplayer world — no download, no install, just a browser tab talking to lor-game-server-01 over a live WebSocket connection.

Acceptance criteria

What was verified (2026-08-03, from the container, externally)

Two checks, matching this session’s task brief exactly:

  1. The web client URL returns the export, HTTP 200, sane content: http://209.38.29.22/play/index.html returns 200 with the correct <title>lor-world-server</title>; index.wasm (39,513,091 bytes, Content-Type: application/wasm) and index.pck (150,380 bytes) both return 200 with correct sizes.
  2. The existing CLI test-client machinery, pointed at the live droplet over the public internet (director/cli-test-client/verify-live-droplet.ts, npm run verify-live-droplet from director/) — not a local/spawned-in-process stand-in: two accounts created against the real droplet director (through Caddy’s /director/* proxy on port 80), a world created and joined by both, a real Godot world-server OS process spawned live on the droplet, both game clients connecting directly to that process’s dynamically-allocated gamePort (opened through the droplet firewall for exactly this purpose — see below) over the public internet, mutual movement visibility proven in both directions, and an illegal (out-of-bounds) intent proven refused live. 9/9 checks passed.

Not verified from this container — genuinely can’t be: actually loading http://209.38.29.22/play/index.html?director=ws://209.38.29.22/director/ in a browser and watching the canvas render. This container has no display and no browser. The check above proves the exact same protocol traffic a browser tab would generate works correctly, live, against this droplet — but the visual “two tabs, watch the balls move” moment is still Kris’s own check, same as Stage 3’s own handoff note already says for the desktop client. If that check ever fails despite the above, the gap is almost certainly Web-export/browser-specific (e.g. JavaScriptBridge query-param reading, WASM loading) rather than the underlying multiplayer plumbing, which this session did prove live.

Known prerequisites, carried over from deliverable #5 — resolved or updated

Kris tried the original plain-HTTP link in Firefox and hit Godot’s refusal to run outside a Secure Context — exactly the browser-specific gap the “not verified from this container” note above anticipated. Fixed the same day:

Later the same day — the page loaded but joined nothing, so the commons was born. With HTTPS working, the client authenticated and then sat on a blank canvas forever: joining a world had only ever been driven by a --world-id command-line argument (minted by the desktop two-player setup script), which a browser never receives — and even with one, two fresh browser accounts could never pass the members-only gate on each other’s worlds. The fix is a real feature, not a patch: a public commons world. A new director request (join_public_world) finds-or-creates a shared world named The Commons and auto-members any account that asks; the client falls back to it whenever no world id is supplied (an explicit ?world=<id> query param also now works). Private worlds keep their members-only gate — the commons is the one deliberate exception. Shaking this out live also surfaced and fixed two cold-start races (two simultaneous first-joiners could double-spawn the world process, stranding one of them, or double-create the commons row) and one browser-specific trap: Godot’s user:// storage is shared across tabs, so tabs reused one saved account — the web client now mints a fresh account per tab, which is what makes the two-tab demo two players. Covered by a new director test suite run (30/30) and a live verifier (verify-public-world.ts, 5/5 against this droplet over wss: two strangers, no world id exchanged, same world, mutual movement observed).

Artifacts

Sources & artifacts

← related epic: server-architecture

Also available as raw markdown.