forked from quic-issues/427e7578-d7bf-49c8-aee9-2dd999e25316
3.2 KiB
3.2 KiB
P2P Poll App
A peer-to-peer polling app built with Automerge and Vanilla JS. No backend required — polls sync in real time across browsers using CRDTs and a WebSocket relay.
Features
- Add options — type an option and press Enter or click "Add Option". Duplicate options (case-insensitive) are rejected with an inline error message.
- Vote on options — click the vote button next to any option. You can vote on multiple options, but only once per option.
- Toggle votes — click your vote again to remove it (the button turns green with a checkmark when you've voted).
- Live vote counts — options are sorted by vote count in descending order and update in real time as votes come in from other users.
- 2-minute countdown timer — click "Start 2-min Vote" to begin a shared countdown. Voting is open before and during the countdown. Once the timer expires, all vote buttons are disabled.
- Shared timer — the deadline is stored in the Automerge document, so all peers see the same countdown and voting closes simultaneously for everyone.
- Copy URL — click "Copy URL" to copy the poll link to your clipboard. Share it with others to join the same poll.
- P2P sync — all state (options, votes, timer) syncs across browsers in real time with no central server handling your data.
How it works
Tech stack
- Automerge via
@automerge/vanillajs— a CRDT library that lets multiple clients concurrently edit shared documents and merge changes without conflicts. - BroadcastChannelNetworkAdapter — syncs between tabs in the same browser instantly via the browser's BroadcastChannel API.
- WebSocketClientAdapter — syncs across different browsers/devices via a WebSocket relay (
wss://sync.automerge.org). The relay only forwards CRDT messages; it does not store or interpret your data. - IndexedDBStorageAdapter — persists the document locally so it survives page refreshes.
- Vite — bundles the app with WebAssembly support (required by Automerge).
Data model
The poll is a single Automerge document with three fields:
{
options: string[], // list of poll options in insertion order
votes: { [option]: number }, // vote count per option
deadline: number | null // Unix timestamp (ms) when voting closes, or null
}
URL-based sharing
Each document gets a unique Automerge URL (e.g. automerge:abc123...) stored in the page's URL hash. Opening the same URL in any browser loads and syncs the same document. Creating a new poll generates a new document and updates the hash automatically.
Voting rules
- Voted options are tracked in
localStorage(keyed by document URL), so they persist across page refreshes but are isolated per browser. - One vote per option per user. Votes can be toggled off and back on until the timer expires.
- The timer (
doc.deadline) is set once by whoever clicks "Start 2-min Vote" and is shared via the Automerge document, so all peers use the same deadline.
Running locally
pnpm install
pnpm dev
Open the printed localhost URL. To test cross-browser sync, copy the URL (including the #automerge:... hash) and open it in a different browser.