The Question
FE DesignCollaborative Design Tool Architecture
Design the frontend architecture for a professional, web-based collaborative design tool similar to Figma. Your solution should specifically address the challenges of rendering thousands of vector objects at 60fps, managing high-frequency state updates in a multi-user environment, and implementing a robust undo/redo system. Discuss your choice of rendering technology, conflict resolution strategy for multiplayer, and how you would maintain a responsive UI during heavy computational tasks.
React
Canvas API
CRDT
Yjs
WebSockets
IndexedDB
Zustand
WebWorker
TypeScript
Questions & Insights
Clarifying Questions
Q1: What is the primary rendering engine target (DOM/SVG vs. Canvas/WebGL)?
Assumption*: To support thousands of layers with high performance (60fps zooming/panning), we will use a HTML5 Canvas/2D Context for the workspace and React/DOM** for the UI panels.
Q2: Is real-time multi-user collaboration a Day 1 requirement?
Assumption*: Yes, "Figma-like" implies multiplayer. We will implement a Conflict-free Replicated Data Type (CRDT**) approach to handle concurrent edits.
Q3: What level of "Vector" support is needed for the MVP?
Assumption: Basic shapes (rects, circles), text, and simple paths. Advanced boolean operations and complex pen tools are post-MVP.
Q4: How should we handle large files that exceed browser memory?
Assumption: MVP will focus on a "one file at a time" model with a 500MB memory limit, using binary serialization for snapshots.
Crash Strategy
Core Bottleneck: High-frequency updates (mouse moves/drags) causing UI lag and state synchronization overhead.
Strategy:
Decouple the Viewport from React: Use a specialized Rendering Loop for the canvas to avoid React's reconciliation overhead for every pixel moved.
Atomic State Updates: Use a centralized store with a CRDT library (like Yjs) to handle document state and presence.
Spatial Indexing: Implement a Bounding Volume Hierarchy (BVH) or R-Tree to optimize hit-testing and rendering of only visible elements.
Command Pattern: Encapsulate every user action (move, resize, color change) as a Command to facilitate robust Undo/Redo and sync.
Elite Bonus Points
Offscreen Canvas: Move heavy rendering logic to a Web Worker to keep the main thread responsive for UI interactions.
WASM for Geometry: Use Rust/C++ compiled to WebAssembly for heavy mathematical operations like path boolean operations or SVG parsing.
Binary Protocols: Use Protocol Buffers over WebSockets to reduce the payload size of real-time sync messages.
Design Breakdown
Requirements
Functional Requirements:
Infinite Canvas with zoom and pan.
Create, select, move, and style basic shapes (Rectangle, Ellipse, Text).
Layers Panel for hierarchy management.
Properties Panel for styling (Fill, Stroke, Opacity).
Real-time multiplayer presence (cursors) and state sync.
Non-Functional Requirements:
Performance: Render loop at ~60fps; Interaction latency < 100ms.
Scalability: Support up to 5,000 objects per page without significant degradation.
Responsiveness: UI must remain fluid while the canvas is rendering heavy scenes.
Persistence: Auto-save to cloud and local caching for crash recovery.
Design Summary
Concise Summary: A hybrid architecture utilizing React for the structured UI and a specialized Canvas Engine for the design workspace, synchronized via a CRDT-based state layer for real-time collaboration.
Major Components:
Canvas Engine: A custom 2D renderer responsible for drawing shapes, handling zoom/pan, and high-frequency input events.
Document Store: A CRDT-powered state manager that ensures all collaborators converge on the same document state.
Presence Manager: Handles ephemeral data like peer cursor positions and selection highlights.
UI Shell: React-based components for the Toolbar, Layer Tree, and Property Inspector.
CUJ Walkthrough:
User draws a rectangle: Input is captured by the Canvas Engine -> Command is dispatched to the Document Store -> Store updates CRDT -> Canvas re-renders local state -> Change is broadcasted via WebSockets to peers.
Simplicity Audit: By using a single
<canvas> for the viewport, we avoid the overhead of thousands of DOM nodes. By using Yjs, we delegate the complex math of conflict resolution to a proven library.Architecture Decision Rationale:
Why this architecture?: React is excellent for forms (Property Panel) and trees (Layer Panel), but terrible for high-frequency 2D graphics. Decoupling the two ensures "The Figma Feel."
Requirement Satisfaction: Canvas ensures performance; CRDT ensures multiplayer; React ensures a robust, accessible UI.
System Diagram
Architecture Deep Dive
Presentation Layer
Component Hierarchy: The
App Shell provides the frame. The Main Layout uses a 3-column grid. The Viewport is the star, hosting a high-performance <canvas> element that fills the center.Interaction Layer:
Canvas Engine: Uses a "Draw Loop" (requestAnimationFrame). It calculates the transformation matrix (zoom/pan) to map screen coordinates to world coordinates.
Input Handling: Captures
PointerEvents. Distinguishes between clicks (selection), drags (move/resize), and scrolls (pan/zoom).Rendering Layer:
Dirty Rectangles: Only re-render the portions of the canvas that changed to save GPU/CPU cycles.
Virtualization: The
Layer Tree in the sidebar is virtualized (e.g., react-window) to handle thousands of layers.UI Frameworks: React for the UI; Tailwind for styling; Radix UI for accessible primitives (menus, dialogs).
Application Layer
Data Fetching Layer: Load initial document state via REST/JSON. Subsequent updates are incremental binary blobs (CRDT updates) over WebSockets.
State Management Layer:
Zustand + Yjs: Use Zustand for UI state (which panel is open) and Yjs for the shared document state.
Persistence: Every change is written to
IndexedDB locally first to ensure no data loss if the tab crashes.Routing: Minimal for MVP; mostly used for
/[project_id].Domain Layer
Business Rules:
Geometry Engine: Logic for "Snap to Grid," "Smart Guides," and bounding box calculations.
Command Pattern: Actions like
MoveCommand, ResizeCommand, ColorChangeCommand allow for easy Undo/Redo by storing inverse operations.Entities:
Document: Root container.Node: Abstract base for Rectangle, Text, Group.Style: Value object containing Fill, Stroke, etc.Infrastructure Layer
API / Network: WebSockets for low-latency sync. If the socket drops, the client buffers changes and reconciles upon reconnection using the CRDT's vector clock.
Storage:
IndexedDB acts as a write-ahead log (WAL) for document changes.Wrap Up
Wrap-up
Evaluation: This design hits the "sweet spot" of performance (Canvas) and developer velocity (React).
Trade-offs: Using Canvas makes accessibility harder; we must implement an "Aria-Live" region or a hidden DOM tree that mirrors the canvas structure for screen readers.
Future Scale: As the file grows, we would move the
Canvas Engine to WebGL for GPU-accelerated rendering and use "Tiling" (rendering the canvas in chunks) to handle massive artboards.