280 lines
7.4 KiB
Markdown
280 lines
7.4 KiB
Markdown
|
|
# P2P Poll App
|
|
|
|
A peer-to-peer polling application built with React, TypeScript, Tailwind CSS, Node.js, Yjs, and WebSocket for real-time collaborative voting.
|
|
|
|
**Users can create polls, add answers, and vote in real-time with automatic P2P synchronization across all connected clients.**
|
|
|
|
## Architecture
|
|
|
|
**Hybrid P2P Approach:**
|
|
- Backend serves as both a Yjs WebSocket provider (for state synchronization) and signaling server (for WebRTC peer discovery)
|
|
- Clients sync poll data via Yjs CRDT for conflict-free merging
|
|
- Direct P2P connections via WebRTC for real-time updates when possible
|
|
- Server fallback ensures reliability when P2P fails
|
|
|
|
## Tech Stack
|
|
|
|
**Backend:**
|
|
- Node.js + TypeScript
|
|
- Express.js
|
|
- WebSocket (ws)
|
|
- y-websocket (Yjs WebSocket provider)
|
|
- CORS support
|
|
|
|
**Frontend:**
|
|
- React 18 + TypeScript
|
|
- Vite (build tool)
|
|
- Tailwind CSS
|
|
- Yjs (CRDT library)
|
|
- y-websocket (server sync)
|
|
- y-webrtc (P2P sync)
|
|
- lucide-react (icons)
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
quicgroup/
|
|
├── server/ # Backend Node.js server
|
|
│ ├── src/
|
|
│ │ ├── index.ts # Main server entry
|
|
│ │ ├── yjs-server.ts # Yjs WebSocket provider
|
|
│ │ ├── signaling-server.ts # WebRTC signaling
|
|
│ │ ├── types/ # TypeScript types
|
|
│ │ └── utils/ # Utilities
|
|
│ ├── package.json
|
|
│ └── tsconfig.json
|
|
│
|
|
└── frontend/ # React frontend
|
|
├── src/
|
|
│ ├── components/ # React components
|
|
│ ├── hooks/ # Custom React hooks
|
|
│ ├── lib/ # Yjs setup and utilities
|
|
│ ├── types/ # TypeScript types
|
|
│ └── styles/ # CSS styles
|
|
├── package.json
|
|
└── vite.config.ts
|
|
```
|
|
|
|
## Setup Instructions
|
|
|
|
### Prerequisites
|
|
- Node.js 18+ and npm
|
|
|
|
### Backend Setup
|
|
|
|
1. Navigate to server directory:
|
|
```bash
|
|
cd server
|
|
```
|
|
|
|
2. Install dependencies:
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. Copy environment file:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
4. Start the development server:
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
The server will run on `http://localhost:3000` with:
|
|
- Yjs WebSocket: `ws://localhost:3000/yjs`
|
|
- Signaling WebSocket: `ws://localhost:3000/signal`
|
|
|
|
### Frontend Setup
|
|
|
|
1. Navigate to frontend directory:
|
|
```bash
|
|
cd frontend
|
|
```
|
|
|
|
2. Install dependencies:
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. Copy environment file (optional):
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
4. Start the development server:
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
The frontend will run on `http://localhost:5173`
|
|
|
|
## Running the Application
|
|
|
|
1. **Start Backend** (Terminal 1):
|
|
```bash
|
|
cd server
|
|
npm run dev
|
|
```
|
|
|
|
2. **Start Frontend** (Terminal 2):
|
|
```bash
|
|
cd frontend
|
|
npm run dev
|
|
```
|
|
|
|
3. **Open Browser:**
|
|
- Navigate to `http://localhost:5173`
|
|
- Open multiple tabs/windows to test P2P synchronization
|
|
|
|
## Features
|
|
|
|
### Dynamic Poll Creation
|
|
- **Create Polls** - Any user can create new polls with custom questions
|
|
- **Add Answers** - Anyone can add answer options to any poll
|
|
- **Real-time Voting** - Vote on options with instant updates across all clients
|
|
- **Smart Vote Tracking** - One vote per user per option (prevents duplicate voting)
|
|
- **Visual Feedback** - Green border and " Voted" indicator on voted options
|
|
- **User Attribution** - See who created each poll and option
|
|
- **Live Vote Counts** - See vote percentages and counts update in real-time
|
|
- **P2P Synchronization** - Uses Yjs CRDT for conflict-free state merging
|
|
- **Connection Status** - Visual indicator showing WebSocket and peer connections
|
|
- **Hybrid Architecture** - Combines WebSocket server sync with WebRTC P2P
|
|
- **Beautiful UI** - Modern gradient design with Tailwind CSS
|
|
|
|
## How to Use
|
|
|
|
### Create a Poll
|
|
1. Enter your question in the "Create a New Poll" form at the top
|
|
2. Click "Create Poll"
|
|
3. Your poll appears instantly for all connected users
|
|
|
|
### Add Answer Options
|
|
1. Find the poll you want to add an answer to
|
|
2. Type your answer in the "Add a new option..." field
|
|
3. Click "Add"
|
|
4. Your answer appears instantly for all users
|
|
|
|
### Vote on Options
|
|
1. Click the vote button (thumbs up icon) on any option
|
|
2. You can only vote once per option
|
|
3. Voted options show a green border and " Voted" indicator
|
|
4. Vote counts update in real-time across all clients
|
|
|
|
### Multi-User Testing
|
|
1. Open multiple browser tabs/windows
|
|
2. Create polls from different tabs
|
|
3. Add answers from different tabs
|
|
4. Vote from different tabs
|
|
5. Watch real-time synchronization in action!
|
|
|
|
## How It Works
|
|
|
|
### CRDT Synchronization
|
|
The app uses Yjs (a CRDT library) to ensure all clients converge to the same state without conflicts:
|
|
- Each client maintains a local Yjs document
|
|
- Changes are automatically synced via WebSocket to the server
|
|
- WebRTC provides direct P2P connections between clients
|
|
- Yjs handles merge conflicts automatically
|
|
- One vote per user per option is enforced via `votedBy` tracking
|
|
|
|
## Data Model
|
|
```typescript
|
|
{
|
|
polls: Array<{
|
|
id: string,
|
|
question: string,
|
|
createdBy: string,
|
|
timestamp: number,
|
|
options: Array<{
|
|
id: string,
|
|
text: string,
|
|
votes: number,
|
|
votedBy: string[], // Tracks which users have voted
|
|
createdBy: string,
|
|
timestamp: number
|
|
}>
|
|
}>
|
|
}
|
|
```
|
|
|
|
## Testing P2P Functionality
|
|
|
|
1. Open the app in multiple browser tabs/windows
|
|
2. **Create polls** from different tabs - they appear everywhere instantly
|
|
3. **Add answer options** from different tabs to the same poll
|
|
4. **Vote** from different tabs - watch vote counts update in real-time
|
|
5. Try voting twice on the same option - it won't let you!
|
|
6. Check the connection status indicator for peer count
|
|
7. Verify visual feedback (green border) on options you've voted on
|
|
|
|
## Development
|
|
|
|
### Backend Scripts
|
|
- `npm run dev` - Start development server with hot reload
|
|
- `npm run build` - Build for production
|
|
- `npm start` - Run production build
|
|
|
|
### Frontend Scripts
|
|
- `npm run dev` - Start Vite dev server
|
|
- `npm run build` - Build for production
|
|
- `npm run preview` - Preview production build
|
|
|
|
## Environment Variables
|
|
|
|
### Backend (.env)
|
|
```
|
|
PORT=3000
|
|
YJS_WS_PORT=1234
|
|
NODE_ENV=development
|
|
CORS_ORIGIN=http://localhost:5173
|
|
```
|
|
|
|
### Frontend (.env)
|
|
```
|
|
VITE_WS_URL=ws://localhost:3000
|
|
```
|
|
|
|
## Components
|
|
|
|
### Frontend Components
|
|
- **PollView** - Main view showing all polls and create poll form
|
|
- **CreatePoll** - Form to create new polls
|
|
- **PollCard** - Individual poll display with metadata
|
|
- **OptionList** - List of answer options with vote tracking
|
|
- **AddOption** - Form to add new answer options
|
|
- **VoteButton** - Vote button with disabled state for voted options
|
|
- **ConnectionStatus** - Shows WebSocket and P2P connection status
|
|
|
|
### Key Functions
|
|
- `createPoll(question)` - Create a new poll
|
|
- `addOption(pollId, text)` - Add an option to a specific poll
|
|
- `vote(pollId, optionId)` - Vote on an option (one vote per user)
|
|
- `hasVoted(option)` - Check if current user has voted on an option
|
|
|
|
## User Tracking
|
|
|
|
Each user gets a unique ID stored in localStorage:
|
|
- Format: `user-xxxxxxxxx`
|
|
- Used to track poll/option creators
|
|
- Used to prevent duplicate voting
|
|
- Persists across browser sessions
|
|
|
|
## Future Enhancements
|
|
|
|
- [ ] Edit/delete polls and options
|
|
- [ ] User nicknames instead of IDs
|
|
- [ ] Poll expiration/closing
|
|
- [ ] Vote history and analytics
|
|
- [ ] Export poll results
|
|
- [ ] Persistent storage (database)
|
|
- [ ] Dark mode toggle
|
|
- [ ] Mobile responsive improvements
|
|
- [ ] Poll categories/tags
|
|
- [ ] Search/filter polls
|
|
|
|
## License
|
|
|
|
MIT |