Nodepad is a collaborative text editor built on a Hybrid Peer-to-Peer architecture using Y.js. It leverages both WebRTC and WebSockets to ensure real-time synchronization is fast, efficient, and reliable across any network.
- Y.js – CRDT-based shared document model
- y-webrtc – WebRTC-based peer-to-peer provider for y.js
- y-indexeddb - Database adapter for offline persistence (see the persistence guide)
- y-websocket - WebSocket provider for server-relayed syncing and persistence.
- Tiptap – Headless, framework-agnostic rich-text editor built on ProseMirror
- React – Component-based UI library
- Vite – Fast development bundler and dev server
- Node.js – JavaScript runtime
- Node.js (LTS recommended)
- npm or yarn
- Modern browser with WebRTC support
Nodepad uses Y.js for conflict-free collaborative editing. To maximize reliability, the application employs a Hybrid Sync Strategy:
-
Peer-to-Peer (Primary): Clients attempt to connect directly via y-webrtc. This offloads traffic from the server and offers low-latency syncing on local networks.
-
Client-Server (Fallback & Persistence): All clients also connect to a central Node.js server via y-websocket. This ensures that users behind restrictive firewalls (Symmetric NAT) can still collaborate and serves as the central storage for document history.
The server acts as both a Signaling Server (introducing peers for WebRTC) and a Sync Server (relaying data when P2P fails).
- Hybrid Synchronization: Seamlessly merges updates from P2P and WebSocket sources.
- Resilient Connectivity: Works even if P2P connections are blocked by corporate/university firewalls.
- Real-time Collaboration: Multiple users can edit the same document simultaneously.
- Offline Support: Changes are saved locally using IndexedDB and synced when the connection is restored.
This installs all dependencies needed.
npm install
# or
yarn installStart the hybrid signaling and sync server.
npm run server
# or
yarn serverBy default, the server runs on port 4444.
Create a .env file in the project root to configure the connection domain.
VITE_SIGNALING_SERVER_DOMAIN=wss://<domain>If you for example use a signaling server on your current device on port 4444 - which is default when using npm run server - you add:
VITE_SIGNALING_SERVER_DOMAIN=ws://localhost:4444Since we use Vite, the domain is finally loaded from the .env file in collabRoom.ts using const domain = import.meta.env.VITE_SIGNALING_SERVER_DOMAIN;
Start the frontend development server.
npm run dev
# or
yarn devThen open the website (default:http://localhost:5173).
-
Visible shared cursors
-
Editor Toolbar (Bold, Italic, Underline)
-
Improved UI with Tiptap
-
Client awareness list (Who is online)
-
Document Export
Contributions are not allowed since this is a graded project for the seminar "New Trends for Local and Global Interconnects for P2P Applications" by Professor Christian Tschudin at University of Basel.
Nodepad is licensed under the MIT License.