y-prosemirror

The official Yjs binding for the ProseMirror rich-text editor, enabling real-time collaboration

Library
npm
v1.3.7
466 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
90 /100 Excellent
Development Activity 92
Maintenance 100
Community 80
Maturity 60
Momentum 28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
81 /100 Excellent
Architecture 88
Code Quality 85
Innovation 87
Learning Curve 62

y-prosemirror is the binding library that connects Yjs — a CRDT (conflict-free replicated data type) framework — to ProseMirror, the extensible rich-text editor toolkit. It provides a ProseMirror plugin (ySyncPlugin) that keeps a ProseMirror document in sync with a shared Yjs document, along with additional plugins for collaborative cursors/awareness and CRDT-aware undo/redo.

Because ProseMirror’s own undo history isn’t CRDT-safe (concurrent edits from multiple users break naive undo stacks), y-prosemirror ships a dedicated yUndoPlugin that understands Yjs’s operation history, making it possible to build Google-Docs-style collaborative editors on top of ProseMirror without hand-rolling conflict resolution.

What You Get

  • ySyncPlugin - keeps the ProseMirror editor state synchronized with a shared Yjs document
  • yCursorPlugin - renders other collaborators’ cursors and selections in real time
  • yUndoPlugin - a CRDT-aware undo/redo manager that correctly handles concurrent multi-user edits
  • Transformers for converting between ProseMirror and Yjs document representations
  • Works with any Yjs-compatible network provider (WebRTC, WebSocket, y-websocket, etc.) for the actual transport

Common Use Cases

  • Building real-time collaborative document editors (Notion/Google Docs-style) on top of ProseMirror
  • Adding live multi-cursor presence and selection highlighting to a shared rich-text document
  • Offline-first collaborative editing where edits made offline merge conflict-free once reconnected
  • Powering collaboration features in higher-level editors built on ProseMirror, such as Tiptap or BlockNote

Under The Hood

Architecture: The library is organized as a set of independent ProseMirror plugins (sync-plugin.js, cursor-plugin.js, undo-plugin.js) that each subscribe to Yjs document update events and translate them into ProseMirror transactions, and conversely intercept ProseMirror transactions to apply them onto the shared Yjs type. A transformers/ directory handles the bidirectional mapping between ProseMirror’s node/mark tree and Yjs’s XmlFragment/XmlElement CRDT types, which is the core technical challenge the library solves.

Tech Stack: Plain modern JavaScript (ES modules, type: module), built with Rollup and type-checked via TypeScript’s tsc against hand-written .d.ts declarations rather than being authored in TypeScript directly; depends on yjs and prosemirror-* packages as peers.

Code Quality: The tests/ directory includes dedicated suites for complex scenarios — overlapping marks, attributed nodes, delta conversion, and cursor behavior — reflecting the genuinely hard edge cases in reconciling two independent document models. An ARCHITECTURE.md and CAVEATS.md document known limitations and design decisions explicitly, which is unusually transparent for a library of this size.

API Design: Usage requires wiring several plugins into a ProseMirror EditorState (ySyncPlugin(yXmlFragment), yCursorPlugin(awareness), yUndoPlugin()), plus understanding both ProseMirror’s and Yjs’s own concepts — a real learning curve, though the maintained demo apps (blocknote-demo, tiptap-demo) provide working reference integrations that shortcut a lot of that ramp-up.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers