From d05cf7d13dcf81f6cdb647c08b3d7d85172d1498 Mon Sep 17 00:00:00 2001 From: Dimas Wiese Date: Mon, 16 Mar 2026 00:00:01 +0100 Subject: [PATCH] Restore README --- README.md | 348 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 347 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0217c70..9590d32 100644 --- a/README.md +++ b/README.md @@ -1 +1,347 @@ -# P2P Poll App \ No newline at end of file +# P2P Survey App + +A serverless peer-to-peer survey application built with Ionic and Angular. +Survey creators store all data locally in their browser and participants connect +directly via WebRTC — no backend server required. + +--- + +## Table of Contents + +1. [Overview](#overview) +2. [Architecture](#architecture) +3. [Features](#features) +4. [Setup & Installation](#setup--installation) +5. [How It Works](#how-it-works) + - [Creator Flow](#creator-flow) + - [Participant Flow](#participant-flow) +6. [Question Types](#question-types) +7. [Technology Stack](#technology-stack) +8. [Limitations](#limitations) +9. [Self-Hosting the PeerJS Signaling Server](#self-hosting-the-peerjs-signaling-server) +10. [Development Commands](#development-commands) +11. [Technology Choices](#technology-choices) + +--- + +## Overview + +P2P Survey App lets you create and distribute surveys without any server-side +infrastructure. All survey data — questions, participant tokens, and responses — +lives exclusively in the survey creator's browser (IndexedDB). Participants +connect directly to the creator's browser using WebRTC peer-to-peer data +channels, facilitated by the PeerJS library. + +--- + +## Architecture + +``` + Creator Browser (Host) + ┌─────────────────────────────────────────────┐ + │ Ionic/Angular App │ + │ ┌─────────────────┐ ┌──────────────────┐ │ + │ │ PeerService │ │ Dexie (IndexedDB)│ │ + │ │ (PeerJS/WebRTC)│<─>│ surveys │ │ + │ └────────┬────────┘ │ participants │ │ + │ │ │ responses │ │ + │ Peer ID: survey-{id}└──────────────────┘ │ + └───────────┼─────────────────────────────────┘ + │ + [PeerJS Cloud – signaling only, not data relay] + │ + Participant Browser + ┌─────────────────────────────────────────────┐ + │ Opens: /participate?host=survey-{id} │ + │ &token={uuid} │ + │ │ + │ 1. Connect to host peer via WebRTC │ + │ 2. Send { type: 'join', token } │ + │ 3. Receive survey questions │ + │ 4. Fill in answers │ + │ 5. Send { type: 'submit', answers } │ + └─────────────────────────────────────────────┘ +``` + +### Star topology + +The survey creator acts as the central hub. Each participant opens a direct +WebRTC data channel to the creator's browser. The creator's browser validates +tokens, stores responses, and optionally pushes aggregated results back. + +The PeerJS signaling server is only used for the initial WebRTC handshake +(exchanging ICE candidates). Once connected, all data flows directly between +the two browsers — the signaling server never sees response data. + +--- + +## Features + +- **Create surveys** with four question types: free text, multiple choice, + yes/no, and 1–5 rating +- **Generate unique participant links** — each link contains a UUID token that + identifies one participant +- **Token-based access control** — each token can only be submitted once; + reuse is rejected by the host +- **Draft saving** — participants can save answers before final submission + without locking their token +- **Live results** — the creator sees responses update in real time using + Dexie's `liveQuery` +- **Optional results sharing** — the creator can toggle whether participants + see aggregated results after submitting +- **CSV export** — download all responses as a comma-separated file +- **Local-only storage** — all data lives in the creator's IndexedDB; delete + the survey and the data is gone + +--- + +## Setup & Installation + +### Prerequisites + +- Node.js 18+ and npm 9+ +- A modern browser (Chrome, Firefox, Edge, Safari) + +### Install + +```bash +# 1. Install Ionic CLI globally (skip if already installed) +npm install -g @ionic/cli + +# 2. Install project dependencies +npm install + +# 3. Start the development server +ionic serve +``` + +The app opens at `http://localhost:8100`. + +### Build for production + +```bash +ionic build --prod +``` + +Output is written to `www/`. Deploy the contents of `www/` to any static +web host (GitHub Pages, Netlify, Vercel, Nginx, etc.). + +--- + +## How It Works + +### Creator Flow + +1. **Open the app** and click **Create Survey**. +2. **Enter a title** (required) and optional description. +3. **Add questions** — choose a type for each and mark which are required. +4. Click **Create** to save the survey to IndexedDB and navigate to the + **Survey Detail** page. +5. On the detail page: + - Toggle **Show results to participants** if desired. + - Enter a number and click **Generate Links** to create unique participant + tokens. Copy links to share. + - Click **Start Hosting** to initialise the PeerJS peer. The app listens + for incoming connections using the peer ID `survey-{surveyId}`. +6. **Keep this page or the Results page open** while collecting responses. + If the creator navigates away, the peer is destroyed and participants + cannot connect. +7. Click **View Results** to see live aggregated and individual responses. +8. Click **Export CSV** to download all responses. + +### Participant Flow + +1. **Open the unique link** shared by the survey creator. +2. The app parses `host` and `token` from the URL query parameters. +3. A WebRTC connection is established to the host's peer ID. +4. The participant sends `{ type: 'join', token }`. +5. The host validates the token: + - **Invalid token** → error card is shown. + - **Already submitted** → error card is shown (token is locked). + - **Valid** → survey questions are sent back. +6. Participant fills in answers. Answers are auto-saved as drafts after each + blur event (free text) or selection change (other types). +7. Click **Submit** to finalise. The token is locked on the host side. +8. If the creator enabled result sharing, aggregated results are shown. + +--- + +## Question Types + +| Type | Input widget | Aggregation | +|---|---|---| +| **Free Text** | Multi-line textarea | List of all answers | +| **Multiple Choice** | Radio buttons (creator-defined options) | Count per option + bar chart | +| **Yes / No** | Radio buttons (Yes / No) | Count per option + bar chart | +| **Rating** | 5 buttons (1–5) | Average score + distribution bar chart | + +--- + +## Technology Stack + +| Library | Version | Role | +|---|---|---| +| `@ionic/angular` | 8.x | Mobile-first UI components | +| `@angular/core` | 20.x | Application framework | +| `peerjs` | 1.5.x | WebRTC data channel wrapper | +| `dexie` | 4.x | IndexedDB wrapper with liveQuery | +| `qrcode` | 1.5.x | QR code generation (optional usage) | + +--- + +## Limitations + +### Host must be online + +The survey creator's browser **must be open** and on the Survey Detail or +Results page for participants to submit responses. There is no server that +relays or buffers messages. If the creator goes offline, participants see a +"Host is Offline" card. + +### Data loss + +All data is stored in the creator's browser IndexedDB. Data is lost if: +- The creator explicitly deletes the survey +- The browser's storage is cleared (private/incognito mode, clearing site data) +- The browser's IndexedDB quota is exceeded + +Export responses to CSV regularly to prevent data loss. + +### PeerJS Cloud rate limits + +The free PeerJS Cloud signaling server (`0.peerjs.com`) has rate limits and +may occasionally be unavailable. For production use, self-host the signaling +server (see below). + +### NAT traversal + +WebRTC uses STUN to traverse most NAT configurations. Strict corporate +firewalls or symmetric NAT may block direct connections. For full reliability +in such environments, add a TURN server to the PeerJS configuration in +`src/app/services/peer.service.ts`. + +### Browser compatibility + +Requires a browser that supports: +- WebRTC (DataChannels) +- IndexedDB +- `crypto.randomUUID()` + +All modern browsers (Chrome 86+, Firefox 78+, Safari 15.4+, Edge 86+) satisfy +these requirements. + +--- + +## Self-Hosting the PeerJS Signaling Server + +For production deployments, run your own PeerJS server to avoid rate limits. + +### Option 1: npm + +```bash +npm install -g peer +peerjs --port 9000 --key peerjs +``` + +### Option 2: Docker + +```bash +docker run -p 9000:9000 peerjs/peerjs-server +``` + +### Option 3: Node.js + +```javascript +// server.js +const { PeerServer } = require('peer'); +const server = PeerServer({ port: 9000, path: '/peerjs' }); +``` + +### Configure the app to use your server + +Edit `src/app/services/peer.service.ts` and update the `Peer` constructor: + +```typescript +this.peer = new Peer(peerId, { + host: 'your-peer-server.example.com', + port: 9000, + path: '/peerjs', + secure: true, // use wss:// if your server has TLS +}); +``` + +--- + +## Development Commands + +```bash +# Start dev server with live reload +ionic serve + +# Build for production +ionic build --prod + +# Run TypeScript type check +npx tsc --noEmit + +# Lint +npx ng lint + +# Build Angular app only (no Ionic wrapper) +npx ng build +``` + +--- + +## Technology Choices + +### PeerJS over Gun.js + +Gun.js is a decentralized graph database that syncs between peers. However, +a survey has a **star topology** (one host, many participants) — not a mesh +where every peer is equal. PeerJS maps directly to this model: the creator +opens one peer ID, participants connect to it, and all data flows through +that central point. Token validation and response deduplication are trivial +to enforce at the host. Gun.js would require additional complexity to achieve +the same guarantees. + +### Dexie.js over raw IndexedDB + +Raw IndexedDB uses a callback-based API that is verbose and error-prone. +Dexie wraps it in clean Promises, adds a TypeScript-friendly schema +definition, and provides `liveQuery` — a reactive subscription mechanism +that automatically re-runs queries when the underlying data changes. This +powers the live results view without any manual polling or event wiring. + +### Module-based Angular over Standalone Components + +The Ionic CLI scaffolds a module-based project by default with Angular 20. +Module-based components provide a clear separation of concern via `NgModule` +declarations and are well-supported by the Ionic ecosystem. + +--- + +## Project Structure + +``` +src/ +└── app/ + ├── shared/ + │ └── models/ + │ └── survey.models.ts # All TypeScript interfaces + P2PMessage type + ├── database/ + │ └── database.ts # Dexie singleton (AppDatabase) + ├── services/ + │ ├── peer.service.ts # PeerJS wrapper (NgZone-aware) + │ ├── survey.service.ts # Survey/participant CRUD + │ └── response.service.ts # Response storage + aggregation + ├── pages/ + │ ├── home/ # Survey list + │ ├── create-survey/ # Survey creation/editing + │ ├── survey-detail/ # Settings, link generation, hosting + │ ├── survey-results/ # Live results view + │ └── participate/ # Participant survey form + ├── app-routing.module.ts + ├── app.component.ts + └── app.module.ts +```