Changelog
What has shipped, and what changed underneath it
The wheel itself
pre-1.0 · 2026-08-29Twelve pages, a wheel you can drag, sound, share links, and a renderer that stopped repainting.
The draw
- Drawn before it moves. A spin picks its winner from
crypto.getRandomValueswith rejection sampling, and the animation is then aimed at that entry. A hard flick buys a longer spin, never a different answer. - The fairness page. The algorithm is the copy there — the code on the page is the code that runs.
- Weights and repeats. An entry's weight is its share of the draw, shown as the percentage it actually buys. Two entries with the same text stay two entries, and the list says how many repeats it found rather than merging them quietly.
The wheel
- Twelve pages. Each one opens on a wheel that is already filled in, and each has one control no sibling has — a number range, an alphabet, a team splitter, a class list, a draw log.
- Drag it and let go. The parting speed becomes extra turns. A press during a spin brings it in early; space and enter spin without hunting for the button.
- A voice. Ticks timed to the dividers the pointer passes, a landing tone, a countdown you can cancel, and a vibration on a phone — each of them switchable, and each stating whether it is currently on.
- Presentation mode. Secondary controls hide, the wheel grows past 70% of the screen's short side, and the result lifts into a high-contrast panel with a reading a room can see.
- Two more ways to show a draw. A slot strip and a card strip, for when a circle is not the right picture.
Keeping and sharing
- Share links are snapshots. The wheel is encoded into the URL, so a link never expires and editing the wheel afterwards does not change what a colleague opens.
- Saved wheels, spin history and weight presets, all in this browser, all exportable to a file you can carry to another one. There is no account, so that file is the only way anything moves between machines.
Underneath
- The renderer moved to canvas. The face is drawn once when the picture changes and the rotation is a transform on the element, so a spin does no per-frame work at all. The entry text is kept as a real, hidden list beside it — a canvas is pixels, and a screen reader needs something to read.
- Reduced motion is implemented. With
prefers-reduced-motion: reducethe travel is skipped and the result is announced straight away. All three competitors measured zero handling of it. - The result is announced. It lands in a live region as selectable text, not as pixels painted on the wheel.
Down to a tool site
pre-1.0 · 2026-08-27The SaaS scaffolding this repo started from is removed rather than switched off.
TossWheel began life as a SaaS starter template, and most of the work of this day was subtraction.
Removed
- Accounts, dashboard, admin and settings. There is nothing to log into and nothing behind a login, so the surfaces are gone rather than switched off — a feature flag left off still ships the code behind it.
- The database, object storage and the key-value cache. The Worker now carries no bindings at all. Lists live in your browser and a shared wheel travels inside the link.
- Payments, the newsletter and the AI surfaces. None of them had a job here.
Decided
- Direction A, "the instrument". Three high-fidelity prototypes were built and one was chosen: the wheel on the left, the list beside it, the action under the wheel, and the wheel as the only coloured object on the page.
- A pre-launch switch. Every response carries
noindexuntil the launch checklist is done, so nothing half-finished gets indexed and then has to be un-indexed.
Why it is written down
Reintroducing a database or a login later would be a product change, not an implementation detail. The constraint is the reason a wheel here needs no account and keeps no copy of your list.