akinwumisehinde e14bb6d425 feat: implement dynamic P2P polling app with real-time synchronization
- Add complete P2P polling application with React + TypeScript frontend
- Implement Node.js backend with Yjs WebSocket and WebRTC signaling
- Support dynamic poll creation, answer management, and voting
- Add CRDT-based state synchronization using Yjs for conflict-free merging
- Implement user tracking and vote prevention (one vote per user per option)
- Create modern UI with Tailwind CSS and visual feedback
- Add comprehensive documentation and setup instructions

Features:
- Users can create polls with custom questions
- Anyone can add answer options to any poll
- Real-time voting with instant cross-client synchronization
- Smart vote tracking with visual feedback for voted options
- User attribution showing who created polls and options
- Connection status indicators for WebSocket and P2P connections

Technical:
- Hybrid P2P architecture (WebSocket + WebRTC)
- CRDT-based state management with Yjs
2026-03-25 11:51:33 +01:00

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:
cd server
  1. Install dependencies:
npm install
  1. Copy environment file:
cp .env.example .env
  1. Start the development server:
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:
cd frontend
  1. Install dependencies:
npm install
  1. Copy environment file (optional):
cp .env.example .env
  1. Start the development server:
npm run dev

The frontend will run on http://localhost:5173

Running the Application

  1. Start Backend (Terminal 1):
cd server
npm run dev
  1. Start Frontend (Terminal 2):
cd frontend
npm run dev
  1. 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

{
  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

Description
No description provided
Readme 3.9 MiB