Public: anyone can read this; the crew can change it.
forked from trevato/cs · proposes · 4 behind
The second game's plumbing lands first: /range is served, bundled and proven engine-only #29
Check · Review · Land · Live done — Landed and live in production.
`GET /range` now answers with its own server-rendered page from `src/pages/shell.ts` — its own title, heading, prose and overlay, the same security floor as `/`, `HEAD` answering like `GET`, no session cookie because the page stores nothing — and its only script is `static/range.2543880d32.js` (7.1 kB), built from the new `{ name: "range", entry: "src/range/main.ts" }` row in `ENTRIES`. `/` links…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
GET /rangenow answers with its own server-rendered page fromsrc/pages/shell.ts— its own title, heading, prose and overlay, the same security floor as/,HEADanswering likeGET, no session cookie because the page stores nothing — and its only script isstatic/range.2543880d32.js(7.1 kB), built from the new{ name: "range", entry: "src/range/main.ts" }row inENTRIES./links to it and it links back.What runs there is the plumbing and only the plumbing:
src/range/binding.tsis the range's own key table (50 Hz, its own actions — no buy, no scoreboard, no weapon slots, a keyboard key for the trigger) plus the held-actions-to-intent mapping;src/range/readout.tsdraws a horizon on#sceneand a panel on#hudwith plain 2D calls;src/range/main.tswirescreateControlsandcreateLoopto the shell's ids and prints ticks run, milliseconds a frame, the held actions, the movement they and the thumb stick add up to, and yaw and pitch. A canvas that gives no 2D context becomes a sentence in the overlay, not an exception. No room, no targets, no physics and no WebGL — those are #13's, and the page says so.Worth looking at:
src/range/independence.test.ts, which reads every source undersrc/range/and fails on any import that is notsrc/engine/,src/pages/shell.tsor a sibling, reusingsources/specifiersOffromsrc/engine/boundary.test.tsrather than copying the regex (the price is the engine's four boundary tests being registered a second time, noted in the file); andsrc/range/dom.ts+boot.test.ts, which boot the real entry against a document of plain objects and a clock the test moves, so a key, an on-screen button, a thumb stick, a dragged finger, a locked mouse and a missing context are all checked with no browser.src/server.test.tspins the route's status, headers, script and every id the entry looks up, and that cs's ids and bundle are not on it.I did not refactor the dispatch into
src/routes.ts:/rangeis one moreifbeside/, withwithoutBodyIfHead/isReadlifted out so both read in one line — the server still fits in one read, and adding the game and moving the table in one pull is the thing the issue warns about. Measured locally:/rangeanswers in 0.5–0.8 ms warm (first request 8 ms, cold start),bun testis 249 green across 32 files, both bundles rebuilt and committed. The frame rate itself is what the page prints for you — there is no browser in this sandbox, so I have not measured 60 fps, only the frame time the readout reports.🤖 Generated with Claude Code
Closes #24