So I started building. To my now wife's dismay.
The technical bits: 1. Collaboration faster than Google Docs Most collaborative editors wait for server round-trips. We don't. Drag events broadcast client-to-client via Ably at ~30fps (33ms throttle). You see tables move during the drag. Server broadcasts confirm final position but never block the UI. The trick is a hybrid optimistic model with version-based reconciliation: - Each element has _version, _versionNonce, _updated - Higher version wins - Same version? Lower nonce wins (deterministic tie-breaker) - Currently-dragged element always wins locally This means two people can drag the same table simultaneously and the system resolves it without conflicts or last-write-wins chaos. The reconciliation code is ~100 lines. We also skip broadcasts entirely when you're the only one in the session (solo optimisation) and compress large scenes with gzip via pako to stay under Ably's 65KB limit. 200-guest weddings generate ~50KB of scene data. 2. Custom touch and drag system from scratch Started with react-beautiful-dnd. Ripped it out. The problem: it's designed for lists, not infinite canvas with zoom. Built our own on native pointer events + requestAnimationFrame: * Direct DOM updates during drag: We bypass React reconciliation entirely—write to element.style.transform directly via RAF. React only sees the final position on drop. * Touch hierarchy: Canvas captures two-finger gestures (pan), tables capture single-finger (drag). No conflicts. * Zoom-adjusted coordinates: Divide delta by zoom level. Sounds obvious, took embarrassingly long to get right. * Haptic feedback: navigator.vibrate(50) on drag start. Small thing, feels native. Result: 60fps on iPad (our biggest use case). The gesture detection alone is ~250 lines across useTouchGestures, useTableDragPWA, and useCanvasPan.
3. Version fields that don't pollute the database In-memory versioning with underscore-prefixed fields (_version, _versionNonce, _updated). stripVersionFields() removes them before persistence. No schema changes, no migrations, no cleanup jobs. Stack: Next.js 15 (App Router), React 19, Ably, Prisma + Postgres, Stripe, AWS Amplify. Pricing: Free to try (no signup), £8 one-time to save, £25/month for event managers. Traction: 500+ paying customers in first few weeks, organic only/ Honest limitations: Mobile web is functional but not great.
Happy to go deeper on the WebSocket architecture, touch gesture hierarchy, or the finer points of wedding seating diplomacy.