For the latest codex/engine-foundations build with the new characters and arrival art, use the current branch beta handoff. The instructions below describe the earlier beta.
This build is for a small cooperative exploration test with two trusted people. The required shared-room path is the default. ?solo=1 is a diagnostic fixture only. Keep the Spawn reference as the visual quality target: warm lighting, readable materials, thoughtful framing and unobtrusive interface. The current original characters are proxies; imported, animated character art is a next-stage requirement.
#Start and join
Use Node 22.23.4, run npm ci, npm run build, then npm start. Open http://localhost:8787. The process serves both the built game and its shared relay. A fresh room starts with an unlit beacon. To develop source with live reload, stop this process and use npm run dev instead (http://localhost:5173).
Open a second independent browser profile, or create a new tab and type the URL. Do not duplicate a tab: browsers can copy session storage and thus its traveler identity. The upper-right status must show 2 travelers · Connected. Both players should see the other’s avatar/name when looking toward them. Sessions last 24 hours and survive refresh in the same tab; there is no persistent user account. Closing the tab ends that traveler session for practical playtest purposes.
For two machines, use an existing authenticated SSH connection to the machine running the server:
ssh -N -L 8787:127.0.0.1:8787 YOUR_EXISTING_SSH_HOSTThe joining person opens http://localhost:8787 on their computer. This preserves a secure browser context for WebGPU. For internet play, follow the Coolify Docker deployment guide, including HTTPS, the persistent volume and exact DW_ALLOWED_ORIGINS. Deployment configuration is provided; hosting must still be configured in Coolify. Plain HTTP on a LAN IP is not a supported WebGPU entry point.
#Fifteen-minute session
- Enter with both players. Walk around the house, turn toward each other, and verify avatar movement and names. Compare the lighting and interface at normal viewing distance.
- Speak with Elowen using E. The conversation pauses only your movement. Verify that the other player can keep walking. Use J to inspect the shared discovery.
- Both approach the lantern on the writing desk and press E. Exactly one satchel should receive it; it disappears for both. The other player’s objective points them toward their companion.
- Open the garden door. Both clients must see the same state. Walk through and use E at the exit. Follow the garden path to the sanctuary and use E at its entrance. The holder lights the beacon; both players should see the finished objective, even from different places.
- Send a short room message using Enter. Escape returns to movement. Verify that typing never moves the player.
- Refresh a tab. Position should restore near its last checkpoint and shared progress should remain. Close the host tab (F2 identifies it). The remaining traveler should become room host and still operate shared interactions.
- If the lantern holder disconnects, allow 30 seconds. The lantern returns to the writing desk and can be picked up by the remaining traveler. Reconnecting within the grace period preserves possession.
- Restart the relay, leaving a client open. It should reconnect automatically and restore acknowledged door/quest state. Input may continue locally during disconnection, but shared interactions remain unavailable until the room reconnects.
Report confusing controls, collision snags, visual defects, frame hitches or state disagreement. Press F2 and Export playtest report; include the JSON, a screenshot and reproduction steps. Exports contain browser/version, viewport, position, timings and room revision, but no admission token. Frame intervals measure the main-thread animation loop; render CPU timing is not GPU time.
#Saves and recovery
.data/hearth/room.jsonstores shared state, authority epoch, bounded deduplication receipts and session metadata.session-keysigns room admission tokens. Keep this directory private and out of source control.- Acknowledged shared changes are synchronously written, fsynced and atomically renamed before the server sends the durable commit. This is one process on one local filesystem, not a distributed database guarantee.
- Position is saved in local storage roughly every two seconds and when pausing/changing place. Storage failures preserve the last readable save and show a notice. Settings → Return to the house resets local position without resetting the shared room.
- Before backup, stop the process and copy the whole directory, including the key. Restore it alongside the exact same source/build release. Changed world content causes a deliberate startup refusal instead of silently reinterpreting saved progress.
- To start a fresh test without destroying evidence, stop the server and choose a different
DW_DATA_DIR, for exampleDW_DATA_DIR=.data/playtest-02 npm start. Keep the previous directory. - A malformed/cross-release checkpoint needs inspection or an explicit migration. Automatic schema migrations are not implemented. If storage fails, the relay fails closed and does not acknowledge new changes. Restore writable storage and restart.
- Chat and motion presence are ephemeral. Disconnected item ownership has a 30-second grace period, including after server restart; this is a cooperative quest policy, not permanent inventory storage.
#Simulation recovery on the engine branch
Run npm run test:browser:simulation-recovery on codex/engine-foundations with the project's Playwright browser available. The isolated production build exercises real blocked workers, native checkpoint restoration in both render placements, shared rejoining, recovery limits and safe manual retry. npm run test:browser:development-recovery checks restoration across accepted edits and a stall during live-update preparation. These tests do not stall or modify your running development server.
The player retains a sealed native recovery point in memory. After a worker stall or uncaught worker fault, Finding your place restores the simulation and view, rejoins the shared room and returns to the pause menu without reloading the page. Input stays released until you continue. Shared authoritative progress is reconciled on rejoin. Local movement and solo actions since the latest recovery point can roll back; the ordinary on-device save remains the fallback when native recovery cannot complete.
See runtime recovery for cadence, bounds, accepted-world migration, diagnostics and limits. The existing npm run test:browser:watchdog command specifically exercises manual retry when a native point is unavailable, plus liveness under presentation backpressure.
#Configuration
| Variable | Default | Purpose |
|---|---|---|
DW_DATA_DIR |
.data/hearth |
Persistent room directory; one process per directory |
DW_RELAY_PORT |
8787 |
Built client and WebSocket service port |
DW_STATIC_DIR |
dist |
Built browser assets |
DW_ALLOWED_ORIGINS |
localhost/127.0.0.1 on 5173 and 8787 | Exact comma-separated browser origins |
DW_ROOM_PASSWORD |
unset | Optional room passphrase; clients prompt before admission |
DW_HTTP_PORT |
5173 |
Vite development port only |
The Docker image defaults to /data for saves and /app/dist for assets. With NODE_ENV=production, DW_ALLOWED_ORIGINS is required. npm run build compiles both client and server; npm start uses those compiled outputs.
If setting a non-default origin/port, allow its exact origin explicitly. Keep secrets in the process environment, never in the client bundle. A valid admission token is required for WebSocket hello, and the browser and relay must agree on protocol, release and content fingerprint.
#Supported evidence and known limits
Automated browser acceptance uses two independent Chromium 141 contexts on Linux with SwiftShader WebGPU. The suite exercises the actual built assets. A real Codex in-app browser also rendered and walked the scene during development. Hardware-GPU frame-rate, other operating systems/browsers and two physical machines still need human measurement; the checks are not a broad compatibility certification.
Only two players are the beta test target. The admission cap is eight; no eight-player capacity or long soak result is claimed. The authority is an elected, trusted browser, so a modified host can cheat. This profile must not carry an economy, adversarial gameplay or untrusted creator code. There is one room, one coordinator process, JSON full shared-state commits, static props, kinematic players and safe discrete place transitions. There is no combat, movable shared body, avatar customization, editor, GLB animation, accounts, mobile control scheme or public release service yet.
The initial three-place journey is an acceptance fixture within the larger engine program. Its readiness for a private playtest does not complete roadmap milestones 0–9 or establish Spawn parity.
#Updating the original beta for the porch collision fix
Stop the relay, build the updated client, then run node --import tsx tools/cli/migrate-porch.ts .data/hearth before restarting. This narrow migration verifies the exact original content fingerprint and that only the lawn collider and porch step changed. It writes a private backup and preserves all shared state, sessions, receipts and authority metadata. It refuses unrelated content changes. Existing clients must refresh after the update.