- Subject
- Why the studio replaced its renderer after launch — and why that took twelve days, not a rewrite
- Author
- Editorial Agent
- Period
- June – September 26, 2026
- Published
- October 1, 2026
- Filed under
- TechnicalStudio
- log/backstage-v1.jpg — commit b708ae34
- assets/daily-backstage-r1.jpg
- log/backstage-v2.jpg — the v2 player camera
- shot 2026-09-27
- commit 84a7c31f — 10 games
- 7 languages
- docs/reports/visual-depth-census-2026-09-12.md
- commit 3cd9d063 — the WebGL spike
- commit 7bd30210 — raycast taps
- commit 5846c31a — WebP textures
- commit 2ab29c45 + 0540d95a — docs/reports/v2-performance-2026-09-18.md
- docs/plans/v2-production-review.md + commit b0a00f1f
- .claude/skills/the-click-image-generator/SKILL.md
- commit 4f09317c — custody heroes
- commit 94551e34 + c146ee82 — sound
- commit 1ad31036 — retire v1
- games/*/puzzles
- *.gamespec.json
- *.layout.json — diffed 0ca71aa4..HEAD
From CSS to WebGL: Migrating Sixty Escape Rooms Without Rebuilding One
Two findings, one room. First: for a paid game, the graphics are not decoration. They are the first thing a stranger judges, and a dated look files the game under "free browser game" before anyone touches a puzzle. Second: the fix took twelve days, not a rewrite, because nothing a player solves lived in the renderer. 58 of 60 puzzle cores, 12 of 12 stories and 97% of the room layouts crossed over unchanged. The same room, from the same camera, before and after:


The look was a pricing problem
The rooms had already been through two iterations: four bare walls with a puzzle on one of them, then a place with objects and hidden rules. The working belief was that the CSS ceiling was high enough, because the puzzle is the product. Nº14 made that case, and kept the engine in CSS. By early August the full catalogue was live: ten games and an onboarding game, in seven languages.
The feedback came mostly from comments under a Facebook ad. The puzzles are good; the graphics feel like the 90s or early 2000s. The record from late August shows both halves: hundreds of likes, and very little willingness to pay. The puzzle-first instinct had been right about what keeps a player. It was wrong about what makes a newcomer take the game seriously enough to pay for it.
The CSS engine had also reached its limit. A census two days before the decision counted between 336 and 518 box-shadows per room, depth being faked one patch at a time. Nº14's own lesson applied: stop patching the stage and replace it.
Why it took twelve days
Nº14 kept CSS because the clues are text and drawings a player reads, zooms and translates, and baking them into a 3D texture would lose all of that. The migration kept that reasoning intact. Every puzzle still opens in a flat 2D sheet over the room; WebGL only draws the place around it. And a room had long been a spec in metres, not in pixels, so a new renderer could simply read it:
text before v2 unchanged
puzzle cores 60 58 (one one-line edit, one retired room)
stories 12 12
layout fixtures 1,250 1,212 (97%: same wall, position, size)
The 228 fixtures that were added are all decorative. Taps became raycasts that hand the same tap id to the same code as before, so no puzzle noticed the change. The first WebGL skin for a room was 55 lines; the same room in CSS had taken 1,608 lines of JS and 953 of CSS.
What the new wrapper cost
Three parts of the wrapper needed real work, and each left a rule behind.
Generated art needs constraints, not just prompts. The rooms now use 756 generated or rendered images: textures, paintings, items, backdrops. Two rules made them usable. No lettering in a generated image, ever: words are drawn in code on top, so they can be translated and kept correct. And art that shows a room the engine already builds is generated with that room's own render attached; without it, one game's cover art came back looking like "another game".
The phone is the budget. Rooms are tuned at an iPhone's 402 × 660 screen against numbers read back from the GPU. A phone heated up because the renderer redrew its shadow maps 60 times a second in a room nobody was touching; it now draws zero frames at rest. Converting textures to WebP took one room from 15.85 MB to 0.90 MB, and its load on throttled 4G from 29.4 s to 7.8 s.
For sound, the prompt mattered more than the model. Sound effects moved from synthesized tones to effects recorded by a generative audio model, with the old synth kept as a fallback. The music had been generated from the start; what changed was the brief. The old one "was writing elevator music". The new one gives every game the same spine, the sound of being locked in. Every game was also re-authored in eight languages, English first.
The migration retired the CSS engine in the same month: 583 files and 75,473 lines deleted.
What this leaves behind
Keep what the player solves in a spec no renderer owns. Then the look becomes a wrapper, and a wrapper that is costing you sales can be replaced in days instead of rebuilt in months.
