jonnify·codemojex /codemojex/road-to-gameisland/the-road-ahead

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.

Three delivery tiers, three cadences — select a tier
ship-with · the boot app.js · the stable contract surface cadence: a Mercury build + a git commit edge · the React island game-[hash].js · self-contained ESM new hash server · the Phoenix release the release image · on the 6PN cadence: an Operator-run deploy
ship-with → the boot (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.
§1

The edge cadence and the F-1 gate

architecture.md §1 · §4

The 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.

apps/game/vite.config.ts · the F-1 export-signature gate source
// 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).

§2

Four seams to GameRoom

channels.md §6 · forward

The 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.

The road to GameRoom — shipped, then four seams; select one
island shipped write path join reply scored fold real acks GameRoom the screen as-built the road ahead (forward)
write path → today the channel transport is read-only: RoomChannel’s only handle_in is refresh, and guesses flow through LiveView. Wiring submit_guess onto the channel is a deferred engine rung.
channels.md §6 · the as-built seams forward
# 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.

§3

References

sources · related

Sources

Related