Skip to content

Repository files navigation

🍷 Wine Night

Wine Night is a mobile-friendly blind tasting app for small social events. Each couple can bring a bottle and contribute to the pot, while every attendee can taste, vote, and keep private notes from their own phone.

How it works

  1. The host creates a room, enters the wines, and starts the tasting.
  2. Guests join with the room code and vote using numeric scores, a full ranking, or a top-three ranking.
  3. The host locks voting and controls a staged results reveal.

During tasting, bottles are identified as Wine 1, Wine 2, and so on. The number entered during setup should match the number on the bottle's physical bag.

Scoring

Raw numeric averages are not comparable when participants use different scales or scoring habits. Wine Night converts each person's ballot into ranks before combining the results.

  • Numeric voters choose their own scale maximum. Equal scores remain tied.
  • Full-rank voters order every wine.
  • Top-three ballots and incomplete numeric ballots leave the remaining wines tied below the wines that were scored.
  • Unranked ties share the average of the remaining Borda positions, keeping the total weight of each ballot equal without inventing preferences.
  • A Condorcet winner is recognized when one wine beats every other wine in head-to-head comparisons. Otherwise, the Borda totals determine the order.

Exact unresolved ties are shown as shared places. The close, clear, and decisive result labels are descriptive summaries, not statistical significance tests.

Local development

npm install
npm run dev

The local server runs at http://localhost:8787.

Command Purpose
npm run dev Start the local Cloudflare development server
npm test Run the automated test suite
npm run typecheck Validate Cloudflare types and TypeScript
npm run cf-typegen Regenerate Cloudflare binding types
npm run deploy Deploy or update the workers.dev version
npm run deploy:domain -- DOMAIN Deploy or update with a custom domain
npm run destroy:dry-run Preview deletion of the Cloudflare deployment
npm run destroy Delete the live Cloudflare Worker and its data

Cloudflare deployment

See Cloudflare deployment and operations for initial deployment, custom domains, room backups, restores, monthly downtime, public-hosting safeguards, and permanent teardown.

Architecture and privacy

  • src/index.ts: HTTP API, static assets, authentication, rate limits, and WebSocket routing.
  • src/archive.ts: versioned host-backup validation and import limits.
  • src/event.ts: room state in a Durable Object with SQLite storage and caller-scoped live updates.
  • src/scoring.ts: rank conversion, Borda and Condorcet calculations, Spearman correlation, and result analytics.
  • public/: dependency-free HTML, CSS, and JavaScript frontend.

Host actions require a random room-specific host key. Each voter receives a separate participant key stored per room and browser tab. Before reveal, a voter can retrieve only their own ballot and private notes. The complete raw-votes table is host-only.

Inactive rooms expire after 90 days. Bottle prices are optional, and price-based analysis is omitted when no usable prices were entered.

Statistical and voting-method references

License

Wine Night is released under the Zero Clause BSD License (SPDX: 0BSD).

Copyright © 2026 Aaron Bull Schaefer and contributors

About

A blind tasting app for small social events

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages