Real-Time Collaborative Markdown Editor
Build a Markdown editor for the browser where several people can edit the same document at the same time, like Google Docs. Everyone sees each other's typing and cursors instantly, and simultaneous edits always merge without conflicts, even edits made offline and synced later. This works thanks to Yjs, a CRDT library: a data structure designed so that every copy ends up identical no matter in which order the changes arrive. The editor is CodeMirror inside a React app, with a live preview of the rendered Markdown, and a small Node.js WebSocket server relays changes and saves documents. You'll learn how CRDTs work, real-time sync over WebSockets, presence (who is here and where their cursor is), offline editing, and testing that all copies converge.
- Estimate
- ~14.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
Yjs · React · WebSocket · CodeMirror
Project roadmap
- 01
Build the editor
~2hCreate a React and TypeScript project with Vite. Add CodeMirror 6 with Markdown syntax highlighting, and a live preview next to it that renders Markdown safely (for example with markdown-it, without allowing raw HTML). Documents are opened by URL, such as /doc/meeting-notes. Done when: typing in the editor updates the preview.
- 02
Connect Yjs to the editor
~2hCreate a Y.Doc with a Y.Text for the document, and bind it to CodeMirror with y-codemirror.next, so the editor's text is the shared text. To see the sync working before adding a server, connect two editors on the same page through their update events. Done when: typing in either editor appears in the other.
- 03
Build the WebSocket server
~2.5hBuild a Node.js server (using the y-websocket server utilities or your own implementation with the ws package and y-protocols) that keeps one Y.Doc per document name, relays updates between everyone connected to it, and saves each document to disk or a database (with y-leveldb or by storing encoded updates), loading it again after a restart. Done when: two browsers on the same URL edit together, and the document survives a server restart.
- 04
Show who is editing
~2hUse the Yjs awareness protocol to share each user's name, color and cursor position. Show other people's cursors and selections in the editor with their name, and a list of who is online. Ask for a name on first visit and remember it in localStorage. Done when: each browser shows the others' cursors moving as they type.
- 05
Support offline editing
~2hStore the document in the browser with y-indexeddb, so it opens without a connection and keeps offline edits. Show the connection status. When the connection returns, the provider syncs automatically. Test it: edit the same paragraph in two browsers while both are offline, then reconnect. Done when: offline edits from both browsers merge into the same text after reconnecting.
- 06
Add limits and access
~1.5hLimit the document size and the number of connections per document on the server. Protect documents with a simple shared secret in the link (a random token), refusing WebSocket connections without it. Log connections and saves. Done when: a document can't be opened without its token, and oversized updates are rejected.
- 07
Test convergence
~2.5hWrite a Node.js test that creates several Y.Doc clients connected to your server (on your own machine), applies thousands of random inserts and deletes from all of them at the same time, including clients that disconnect and reconnect, and then checks that every client ends with exactly the same text. Record how many clients and edits per second it handled. Done when: every run ends with identical documents on all clients.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack