Text Editors

Designing collaborative rich text editors with Y.Text.

Document Structure

Document
├── content: Y.Text             (main document)
├── metadata: Map<key, value>   (title, created, etc.)
└── comments: Map<commentId, Comment>

Use Y.Text for the main content. Editor bindings (y-quill, y-prosemirror, y-tiptap) handle synchronization automatically.

Comments with Relative Positions

Comments reference text ranges that must survive edits. Use Y.RelativePosition:

interface Comment {
  id: string
  text: string
  startPosition: Y.RelativePosition  // Survives text changes
  endPosition: Y.RelativePosition
}

Convert between absolute and relative positions when creating/reading comments. Relative positions stay valid even when text is inserted or deleted around them.

Common Mistakes

Storing HTML as plain text:

// WRONG - loses semantic structure
yText.insert(0, '<p><strong>Hello</strong></p>')

// CORRECT - use formatting attributes
yText.insert(0, 'Hello', { bold: true })

Absolute positions for persistent references:

// WRONG: position 42 becomes invalid when text changes
const savedPosition = 42

// CORRECT: relative position adapts to edits
const relPos = Y.createRelativePositionFromTypeIndex(yText, 42)

See Also