Awareness & Presence Design Document
1. Overview
This document describes the design of Awareness & Presence in a real-time collaborative editor. Awareness & Presence answers four fundamental user questions with minimal cognitive load:- Who is currently in the room?
- Where are they in the document?
- What are they doing (roughly)?
- Will it affect me?
2 (PRESENCE_PROTOCOL_VERSION in @softmaple/awareness).
2. Design Principles
2.1 Low Interruption by Default
- Awareness information should be visible but ignorable
- No blocking modals, no toast spam
- Strong signals only appear on hover, focus, or potential conflict
2.2 Approximation Over Precision
- Presence is probabilistic, not authoritative
- “Someone is editing here” is sufficient
- Exact keystrokes or real-time character updates are unnecessary
2.3 Layered Awareness
Information is presented in layers from coarse to fine:3. Non-Goals
The following are explicitly out of scope for the first iteration:- Chat or messaging
- Audio / video presence
- Detailed activity logs
- Real-time keystroke mirroring
- Conflict resolution UI (handled at data layer)
4. Presence Model
4.1 Session Identity
connectionId. The same userId may appear as
multiple sessions (multiple tabs). UI may aggregate by userId later.
4.2 Status Rules (derived)
Status is never set by heartbeats. It is derived:
Heartbeat may only update
lastSeenAt. Cursor / selection / typing /
markUserActivity update lastActivityAt (and usually lastSeenAt).
patchPresenceUser never implicitly bumps timestamps.
4.3 Clocked Updates
Ephemeral presence is a per-connection versioned register:incoming.clock > known.clock overwrites state. Stale frames may still
refresh lastSeenAt.
4.4 Cursor Positions
5. Transport Readiness
WebSocketconnect() resolves only when presence is ready, not merely
when the socket opens:
6. UI Components
6.1 Document roster and presence primitives
CollaborationBar is the document-level composition used by the web editor.
Its compact row names the context, distinguishes presence connection from the
header’s document-save state, and opens an inline roster. The expanded panel
shows one person per account, live session counts, “You”, and plain activity
labels. Self stays first, then names stay in alphabetical order while people
type. Offline sessions do not contribute to the count, and connection loss
hides the cached roster until presence is ready again.
The cursor visibility checkbox changes the local overlay only. It never stops
publishing the local selection or changes document editing permissions. The
panel uses one button in the tab order; Enter/Space toggle it and Escape inside
the panel closes it and returns focus. On small screens, the roster becomes a
single column. A scrollable roster bounds the height in crowded rooms.
The web editor uses PresenceLayer, LiveCursor, and SelectionHighlight with
its measured Lexical geometry. Cursor labels fade, carets match measured line
heights, and resizing the editor refreshes positions. Neutral name tags and
soft avatar tints retain readable text for pale participant colors; names
remain the primary identity when palette colors repeat.
Storybook review captures (the document prose is a preview fixture):


6.2 Presence Bar (Global Awareness)
PurposeShows who is currently in the room. Behavior
- Displays up to N avatars
- Overflow shown as
+X - Tooltip reveals name and status
- Sorted by recent activity (
lastActivityAt)
6.3 Live Cursor (Local Awareness)
PurposeIndicates where another user is editing. Behavior
- Colored caret
- Username label appears on movement
- Label fades out after 2-3 seconds
- Cursor movement is interpolated (no jitter)
6.4 Selection Highlight (Block Awareness)
PurposeShows which block or range is being edited by others.
6.5 Activity Indicator (Action Awareness)
PurposeCommunicates recent activity without distraction.
7. Performance Considerations
- Network cursor updates coalesced at 50ms (~20 updates/s/user)
- Local rendering may still run at 60fps independently
- When WebSocket
bufferedAmountis high, stale cursor frames are dropped (latest-value-wins) - Off-screen cursors not rendered
- Presence is eventually consistent
8. Accessibility
- Non-blocking indicators
- Screen reader friendly
- Color is never the sole signal
9. Architecture
packages/awareness/src/core/.
10. Success Criteria
- Users feel confident editing together
- Idle is reachable while heartbeats continue
- Multi-tab same account does not self-suppress
- Minimal performance impact under multi-user cursor load
11. Summary
Awareness & Presence should create calm confidence, not excitement.“I know who’s here, and I’m not surprised by their actions.”