About this wheel spinner

A small, dependency-free tool for one job: turning a list of entries into a fair, animated random pick. No account, no upload, and the list you type is never recorded anywhere but your own browser.

Why it exists

A spinning-wheel picker looks simple and is easy to get subtly wrong. The most common shortcut — spin the wheel by some random-looking amount and read off whichever segment stops under the pointer — can be biased in ways that are not obvious from watching it run, especially if the random spin range does not divide evenly by the number of segments. This tool instead commits to a specific, checkable order of operations: pick the winner first, then solve for the one rotation that lands on it. That separation is the entire design.

How the pick and the animation are implemented

The logic lives in one small, dependency-free module (wheel.js) kept completely separate from the code that touches the page, so the maths can be checked on its own:

  • The winner is drawn first. Math.floor(Math.random() * N) over the current entry count, giving every entry an equal 1-in-N chance.
  • The rotation is solved backwards from the winner. Each segment spans 360 / N degrees; the tool computes the one rotation value (plus a handful of extra full turns, purely for the animation) that places the centre of the winning segment exactly under the fixed pointer at the top of the wheel.
  • Rotation only ever increases. The wheel's total rotation is tracked as a running total across spins, never reset to a small number, so every spin visibly keeps turning forward from wherever it already stopped — it never snaps backward to get to the next target.
  • Segment geometry (slice paths, label positions, colours) is computed the same pure way, then handed to small DOM-building code that draws it with createElementNS — nothing on this page is built with innerHTML.

How it was verified

Before shipping, the pure logic was run under plain Node, outside the browser, against checks that do not depend on watching an animation:

Verification checks run against the wheel logic
CheckMethodResult
Uniformity of the pick300,000 simulated spins across 6 entries; each index's share compared to the expected 1-in-6within 0.5% of expected on every index
Rotation always lands on the winnerEvery combination of 2–50 entries, every index, several starting rotations and extra-spin counts, checked that the winning segment's centre lands under the pointer to within floating-point precisionexact in every case tested
Rotation never runs backwardsSame sweep, checked the new total rotation is never less than the rotation before the spinheld in every case tested
Shuffle correctnessChecked the shuffled list is always the same entries in a different order, and that repeated shuffles are not silently returning the original orderpassed
Entry parsingBlank lines and surrounding whitespace are dropped; lists beyond 50 entries are truncated and flaggedpassed

The uniformity check is statistical, not a proof — with any finite number of trials there is always some sampling noise, which is why the check allows a small tolerance rather than demanding an exact split. What is guaranteed by the code, not just observed in a sample, is that each pick is drawn independently and with equal probability per entry; that is a property of Math.floor(Math.random() * N) itself, not something that could drift with more spins.

How the site is built

  • Static HTML, one small stylesheet, two small scripts. No framework, no build step, no bundler.
  • Nothing is fetched from the network. No CDN framework, no web font, no remote image; the favicon and header glyph are inline SVG. The page works offline once loaded.
  • System font stack — your operating system's own UI font, so nothing downloads and nothing shifts as the page loads.
  • Nothing you type is transmitted. The whole pick happens in your browser. Your entry list is written only to that browser's local storage, purely so it is still there next time you open the page on the same device.
  • Reduced motion is respected. If your system asks for less animation, the wheel skips the multi-second spin and reveals the winner immediately instead.
  • Dark mode follows your system setting via prefers-color-scheme.

Scope and honesty about limits

This is a picking tool for everyday decisions — classrooms, giveaways, streams, "what's for dinner." It uses the browser's standard Math.random(), which is not a cryptographically secure random number generator and carries no formal guarantee against a determined adversary studying the browser's internal state. It should not be used to draw numbers for a real-money lottery or anything legally requiring a certified, auditable source of randomness.

It also keeps no history: it does not log past spins, does not sync a list between devices, and cannot weight one entry above another (list something twice if you want it twice as likely). If you need a record of who was entered before a draw, copy the list yourself beforehand — the tool will not do that for you.