A beautiful, private random picker & lucky draw toolkit.
Spin a wheel · Pick a winner · Flip a coin · Roll a die · Split into teams.
No accounts. No tracking. No server.
Your names stay in your browser — everything runs locally, 100% private.
🎡 Live demo: pickly-bw0.pages.dev
Pickly is a modern, privacy-first random selection toolkit for classrooms, teams, events, giveaways, meetings, live streams and games. It started as a redesign and extension of the open-source random-name-picker by Ice Lam (MIT) and grew into a complete product with five tools, a full design system, i18n and PWA support.
| Tool | What it does |
|---|---|
| Wheel | A colorful spinning wheel. Pick 1–10 winners with one tap. |
| Picker | A classic slot-machine lucky draw with blur animation. |
| Coin | 3D coin flip — heads or tails. |
| Dice | 3D dice roll with real pip faces. |
| Teams | Split your list into 2–8 balanced teams. |
- Add, edit, delete and reorder entries (drag & drop on desktop, ↑/↓ on touch)
- Paste lists — one per line; commas and semicolons work too
- Import (replace or append) and export to a
.txtfile - Shuffle and remove duplicates in one click
- Sample lists for parties, classes, lunch and games
- Handles 1,000+ entries, emoji, Chinese and very long names without breaking
- Multiple winners — pick 1–10 winners per draw
- Remove winners from the list automatically (toggleable)
- Undo any draw from the winner dialog or the history panel
- Full history with relative timestamps; clear anytime
- Polished light & dark themes (auto / light / dark)
- English and 中文 (Simplified Chinese) — switch instantly
- Confetti, elegant sound effects (Web Audio — no audio files), spring animations, micro-interactions
prefers-reduced-motionsupport plus a manual "reduce animations" setting- PWA — installable, works offline, auto-updates
- Keyboard-friendly: full focus management, Esc closes dialogs, ARIA labels
- Mobile-first responsive layout — bottom-sheet dialogs, big touch targets
- Vite 7 + TypeScript 5 — no framework, dependency-light
- SCSS design tokens with full dark mode (CSS custom properties)
- Canvas 2D wheel with cached segment palette, capped tick sounds and a hybrid rAF/timer animation scheduler that survives background throttling
- Web Animations API for the picker reel
- Web Audio API for synthesized sound effects
- canvas-confetti
- vite-plugin-pwa for offline support
- Vitest for unit tests
- Self-hosted variable fonts (Inter + Space Grotesk) — no external requests
npm install
npm run dev # start the dev server
npm run typecheck # TypeScript checks
npm test # unit tests
npm run build # production build → dist/
npm run preview # preview the production build
npm run icons # regenerate PWA icons / social card (from logo.svg)Pickly is a fully static SPA — it deploys to Cloudflare Pages in minutes.
- Push this repository to GitHub.
- In the Cloudflare dashboard, go to Workers & Pages → Create → Pages → Connect to Git.
- Choose the repository.
- Build settings:
- Framework preset:
Vite - Build command:
npm run build - Build output directory:
dist
- Framework preset:
- Save and deploy.
public/_redirectsprovides the SPA fallback automatically.
npm ci && npm run build
npx wrangler pages deploy dist --project-name=picklyThe repo ships .github/workflows/deploy.yml which builds and publishes on
every push to main. Add two repository secrets:
CLOUDFLARE_API_TOKEN— an API token withCloudflare Pages: EditpermissionCLOUDFLARE_ACCOUNT_ID— your Cloudflare account ID
wrangler.toml is included with the Pages build settings.
src/
├── core/ # store (localStorage), i18n, random helpers, audio, confetti
├── locales/ # en + zh dictionaries (typed, test-covered)
├── modes/ # wheel, picker, coin, dice, teams
├── styles/ # design tokens, base, components, panels, modes
└── ui/ # list manager, history, settings, modals, toasts, stepper
Key decisions:
- No framework — the app is plain TypeScript with a tiny DOM helper, which keeps the bundle at ~21 kB gzipped and the codebase easy to audit.
- State lives in
localStorage(pickly.state.v1) — no backend, no accounts, nothing leaves the browser. - i18n is typed — dictionaries share a key union; a test fails if a translation is missing.
- The wheel is canvas-based — the segment palette is cached, separator strokes are skipped above 200 segments, and tick sounds are capped at 60 per spin so 1,000+ entry wheels stay smooth.
- Animation is throttle-proof — a
setTimeoutwatchdog backs everyrequestAnimationFrameframe, so spins complete even in hidden tabs or low-power mode.
Pickly is a static site. There is no analytics, no tracking pixels, no
third-party requests at runtime and no server-side storage. Your entry lists,
settings and history live only in your browser's localStorage.
- Pickly is licensed under the MIT License.
- The original project, random-name-picker by Ice Lam, is MIT-licensed. Its copyright notice is preserved in LICENSE-ORIGINAL, and the adapted components (reel animation, sound engine, shuffle) are credited in THIRD_PARTY_NOTICES.md.
The original is a single-screen slot-machine lucky draw in Pug + SCSS + Webpack. Pickly is a full product rebuilt on Vite: five tools (wheel, picker, coin, dice, teams), a complete list manager, winner history with undo, dark mode, EN/中文 localization, PWA/offline support, accessibility hardening and a new design system — while keeping the reel animation, sound engine and shuffle algorithm with attribution.
Made with ♥ for classrooms, teams, events and games.