The completeness bar — what every game must HAVE
The [game design bar](game-design-bar.md) says what the studio is allowed to build. This policy says what a game must have structurally before it counts as finished. The [content bar](content-bar.md) says how much game there is.
This is the loop half of a game's score — a nine-item checklist. The other half is depth. The public completion % is the blend of the two; see [content-bar.md](content-bar.md) for the arithmetic and the weights.
The nine items
1. A cinematic intro sequence — an animated, camera-directed opening with voiceover. NOT a stack of static text slides. 2. A full gameplay campaign with a real ending. 3. A death / game-over sequence. 4. A win sequence. Both death and win are presented, never bare text — the win genuinely cinematic, the death at least a styled/animated beat. 5. A full menu — new game / continue / options with mute. 6. Saves, if the game is longer than one sitting. 7. Full controller support (or a noted pointer-native exemption — see below). 8. Telemetry — the game reports its own loop. See [analytics.md](../analytics.md) for the vendored kit and the four event names. 9. Touch — playable on a phone. See "Touch controls" below.
A new game ships day one with the full loop present (intro → play → death/win → menu, save, controller unless pointer-native), but its campaign may be short; content lanes deepen it on later nights. Existing games that predate any of these rules get them as content-lane work.
Cinematic sequences
Cinematic sequences use the studio's vendored cutscene kit (state/kits/cutscene/, copied into each game), with voiceover baked at build time via the elevenlabs MCP — games stay fully static, so no runtime TTS calls. Games predating the cinematic bar get it as content-lane work.
A game whose options screen has a voice or SFX control must drive the kit's volume as well as its muted. Cutscene narration plays on an HTMLAudioElement, not on the game's WebAudio graph, so it is a second audio path: wire only the mute and the slider moves the in-game barks while every cinematic stays at full blast. Kit 1.2.0 added volume / setVolume for exactly this.
Drift between a game's vendored copy and any canonical kit (whatever is in state/kits/ — the list has grown past the original three) is detected by scripts/kit-drift.sh --nag and fixed with one command per kit — node scripts/kit-sync.mjs <kit> --build, which snapshots each tree, copies only the kit's surface files, writes the .kit-version marker and rebuilds. It is not per-game lane work, and it is not one ticket per game. A game whose divergence is deliberate belongs in state/kits/drift-ignore.txt, with the condition that would let the entry be removed — an exemption that outlives its reason silently withholds every later fix from that game.
Controller support
Standard-mapping Gamepad API driving gameplay AND every menu: stick/d-pad navigate, A/Cross confirm, B/Circle back, Start pause. All on-screen help and button prompts switch to whichever device last produced input (keyboard ⇄ pad, live, no setting needed).
Pointer-native games are exempt. A game whose gameplay is mouse/touch-driven by design (path drawing, point & click) needs NO controller support at all — never bolt a stick-cursor onto one. Note the exemption on the game's status row.
The pointer-native exemption is about controls only. It never excuses a text-slide intro or ending; the cinematic requirement binds every game.
Touch controls — half our players are on a phone
Of the people who opened a game page in the 30 days to 2026-07-26, 104 of 226 were on mobile. They stayed a median of 21 seconds against desktop's 68, and viewed 1.6 pages against 5.1. The catalog had no touch controls at all — so that is what "we built games our audience can't play" looks like.
Every game must be playable on a phone, using the studio's vendored input kit (state/kits/input/, copied into each game as src/input/): keyboard, gamepad and touch behind one action state, so adding touch changes no gameplay code.
Three parts, and the first is the one that matters most:
- Fit before input. A fixed 960×544 canvas in a portrait phone is a ~390×221 strip — rendered, unplayable. Games gate on orientation (requireLandscape, a "turn your phone" prompt) rather than reflowing to portrait; portrait-native is a per-game redesign and is not required. Call lockViewport() so pinch and double-tap zoom stop fighting the game for gestures, and keep controls inside env(safe-area-inset-*). - A control scheme, not a key mapping. The kit ships five — stick-buttons, drag-follow (shmups: the ship follows your finger), drag-aim-release (artillery/golf), lane-hold (runners/flyers), and pointer-native. Each form in studio-config.json → gameDesign.forms carries its default. A virtual stick is right for a platformer and wrong for most other things: never bolt a stick onto a pointer-native game — those need only tap-target sizing and the viewport lock. - Prompts follow the hands. input.device gains a third value, 'touch'; whatever a game already does to switch prompts between keyboard and pad now switches to touch too.
New games ship touch on day one. Existing games get it as content-lane work, ordered by mobile traffic (scripts/analytics.sh signal <slug> shows the device split) — the pointer-native games are nearly free wins.
QA verifies touch at a phone viewport using the kit's ?touch=1 flag, which forces the overlay on in headless Chrome. A narrow desktop viewport reports a fine pointer, so without the flag the touch UI cannot be reviewed at all.
The studio footer — every main menu links home
Every game's MAIN MENU carries a link to the studio site and to the studio's social channels. Studio rule, 2026-09-11 (owner decision), applied to the whole live catalog the same day.
A player who just enjoyed something has no way to find who made it. The portal navbar has the links, but a proxied game fills the tab — the player is inside the game, and the only thing in front of them is the game's own menu. So the menu is where the links go.
- Main menu only. Not the pause menu, not the HUD, never over gameplay. - It uses the vendored studio-links kit (state/kits/studio-links/, copied into each game as <src>/studio/). The URLs live in that one file and nowhere else: node scripts/kit-sync.mjs studio-links --build pushes a changed handle to every game. A hand-typed studio URL in a game is a bug — it is invisible to the sync, and the studio has already moved its Discord invite once. - Which channels is the kit's business, not the game's. It links what the studio actually runs publicly, in step with the portal navbar. A game does not pick a subset and does not add its own. - Links open in a new tab (target="_blank", rel="noopener noreferrer"). A game is a session with state in it; finding the studio must never take the run the player is in the middle of with it. - It is menu furniture, not a menu item. It never joins the game's own navigation array, so pad and keyboard menu control are unchanged — this is the one place the controller rule above does not reach. Tab still finds it, which is what keyboard players expect of a link. - Restyling is placement only. Position it, and let it inherit the menu's colour. A local patch to a kit surface file needs a drift-ignore.txt entry, and every such entry silently withholds every later fix from that game.
This is NOT a tenth loop item. The nine-item checklist and every stored loop value stay as they are — re-basing the catalog a second time would move 36 public completion numbers for a link in a footer. It is a structural requirement that a game either meets or doesn't, checked by QA, scored nowhere.
How loop is scored
loop is the percentage of these nine items a game has. It is recorded by the lane that did the work, via scripts/content.mjs set <slug> --loop <n>, and blended with depth into the public completion %.
Touch became the ninth item on 2026-07-26 (owner decision), applied retroactively — every game's stored loop was re-based over nine items instead of eight. See [content-bar.md](content-bar.md) for the re-basing details.
Enforced at
- game-creator — ships a new game with the full loop present day one. - game-improver — the content lane; retrofits missing loop items on existing games alongside depth work. - game-QA — verifies the items actually work in the running game: the intro plays, the death and win sequences present, the menu navigates on a pad, the telemetry events fire, and the touch UI is reviewable at a phone viewport with ?touch=1. Also that the studio footer is present on the main menu, absent everywhere else, and that its links open in a new tab.