Add README documentation and refactor test suite
Replace minimal README with full project docs (setup, usage, architecture). Remove trivial tests and add meaningful edge case coverage.
This commit is contained in:
92
README.md
92
README.md
@@ -1 +1,91 @@
|
||||
# P2P Poll App
|
||||
# P2P Poll App
|
||||
|
||||
A peer-to-peer polling application where users can create polls, add options, and vote — all without a central server. Built for the [Evocracy democratic coding research experiment](https://demcode.evocracy.org/).
|
||||
|
||||
## How It Works
|
||||
|
||||
Data is synchronized directly between peers using [Automerge](https://automerge.org/) CRDTs (Conflict-free Replicated Data Types). There is no backend database — every client holds a full copy of the poll document and changes merge automatically, even when made offline or concurrently.
|
||||
|
||||
**Sync layers:**
|
||||
|
||||
- **WebSocket** (`wss://sync.automerge.org`) — cross-device sync via a public relay
|
||||
- **BroadcastChannel** — instant cross-tab sync within the same browser
|
||||
- **IndexedDB** — local persistence across page reloads and offline use
|
||||
|
||||
## Requirements
|
||||
|
||||
- [Bun](https://bun.sh/) (standalone runtime, no Node.js needed)
|
||||
|
||||
## Getting Started
|
||||
|
||||
```bash
|
||||
bun install # Install dependencies
|
||||
bun run dev # Start dev server (http://localhost:3000)
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. **Create a poll** — Enter a title on the home page and click "Create"
|
||||
2. **Share it** — Copy the shareable link and send it to others
|
||||
3. **Vote** — Click an option to vote; click again to unvote
|
||||
4. **Add options** — Anyone with the link can add new poll options
|
||||
|
||||
Each browser gets a stable peer ID (stored in localStorage) so votes are tracked per-device and double-voting is prevented.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|---|---|
|
||||
| Runtime | [Bun](https://bun.sh/) |
|
||||
| Framework | [Waku](https://waku.gg/) (React Server Components) |
|
||||
| Styling | Tailwind CSS v4 |
|
||||
| P2P sync | Automerge + automerge-repo |
|
||||
| Storage | IndexedDB (client-side) |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── pages/ # Waku page router
|
||||
│ ├── _root.tsx # HTML document shell
|
||||
│ ├── _layout.tsx # Root layout + Providers
|
||||
│ ├── index.tsx # Home page (create/join polls)
|
||||
│ └── poll/[id].tsx # Poll view page
|
||||
├── components/
|
||||
│ ├── Providers.tsx # Automerge Repo initialization
|
||||
│ ├── HomeClient.tsx # Create/join poll UI
|
||||
│ ├── PollPageClient.tsx # Poll ID validation
|
||||
│ ├── PollView.tsx # Poll display, voting, options
|
||||
│ └── ConnectionStatus.tsx # P2P connection indicator
|
||||
├── lib/
|
||||
│ ├── types.ts # Poll & PollOption interfaces
|
||||
│ ├── repo.ts # Automerge Repo singleton
|
||||
│ ├── poll.ts # Pure poll mutation functions
|
||||
│ ├── peer.ts # Peer ID management
|
||||
│ └── __tests__/ # Unit tests
|
||||
└── styles/
|
||||
└── global.css # Tailwind CSS
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
bun test
|
||||
```
|
||||
|
||||
Covers poll creation, voting/unvoting, double-vote prevention, option management, and peer ID persistence.
|
||||
|
||||
## Architecture Notes
|
||||
|
||||
- **Pure business logic** — Poll mutations in `src/lib/poll.ts` are pure functions, used inside Automerge's `changeDoc()` for CRDT-safe updates
|
||||
- **No server state** — The WebSocket relay only forwards sync messages; it never stores or processes poll data
|
||||
- **Offline-first** — The app works fully offline; changes sync when connectivity resumes
|
||||
- **Conflict-free** — Concurrent edits (e.g., two users voting at the same time) merge automatically without conflicts
|
||||
|
||||
## Built With
|
||||
|
||||
This project was built in collaboration with [Claude Code](https://claude.ai/code), Anthropic's agentic coding tool.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user