Skip to content

Repository files navigation

Spin Wheel Randomizer

A spinning wheel that picks a random name. Type names in, weight the odds, hit spin, and get a winner. Everything runs in the browser: no server, no account, no data leaves your device.

Live: https://adam-ctrlc.github.io/spin-wheel-randomizer/

Features

  • One input for one name or a whole list. Type a name and press Enter, or paste dozens at once separated by line breaks, commas, or semicolons. Duplicates and blank lines are dropped automatically.
  • Weighted odds. Every name carries a weight from 1x to 100x. A 3x name gets a slice three times wider and wins three times as often.
  • Honest draws. The winner is chosen first from crypto.getRandomValues, weighted per slice, and then the animation is aimed at it. What stops under the pointer is always the real result.
  • Remove the winner, and bring them back. Optional raffle mode takes each winner off the wheel, and a single button restores every set aside name with its original weight.
  • Keeps spinning in a background tab. Progress comes from wall clock time with a timer backstop, and the tick and chime audio is scheduled on the Web Audio clock up front, so switching tabs mid spin does not freeze or desync it.
  • Distinct neighboring colors. Slice hues are assigned with a stride co-prime to the slice count, so every adjacent pair, including the last slice wrapping around to the first, sits as far apart on the color wheel as the count allows.
  • Shareable links. The share button copies a URL that encodes every name and weight, so anyone who opens it sees the same wheel.
  • Sound and confetti. A tick per slice, a four note chime on landing, and a confetti burst behind the winner dialog. All muteable.
  • Fits one screen. The page itself never scrolls, on desktop or phone, and the side panel scrolls internally when space is tight.
  • Light and dark themes, plus reduced motion support that shortens spins and skips confetti.
  • Saved locally. Names, weights, options, and recent winners persist in localStorage.

Stack

Getting started

pnpm install
pnpm dev

Then open the printed URL. Other useful commands:

pnpm check     # svelte-check and TypeScript
pnpm build     # static output into build/
pnpm preview   # serve the built output

How the code is organized

Code is grouped by domain rather than by layer, and behavior lives in small classes with a single job. Dependencies are injected, and the abstractions are written so any implementation can be swapped in without the caller noticing.

src/lib/
  core/         Ports: KeyValueStore, Codec, RandomSource
  storage/      Local storage and in memory stores, JSON codec, rune backed PersistentState
  random/       CryptoRandomSource and SeededRandomSource
  entries/      Entry value object, EntryCollection, share link codec, list and input UI
  wheel/        Geometry, layout, palette, spin planning and animation, SpinController
  audio/        SpinSounds port with Web Audio, silent, and gated implementations
  celebration/  Celebration port with confetti and no-op implementations
  settings/     Settings, motion preference, options UI
  history/      SpinResult and HistoryLog
  hint/         The in-app guide modals
  brand/        Logo
  errors/       Status code copy for the error page
  app/          WheelApp, the composition root that wires everything together

Two details worth knowing if you are reading the code:

Substitutability is deliberate. KeyValueStore, Codec, RandomSource, SpinSounds, Celebration, and Easing each document their contract, and every implementation honors it exactly. SilentSpinSounds does nothing rather than throwing, LocalStorageKeyValueStore swallows quota errors rather than surfacing them, and SeededRandomSource returns the same range as CryptoRandomSource. Callers never inspect which implementation they were handed.

Angles. Zero degrees is twelve o'clock and angles increase clockwise. A point at wheel angle a sits under the pointer when the rotation satisfies a + rotation = 0, which is what SpinPlanner solves to aim a spin at the already chosen winner.

License

Apache License 2.0.

Contributing

See CONTRIBUTING.md.

About

A weighted spinning wheel that picks a random name. Runs entirely in the browser, keeps spinning in background tabs, and shares wheels by link.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages