# Plan: Combined P2P Polling App ## Overview Merge the three subfolder projects into a single TypeScript + Yjs + Vite application at the repo root, combining the best features from each. ## Technology Choices - **Language:** TypeScript (from project 3) with strict mode - **CRDT:** Yjs + y-webrtc + y-indexeddb (from projects 1 & 3) - **Build:** Vite (shared by all) - **Package manager:** npm ## Feature Superset From **project 1** (group-efa16e66): - Collaborative title editing via Y.Text (real-time character-level sync) - Delete options - Diff-rendering for poll list (reuse DOM elements) - Peer count display via awareness - Share section with copy-to-clipboard From **project 2** (proposal-8835ffc9): - Deadline/timer system (2-minute voting window with countdown) - Duplicate detection (case-insensitive) From **project 3** (proposal-88461784): - TypeScript types & strict mode - Modular architecture (state, sync, render, identity, app layers) - IndexedDB persistence (offline support) - Online/offline connection tracking - Input validation (max lengths, empty checks) - HTML escaping for XSS prevention - ViewModel pattern for clean render layer ## Data Model (Yjs) ``` Y.Doc ├── poll-meta (Y.Map) │ └── title → Y.Text (collaborative editing from project 1) ├── poll-options (Y.Map) │ └── [optionId] → { id, label, createdAt, createdBy } ├── poll-votes (Y.Map) │ └── [userId] → optionId (single vote per user) └── poll-deadline (Y.Map) └── deadline → number | null (timestamp, from project 2) ``` ## Architecture & File Structure ``` / ├── index.html ├── package.json ├── tsconfig.json ├── vite.config.ts (if needed for any plugins) ├── src/ │ ├── main.ts (entry: mount app) │ ├── app.ts (orchestrator: init sync, bind events, manage state) │ ├── identity.ts (getUserId with localStorage persistence) │ ├── state.ts (types, pure functions, ViewModel creation) │ ├── sync.ts (Yjs doc, WebRTC provider, IndexedDB, connection status) │ ├── render.ts (DOM rendering with escapeHtml, diff-rendering for options) │ ├── components/ │ │ ├── PollTitle.ts (collaborative title input bound to Y.Text) │ │ ├── PollList.ts (diff-rendered option list with sorting) │ │ ├── PollOption.ts (single option: vote bar, vote/delete buttons) │ │ ├── AddOption.ts (input + submit with validation & duplicate check) │ │ ├── StatusBar.ts (connection status + peer count) │ │ ├── ShareSection.ts (copy URL to clipboard) │ │ └── DeadlineTimer.ts (set deadline + countdown display, from project 2) │ └── styles.css (merged: project 1's design tokens + project 3's glassmorphism) ``` ## Implementation Steps ### Step 1: Scaffold root project - Create `package.json` with dependencies: yjs, y-webrtc, y-indexeddb, vite, typescript - Create `tsconfig.json` (strict, ES2022, bundler resolution) - Create `index.html` entry point - Create `vite.config.ts` if needed ### Step 2: Core layer — identity.ts, state.ts, sync.ts - `identity.ts`: port from project 3 (getUserId) - `state.ts`: port types from project 3, add deadline types, add ViewModel with deadline/timer info, add vote percentage calculation from project 1 - `sync.ts`: port from project 3, add Y.Text for title (from project 1), add poll-deadline map, add awareness tracking for peer count (from project 1) ### Step 3: App orchestrator — app.ts, main.ts - `app.ts`: port from project 3, add deadline handlers, add delete option handler, wire up all components - `main.ts`: minimal entry that calls initApp ### Step 4: Components - `PollTitle.ts`: port collaborative Y.Text editing from project 1, add TypeScript types - `AddOption.ts`: merge project 1 (UI/animation) + project 2 (duplicate detection) + project 3 (validation) - `PollOption.ts`: port from project 1 (vote bar, percentage, delete button), add TypeScript - `PollList.ts`: port diff-rendering from project 1, add TypeScript - `StatusBar.ts`: merge project 1 (peer count) + project 3 (online/offline status) - `ShareSection.ts`: port from project 1, add TypeScript - `DeadlineTimer.ts`: new component porting project 2's deadline/countdown logic to Yjs ### Step 5: Styling - Merge CSS: use project 1's design tokens and typography as base, incorporate project 3's glassmorphism panel effects, add timer-specific styles from project 2 ### Step 6: Cleanup - Remove three subfolders (after confirming with user) - Update root README.md