Server Overview
Live process health · refreshes every 2sEvent-loop lag & CPU
Requests/s & active runs
Memory (RSS & heap)
Replay-pool queue
Per-route latency (recent window)
| Route | Count | Avg ms | p50 | p95 | p99 | Max | 5xx |
|---|
Runs & Enforcement
Every saved run + enforcement action, and the recorded bot runs. ▶ Watch replays any run.| Time | School | Nickname | Mode | Verdict | Claimed | Server/Replay | Reasons | Input | Lv | Frames | Replay |
|---|---|---|---|---|---|---|---|---|---|---|---|
Leaderboard Management
Standings, CSV export, targeted removal of test/junk data, and round clearing.| # | School | Best score | Character | Levels | Time | Players | Runs | Status | Manage |
|---|
Danger zone
School Approvals
The full approval queue + code requests (the old schools.html, folded in).A school that couldn't be matched to the national school list stays off the public leaderboard until it is approved — its students play the whole time and their runs are already counted. Approving with a directory match replaces the typed name with the official one.
Stage Ratings
What players say about each BUILT-IN stage, asked the moment they clear it.Two questions, one vote per player per stage, latest wins: stars (did you enjoy it) and difficulty (1 easy … 5 hard). Difficulty is the one to act on — a stage sitting near 5 with few stars is one children are bouncing off. Votes are keyed to the stage position, not the blueprint version, so they survive a rebuild; a stage removed from the campaign keeps its old votes, marked retired. Turn the whole panel off under Anti-cheat → Game features.
| # | Stage | Votes | Stars | Difficulty | How it feels |
|---|
Device Nominations
AEDs registered at /nominate, each one an entry in the AED draw — one per device serial (a CSV upload is one entry per AED, grouped by its upload batch). Separate from the schools game.These are draw entries, not game registrations — nothing here plays, scores or registers a school. Approved = a valid entry that stands in the draw; rejected = not a valid entry. A serial is spent the moment it's entered and stays spent through both — that's what stops a "no" being re-rolled until it turns into a "yes". Withdraw is the only status that hands the serial back, for a genuine mistake (wrong serial, wrong organisation). Nothing is deleted: the withdrawn record stays in the journal beside whatever replaces it. Contact details are typed by the nominator and unverified — we don't contact the nominee off the back of an entry. An owner with several AEDs can upload a CSV: every device becomes its own entry (own reference, own serial), all sharing one upload batch and one nominee — click a batch to see its devices together. Withdrawing one device of a batch frees that serial only.
Event Competitions
Booth competitions at real-world events — one round per email, top verified score wins. Completely separate from the schools game: own stage, own board, own data.Entries
Current leader
| # | Name | Company | Score | Time | Hero | Status | Registered | Manage |
|---|
Verified = the server replayed the round and it ranks (score = the replay's, never the browser's). Rejected = it didn't verify (tampered score, cheat, impossible pace) — it never ranks and still uses up that email. Pending = the replay couldn't run at the time — press Re-verify. Playing = started, no score yet (a crashed or abandoned round). Void = staff cancelled it (a mistake, a crash): it leaves the board and the email may sign up again. Nothing is deleted. Delete = gone for good — for staff test rounds: the entry, its recorded round and its database row are erased, and the email may sign up again. Tick rows (or the header box for every entry shown — use the filter and search to narrow it) and press Delete selected. A winner must be unmarked first.
Bot Runs
Recorded headless test-bot playthroughs — a diagnostic, never competition data. ▶ Watch plays one back.Takes the JSON produced by Download run recording on the game's end screen — the button that only appears for cheated, test-level or altered-rules runs. Stored here for watching only: bot runs sit outside the journal, the leaderboard and the prize audit, so an uploaded run can never be scored.
| Label | Character | Start level | Levels | Score | Frames | Note | Replay |
|---|
Anti-cheat
Toggle the runtime defences, and publish/restart the server.Game features
Server
A plain restart does not pick up edited levels — the campaign is compiled into
game.js. Publish injects every saved level plus the campaign order,
rebuilds, then restarts. If the build fails nothing changes and the service keeps running.
🏅 Point values (what each pickup and kill is worth) are set per campaign on the level editor's campaign screen — so new values can be pre-set on the next round's campaign and take over at the rollover, without repricing the round in progress. Publish compiles them, exactly like level changes.
Configured at boot from ktbg.env:
Badge tiers
What the downloadable badge says for how far a player got.Every player who finishes a run and scores can download a badge. What it says depends on how far through the campaign they got. Thresholds are a percentage of the campaign, not a level number, so they keep working when a scheduled campaign changes length. These take effect immediately on save — no publish, no restart.
Character maker
Build a look, then export the five sprite files the game loads.The look code is the whole design in one line — paste it to someone else and they get exactly this character. Export writes the five PNGs the game loads.
Adds the character to the hero picker straight away — no files to upload and no restart. The look is drawn from the code above, so you can restyle it later. Special abilities are set once and can never be changed: runs already played as this character replay with these specials, and altering them would make honest scores fail verification.
Open to every player. Each joined student can create ONE hero of their own —
a look, a name from the word reels (public/hero-name-words.json) and one
of the four powers — straight after joining; the game invites them in once per sign-in.
A run with a hero is played and replayed as the base character whose power they
chose, so scoring and replays are unaffected. The old school unlock threshold below
no longer does anything and is kept only so its saved value is not lost.
How many levels one player may keep at a time. They delete one to make room for another. An admin can unlock the builder for a whole school on the Schools page, which also hands that school every piece below — otherwise a player earns each one by clearing stages.
Progressive unlocking. How many stages a player must clear in one saved run before each piece appears in their palette. Measured against their best run in any leaderboard period, so nothing is lost when the round rolls over. 0 = always available; the campaign length = finish the whole game.
- Build the look above and press Export sprite set — five PNGs download.
- Drop them into
public/Graphics/sprites/as<id>-right.png,-left,-jump,-squat,-beam. - Replacing an existing character stops there. A NEW one also needs an entry in
CHARACTER_OPTIONSinserver/game.src.js, then a build and restart. - Art is cached for a year, so bump
ASSET_VERSIONin the same file whenever a sprite is replaced in place — otherwise returning players keep the old one.
The originals are kept in server/sprite-originals/ — copying them back
over the live files restores the shipped cast.
Tools & Runbooks
Load testing, the editor, and the CLI commands behind these pages.Stress test the server
Simulate 1–10,000 players playing real, replay-verifiable runs, then watch the Overview tab live. Runs from the machine with the repo:
# against the isolated sandbox (safe):
node tools/stress.mjs --players 500 --duration 120
# heavier, faster submits:
node tools/stress.mjs --players 5000 --pace fast --duration 180
# read-only GET load only:
node tools/stress.mjs --players 2000 --mode api
Stress players register as STRESS… schools; remove them from the Leaderboard tab when done. Per-IP rate limiting is off (KTBG_RATE_LIMIT_IP=off) because a school shares one NAT address — counting per IP would lock out a whole class. Per-run and per-school limits still apply, so a stress run submits freely.
Level editor
Drag-and-drop level design with smart randomise and a playability + accessibility linter. Test-play a draft instantly (test runs never save a score).
Watch a run
Prize audit & CSV
Batch-verify the top schools' best runs before awarding, and export a round.