One HTML file · a hall with reverb · one board on every phone

Broom & Bladehow it was built

A chore tracker that plays like an RPG, built for one household and shipped as a single file. It runs one board across every phone in the house, and its rarest relic has a face. This page is what's underneath the candlelight — for anyone curious how it works rather than doing the dishes.

Fair warning: this page explains the game's surprises. If you're going to play it, play first.

1HTML file
0Dependencies
147KBThe game file
76Lore entries
12Character hall code
0Audio files
Anatomy of the hall

Seven rooms, seven mechanisms

Each part of the game is a different kind of problem underneath. The player's view is on the left. How it works is on the right.

01

Hold to seal

A tap on the ✓ only reminds you to hold. The seal completes after about seven-tenths of a second of held press while a gold ring fills around it — scroll past it and nothing happens.

Underneath

Pointer events with capture. The ring is a conic-gradient driven by a CSS variable on requestAnimationFrame, but completion is a plain timer — so a throttled or paused frame can never swallow a real press. Any drift past 14px, or the browser taking the gesture for a scroll, resets it. Keyboard users press Enter to arm and Enter again to confirm.

02

The Skill Grove

Every chore is a rune on a tree — dailies down the left limb, bounties down the right. Ranks climb from Novice to Legendary on a completions curve, and a rank-up plays a harp.

Underneath

Inline SVG: two quadratic Bézier limbs, with nodes placed by bisecting each curve for even vertical spacing — placing them by curve parameter clumped neighbours near the bend. Node radius and glow scale with rank. The harp is six triangle-wave notes through a ConvolverNode fed by a generated decaying-noise impulse: a hall, not a beep.

03

The nightly chance

Clear every daily quest and a hooded merchant sets three boxes on the table: a fortune, a gift, a curse. Every fifth clean-sweep day he bows instead — a hundred gold, or a box with a relic that can't be bought.

Underneath

Outcomes are shuffled per offer. The day is spent only when a box is chosen, so closing the app mid-choice re-offers it tomorrow-proof. Relics roll by rarity weight — 38 / 28 / 20 / 10 / 4 — over the still-unowned pool. Ceremonies chain in order (rank-up, then level-up, then the merchant) so overlays never stack.

04

Lore that unlocks

Sixty-seven items — thirty-seven pieces of gear and thirty relics — each carry a flavor line and an origin tale you can read only once the thing hangs in your Trophy Hall. The pricier the piece, the taller the tale. The nine titles hang there too, each with a motto and a note on what holding the rank means — sealed until the level is reached.

Underneath

Every string lives in the file, not a CMS, and the Trophy Hall renders unowned relics and unreached titles as sealed slots so nothing leaks. Gear rarity derives from price, so a new item needs no extra field. It's the Plants vs. Zombies almanac, on a chore list.

05

Player select and migrations

Who quests today? Tap a face. The board, the gold and the gear are yours until you log out and the next hero steps in. Resetting the whole saga, or posting a new quest, asks for a password first.

Underneath

One localStorage key holds the household. Every version adds its fields idempotently on load — the merchant ledger, the sweep streak, the relic shelf, the title ledger — so a hero forged in v1 opens v7 with nothing wiped, and a hall online adds only a code beside that key. The reset lives in an in-app dialog because window.prompt() is silently suppressed inside a home-screen PWA, which made the button look dead.

06

The hall online

Open a hall on one phone and it hands you a twelve-character code. Join with that code on the others and everyone plays the same board — heroes, gold, gear, relics, titles, quests. No accounts. Leave the hall and the phone keeps its own save.

Underneath

A free Postgres with every table locked (row-level security, no policies), reachable only through three security definer functions that each take the code. Sync runs after every save, debounced, on return to the app, and when the phone comes back online. Per hero the newer copy wins; the board merges per quest in the database — newer seal wins, dated tombstones for removed quests — so a phone that joins with a fresh board can never wipe another's seals. A weekly cron pings the database so the free project never pauses.

07

The Golden Broom

The one relic that can't be bought is the one with a face. When the merchant's box opens on it, and in its lore sheet, you see a real render: a broom whose handle is a sword hilt, a gold ferrule, three hundred and sixty golden straws, an ember gem in the pommel.

Underneath

Modelled in Blender 5.2 from a single bpy script — no hand modelling; the straws are placed by code — then rendered in Cycles, with an EEVEE turntable for the record. It ships as an 18 KB WebP beside the HTML, with the emoji as fallback if it can't load. Only this relic has art, on purpose, and the Trophy Hall grid keeps the emoji: thirty pixels is too small for a render.

What you can't see while playing

The quiet parts

Most of what's in this file is invisible while playing. One exception at the end.

No audio files

Every sound is synthesised

The seal's ding, the rune chimes, the rank-up harp, the curse box's three sagging notes — all oscillators through the Web Audio API, sharing one generated hall reverb. Nothing is downloaded, because there is nothing to download.

Network

Three requests, all optional

The file fetches its typefaces, one 18 KB relic image, and — once a hall is open — the sync calls. Fonts load through a media="print" stylesheet that swaps to all on load, because a hung font request once froze the game on a blank screen. The image falls back to an emoji. The sync never blocks a tap; offline, the phone plays from its own save.

Playable without a mouse

Keyboard paths and reduced motion

The seal arms on Enter and confirms on Enter. Confetti, the level-up pop and the rune twinkle all step aside for prefers-reduced-motion. Progress survives a closed tab.

Installs like an app

A manifest and three icons

Open it on a phone, add it to the home screen, and it runs standalone with its own icon and splash colour. No store, no account, no build step — it deploys the moment it merges: the static file, plus one tiny serverless function for the weekly keep-alive.

Testing

Checked by playing it

A quick tap must not seal; a held press must. Four sealed dailies summon the merchant; a fifth sweep day makes him bow; a second hero gets their own knock. Each is run in a browser at phone width before a merge. The hall online was tried on two origins against the live database — open, join, seal on each, remove, custom quest, leave, rejoin, wrong code, reset.

Two halls, one database

A second household runs the same file

A second family plays a clone with its own chore list: the same HTML with only the seed block swapped, its own deploy, and saves that never mix. Both halls live in one database, keyed by their codes. Every game change is ported by hand — copy the file, swap the seed back — which is the honest cost of keeping it to one file.

What it doesn't do yet

Referee one hero on two phones

Every phone keeps playing from its own save and syncs after each seal, so it works offline and the hall never blocks a tap. The trade is that the same hero playing on two phones at once resolves as newest-save-wins. Run one hero per phone and it never comes up.

The hall awaits

Take a quest off the board

It opens in a browser, on a phone or a tablet, and it remembers your hero. Nothing to install and nothing to sign up for.