# 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