Where touch support had got to
Every game in the arcade has had an iPad pass, and every pass made "tablet" a branch rather than a view. A game's single component, between three and six thousand lines, gained touch conditionals and a scoped touch stylesheet. Phones are still behind a desktop-only notice. Adding a phone layout the same way would put a third branch into every one of those conditionals, and every desktop change would then risk two touch layouts.
The games also repeated each other. There were eight copies of the same auto-pause module, seven bespoke touch docks, four ways to size a canvas and seven copies of the high-score store.
One session, three views
The plan gives each game one headless session and three views: desktop, tablet and phone.
- The session owns the game: state, the fixed-step loop, timers, saves, scoring and an action map. It never reads the viewport or the pointer type.
- The session is an external store. It exposes
getState,subscribeanddispatch, plus anonFramechannel that asks the mounted view to paint once per frame. HUD components read slices of it, so a frame does not re-render React. - A view only lays out and paints. Views never branch on the device. Choosing the view is the branch.
- The session holds no DOM. Canvases and WebGL contexts belong to the view and are disposed of when it unmounts. iOS caps a page at roughly sixteen live WebGL contexts, so a swap that leaked one would run out within a few rotations.
Rotating a phone or narrowing a window pauses the game, swaps the view and keeps the run.
Moving code without changing it
Retro Labyrinth went first. The rule for the move was that code moved as it was and nothing was rewritten. The game's state and rules went into useRetroLabyrinthSession, the view now reads a typed snapshot and acts through named intents, and the presentation pieces went into shared parts. The view component went from 4,387 lines to about 1,430.
"No gameplay change" is an easy claim to make about 57 changed files and a hard one to check by playing. Two things checked it instead:
- Replays. Five runs had been recorded on main before the move. After the move, all five replay to exactly the same result.
- Pixels. Screenshots at 1024, 1280 and 1440 pixels wide, with a frozen clock and seeded randomness, were compared against main. The launched and moved states are identical.
The screenshot comparison earned its keep. It found that a developer-only view picker was showing in production builds, and that patrols started moving while the view's code was still downloading. The loop now runs only while a view has registered a painter and the room is not paused.
Generate the docs from the map
Keys and gamepad buttons now come from one action map. The cabinet's control list and the field manual's key column are generated from it, which fixed a small, old lie: the control list said the tools sat on keys 1 to 3, and the game read 1 to 5.
A retry is not a pass
The first CI run of that pull request failed device tests that had passed locally. They had passed locally because Playwright retried them. The summary said 120 passed, and the tests that only passed on a second attempt were counted inside that number. Device runs are now repeated with retries off before a pull request asks for review.
A report that was not a bug
A report said the touch controls in Working With Duck vanished after closing the wardrobe. They did, on purpose: a hardware Escape key had switched the input mode to keyboard, and the touch dock fades out until the next tap. The investigation was still worth it. The same dialog had close buttons with no accessible name and a heading order that skipped a level, and both are fixed.
Where it stands
One registry now decides, per game, whether the phone notice shows, which badge the hub card carries and which games the notice suggests instead. Two of the twelve games play on a phone today: Trial & Error and Meme Vault. Retro Labyrinth's phone view is next. A game comes off the notice only after it has been played on a real phone and is fun there, not just when its tests pass.
The arcade is open on desktop and tablet. On a phone, the notice points to the games that are ready.