Codemojex · C9.3
The road ahead.
The front end ships in three delivery tiers with three cadences: the committed boot, the self-contained edge island, the server release. A game change is an edge deploy — decoupled from the server. This dive walks the road forward: the tiers, the export gate that keeps the island honest, and the four seams that lead to the fine-grained GameRoom screen.
Grounding — liveview_boot/architecture.md §1 (tiers) · §4 (the F-1 gate) · channels.md §6 (the seams). The tiers and the gate are as-built; the seams are forward.
app.js) is committed to git and served by Phoenix — the stable contract surface between the host and the island. It changes rarely and deliberately: a Mercury build plus a commit.The edge cadence and the F-1 gate
architecture.md §1 · §4The split is the point: a game change is an edge push (game-[hash].js, pulled once and re-served same-origin), decoupled from the server release. The island is an app-mode Vite build, and app-mode Rollup drops the entry’s named exports unless the signatures are pinned — the module imports fine and renders nothing. This shipped silently once. So the gate is an import of the artifact, not a grep.
// the entry export contract — without this, mount is undefined at runtime build: { rollupOptions: { preserveEntrySignatures: "strict" } } // the gate imports the artifact and checks the keys: node -e "import('file://<abs>/game-<hash>.js').then(m => console.log(Object.keys(m)))" # must include: mount, GameEdge
The boot never imports game code; the game never imports the boot. Their contract is exactly mount(el, props, bridge) plus Bridge and GameProps (apps/game/src/types.ts, kept in lockstep with GameLive.game_props/3).
Four seams to GameRoom
channels.md §6 · forwardThe road ahead, stated honestly as four seams the roadmap closes — each a step toward the fine-grained GameRoom screen the derived stores already contract for. These are forward: the shipped island uses the LiveView transport; the channel-first path is where it grows. Select a seam.
RoomChannel’s only handle_in is refresh, and guesses flow through LiveView. Wiring submit_guess onto the channel is a deferred engine rung.# seam 1 — the channel transport is read-only today RoomChannel handle_in: only "refresh" # submit_guess flows through LiveView # seam 2 — the join reply is thinner than game_props join reply: %{view} only # leaderboard / history / me arrive via refresh # seam 3 — "scored" is not in GAME_INBOUND; a channel client folds it # seam 4 — bridge acks are synthetic; a true reply path gives pushAsync real acks
Where we are: one branded engine, a shipped React island, an Effector model with derived stores. Where we go: the four seams closed, and a GameRoom that subscribes each widget to one slice. The thread that carries it all is the same it always was — the branded id.
References
sources · relatedSources
- Vite — building for productionlibrary vs app build modes; the boot and the island differ
- Rollup — preserveEntrySignaturesthe option the F-1 gate turns to
strict - Fly.io — Fly Machinesthe server tier the release deploys as
Related
- C8 — Production Deploymentthe server tier’s release and Valkey node
- C9.2 — One model, two transportsthe model the seams complete
- C9 — The Road to GameIslandthe chapter hub