Live Cursors Around the World
When multiple people edit the same route in Plot Along, you can see their cursors moving across the map in real time. Each collaborator gets a unique color, and their name follows their cursor as they pan, zoom, and place waypoints.
The Architecture
Live cursors run on Cloudflare Durable Objects. Each map gets its own Durable Object instance that acts as a WebSocket hub. When a user opens a map, their browser connects to the map’s Durable Object via WebSocket and starts broadcasting cursor positions at a throttled rate.
The Durable Object maintains the room state: who’s connected, their cursor positions, and which waypoints they’re actively editing. When a user moves their mouse, the position is broadcast to all other connected clients. The Durable Object handles join/leave events, presence tracking, and message routing.
Cursor Colors
Each collaborator is assigned a color from a pool of 10 distinct values. The color is derived from a hash of the user’s ID, so the same person always gets the same color regardless of join order. The colors are defined as CSS custom properties, making them part of the app’s design system.
Rendering
Cursors are rendered as SVG overlays on top of the Mapbox GL canvas. Each cursor is a simple polygon arrow with a name label positioned below it. The cursor positions are stored in geographic coordinates (longitude/latitude), so they stay anchored to the correct spot on the map as other users pan and zoom independently.
The presence bar at the top of the editor shows colored avatar circles for everyone in the room. Hovering over an avatar reveals the collaborator’s name. When someone disconnects, their cursor and avatar disappear within a few seconds.
Waypoint Interaction Indicators
Beyond cursors, the system also shows when a collaborator is actively editing a waypoint. A pulsing ring appears around the waypoint marker they’re interacting with, colored to match their cursor. This prevents two people from trying to edit the same waypoint simultaneously and gives everyone spatial awareness of where work is happening.
What We Learned
The biggest challenge was performance. Broadcasting every mousemove event to every connected client would overwhelm the WebSocket connection on busy maps. We throttle cursor updates and use the Durable Object’s in-memory state to batch messages. On the client side, cursor positions are interpolated between updates so movement appears smooth even at the reduced update rate.