A real-time collaborative document editor built with modern web technologies, featuring CRDT-based conflict-free editing, Git-based version control, and WebSocket-powered live collaboration.
- Real-time Collaboration: Multiple users can edit documents simultaneously with live cursor tracking
- CRDT-based Editing: Conflict-free replicated data types (Y.js) ensure consistency across all clients
- Git Version Control: Each document has its own Git repository for complete version history
- Role-based Permissions: Owner, Writer, and Reader roles with proper access control
- Document Sharing: Share documents with other users and assign roles
- History & Rollback: View document history and rollback to any previous version
- Rich Text Editing: Full-featured WYSIWYG editor with formatting options
- Dark Mode UI: Modern dark theme interface
Frontend:
- Pure HTML/CSS/JavaScript (no framework)
- Tiptap rich text editor
- Y.js for CRDT synchronization
- Socket.io client for real-time communication
- Vite for bundling and development
Backend:
- Node.js with Express
- Socket.io for WebSocket communication
- Y-Socket.io for CRDT synchronization
- SQLite for user and document metadata
- Simple-git for Git operations
document_storage/
├── doc_1/
│ ├── .git/ # Git repository for document 1
│ └── document.md # Document content
├── doc_2/
│ ├── .git/ # Git repository for document 2
│ └── document.md # Document content
└── ...
Each document has its own isolated Git repository, allowing for true history rollback without affecting other documents.
- Node.js (v18 or higher)
- npm or bun
- Clone the repository:
git clone <repository-url>
cd sync-docs- Install dependencies:
npm install
# or
bun install- Initialize the database:
node setup_db.js- Start the development servers:
# Start both frontend and backend
npm run both
# Or start separately:
npm run dev:be # Backend server (port 3000)
npm run dev:fe # Frontend dev server (port 5173)- Open the application in your browser (default: http://localhost:5173)
- Enter a username and password
- Click "Register" to create an account
- You'll be automatically logged in
- After logging in, enter a document name in the "New Document Name" field
- Click "Create"
- The document will appear in your document list
- Click "Open" to start editing
- Open a document you own
- Click the "Share" button
- Enter the username of the person you want to share with
- Select their role:
- Owner: Full control, can delete and share
- Writer: Can edit and save
- Reader: Read-only access
- Click "Share"
- Open a document
- Click the "History" button
- View all commits for the document
- Click "Rollback to this version" on any commit
- Confirm the rollback (this action cannot be undone)
- The document will be reset to that version, and all subsequent commits will be removed
- Use the toolbar buttons for formatting (bold, italic, headings, lists, etc.)
- Changes are automatically saved every 60 seconds
- Click "Save" to manually save immediately
- Multiple users can edit simultaneously - you'll see their cursors in real-time
POST /api/register- Create a new user accountPOST /api/login- Login and get user session
GET /api/documents?userId={id}- List all documents for a userPOST /api/documents- Create a new documentDELETE /api/documents/:id- Delete a document (owner only)GET /api/documents/:id/content?userId={id}- Get document content and user rolePOST /api/documents/:id/save- Save document contentGET /api/documents/:id/history- Get document commit historyPOST /api/documents/:id/rollback- Rollback document to a specific commitPOST /api/documents/:id/share- Share document with another user
id- Primary keyusername- Unique usernamepassword- Plain text password (for simplicity - use hashing in production)
id- Primary keyname- Document namepath- Virtual path (currently '/')fs_path- Filename in storage ('document.md')owner_id- Foreign key to users tablecreated_at- Timestamp
document_id- Foreign key to documentsuser_id- Foreign key to usersrole- 'owner', 'writer', or 'reader'- Primary key: (document_id, user_id)
The application uses Y.js (CRDT) for conflict-free editing:
- Each document has a Y.Doc instance
- Changes are synchronized via Socket.io
- Y-Socket.io handles the WebSocket protocol
- Tiptap Collaboration extension integrates Y.js with the editor
- Collaboration Cursor extension shows other users' cursors
- User opens a document → Frontend creates Y.Doc and connects via Socket.io
- User types → Changes are applied to Y.Doc locally
- Y.js syncs → Changes are broadcast to server via Socket.io
- Server broadcasts → Other connected clients receive updates
- Other clients apply → Changes are merged into their Y.Doc instances
- Editor updates → Tiptap reflects the merged changes
Each document has its own Git repository:
- Initial Commit: Created when document is first created
- Auto-save: Commits are created every 60 seconds or on manual save
- Rollback: Uses
git reset --hardto permanently remove commits after a point - History: Shows all commits for the document (excluding rollback/reset commits)
- Password Hashing: Currently uses plain text passwords - implement bcrypt or similar
- Authentication: Add JWT tokens or session management
- Authorization: Add middleware to verify permissions on all endpoints
- Input Validation: Sanitize all user inputs
- HTTPS: Use HTTPS in production
- Rate Limiting: Add rate limiting to prevent abuse
- SQL Injection: Use parameterized queries (already implemented)
- XSS Protection: Sanitize HTML content before saving
.
├── server.js # Express backend server
├── db.js # Database connection wrapper
├── setup_db.js # Database initialization script
├── package.json # Dependencies and scripts
├── document_storage/ # Document repositories (created at runtime)
├── collaboration-docs.db # SQLite database (created by setup_db.js)
└── src/
├── index.html # Main HTML file
├── main.js # Frontend application logic
└── style.css # Stylesheet
- server.js: Express server, API routes, Socket.io setup, Git operations
- src/main.js: Frontend logic, Tiptap editor setup, Y.js integration
- db.js: SQLite wrapper that mimics PostgreSQL interface
- setup_db.js: Creates database tables
- Check that the database was initialized:
node setup_db.js - Verify user is logged in (check localStorage)
- Check browser console for errors
- Ensure both frontend and backend servers are running
- Check Socket.io connection in browser DevTools Network tab
- Verify Y.js provider is connecting: check console logs
- Ensure document was created with new system (after refactor)
- Check that document has its own Git repo in
document_storage/doc_{id}/ - Verify Git operations in server logs
- Ensure userId is being passed correctly in API calls
- Check database permissions table
- Verify role is 'owner' or 'writer' for write operations
ISC
This is a demo/educational project. Feel free to fork and modify as needed.
- Tiptap - Rich text editor framework
- Y.js - CRDT library
- Socket.io - Real-time communication
- Simple-git - Git operations