The Question
FE DesignDesign a Collaborative Vector Graphics Editor
Design the frontend architecture for a real-time collaborative design tool similar to Figma. Your design must address the high-performance rendering requirements of an infinite canvas containing thousands of objects, the state management strategy for conflict-free multi-user editing, and the synchronization logic between local and remote clients. Focus on the trade-offs between DOM and Canvas-based rendering, the implementation of the Command pattern for undo/redo, and how to maintain 60fps performance during complex geometric interactions while ensuring accessibility and data consistency.
React
Canvas API
WebGL
WebAssembly
CRDT
WebSockets
IndexedDB
TypeScript
Command Pattern
Questions & Insights
Clarifying Questions
What is the primary target for the MVP rendering engine?
Assumption: We will use a hybrid approach. The UI (layers, properties) uses standard DOM/React, but the design canvas uses
<canvas> with a 2D/WebGL context for 60fps performance with thousands of objects.How many concurrent collaborators should the MVP support per file?
Assumption: Up to 20 concurrent users with real-time cursor presence and conflict-free editing.
What level of offline support is required?
Assumption: "Read-only" offline access for the MVP, with "Reconnect and Sync" logic for transient network interruptions.
What are the core design primitives for the MVP?
Assumption: Vector shapes (rectangles, circles), text, frames, and basic pen tool paths.
Crash Strategy
The Engine Bottleneck: The DOM cannot handle thousands of complex vector nodes with high-frequency updates (zooming/panning). We must offload the viewport to a Canvas/WebGL-based rendering pipeline.
Consistency & Concurrency: How do we prevent users from overwriting each other? We will implement a Command Pattern combined with CRDTs (Conflict-free Replicated Data Types) to ensure eventual consistency without a central locking authority.
State Management: We need to separate "UI State" (panel toggles) from "Document State" (the scene graph). The scene graph must be high-performance and accessible by the rendering engine.
Elite Bonus Points
WASM Acceleration: Offloading heavy geometric calculations (path booleans, SVG exports) to a Rust-based WebAssembly module.
Layer Virtualization: Only rendering the "visible" nodes in the Layer Tree sidebar using windowing to handle files with 10k+ layers.
Multi-player Cursor Interpolation: Using linear interpolation (Lerp) and dead reckoning to make remote cursor movements feel fluid despite network jitter.
Design Breakdown
Requirements
Functional Requirements:
Infinite canvas with zoom and pan.
Create, move, and style vector primitives.
Layer Tree management (nesting, reordering).
Real-time collaborative editing and presence (cursors).
Undo/Redo functionality.
Non-Functional Requirements:
Performance: 60fps for all canvas interactions (panning, dragging).
Optimistic UI: Local changes must reflect instantly (<16ms).
Reliability: Document state must persist to the cloud and local storage.
Scalability: Support for complex files with 5,000+ objects.
Design Summary
Concise Summary: A collaborative vector editor using a high-performance Canvas rendering engine for the viewport and a CRDT-backed state management system to handle multi-user synchronization.
Major Components:
Canvas Renderer: Custom WebGL/2D engine responsible for painting the scene graph and handling low-level input events (zoom/drag).
CRDT Document Store: A specialized state tree that tracks document nodes and resolves conflicts automatically across clients.
Presence Manager: Handles ephemeral data like cursor positions and active selections via WebSockets.
Command Executor: Manages the execution and history (Undo/Redo) of all document mutations.
CUJ Walkthrough:
User Edits Shape: Input captured by Canvas -> Command Executor creates a "Move" operation -> Local CRDT updates -> Renderer repaints -> Op sent via WebSocket -> Remote clients update.
Simplicity Audit: This architecture avoids complex DOM-reconciliation for the design area, which is the #1 failure point in web-based editors.
Architecture Decision Rationale:
Canvas is chosen over SVG/DOM because it provides predictable performance regardless of element count.
CRDTs are chosen over OT (Operational Transformation) to simplify the backend requirements for the MVP, allowing for a more robust peer-to-peer-like sync logic.
System Diagram
Architecture Deep Dive
Presentation Layer
Component Hierarchy: The
Outter App Shell manages global auth and file routing. The Editor Layout uses a grid/flex system to house the Canvas Viewport (center), Layer Sidebar (left), and Property Panel (right).Interaction Layer:
Input Handler captures raw mouse/touch events. It translates screen coordinates to "world coordinates" based on the current zoom/pan transform. It implements a Finite State Machine (FSM) to handle complex drags (e.g., dragging a handle vs. dragging the object).Rendering Layer: We use a
Hybrid Rendering strategy. The Canvas uses a RequestAnimationFrame loop. To optimize, we only re-render the "dirty" rects or use a "dirty flag" on the Scene Graph. Heavy UI like the Layer Sidebar uses React.memo and windowing to prevent unnecessary DOM churn.UI Frameworks / Tools: React for the UI panels, Tailwind CSS for styling, and a custom WebGL or Canvas-2D wrapper for the graphics.
Application Layer
Data Fetching Layer: Initial document state is fetched via REST/GraphQL. Subsequent updates are "pushed" via
M[WebSocket Client].State Management Layer: We split state. Global UI State (which panel is open) lives in a standard store. Document State lives in the
J[CRDT Document Store]. This store is a tree of nodes where every node has a unique ID.Routing & Navigation: URL-based routing (e.g.,
/file/:fileId) drives the Asset Loader to pull the correct document from the Infrastructure Layer.Domain Layer
Business Rules: The
L[Geometry Engine] handles math: "Does this point intersect this rotated rectangle?" or "What are the bounds of these three shapes?". This is decoupled from the UI.Entities / Models: The
K[Scene Graph Model] is a tree structure. Each node (Frame, Group, Rect) is an immutable record.Inter-layer Contracts: The
Command Executor acts as the bridge, translating UI intents ("Move this") into Domain mutations ("Update Property X on Node Y").Infrastructure Layer
API / Network: WebSockets are the backbone for real-time. We use a message protocol (Protobuf or JSON) to send operation deltas.
Storage:
N[IndexedDB] acts as a write-ahead log or local cache, ensuring that if the browser refreshes, the user doesn't lose the last few seconds of unsynced work.Wrap Up
Wrap-up
Trade-offs: Choosing Canvas means we lose built-in browser accessibility (Alt-text, DOM inspection) for the canvas content. We must implement a "Virtual Hidden DOM" to expose the tree to Screen Readers.
Optimization: For the MVP, we use
Canvas2D. As the product grows, we would migrate to WebGL or WebGPU for better shader support and GPU-accelerated effects like blurs and shadows.Security: Since we run user-generated content (SVG/Images), we use strict Content Security Policies (CSP) and sanitize all inputs before rendering them to the canvas.