Skip to content

singhhe/Notepad-Online

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Notepad Online — Collaborative Code Editor

A full-stack, real-time collaborative code editor built with:

Layer Technology
Frontend React 18 + Vite
Editor Monaco Editor (VS Code's engine)
Real-time CRDT Yjs
WebSocket server Hocuspocus
REST API Node.js + Express
Database PostgreSQL
Auth JWT (bcrypt + jsonwebtoken)

Features

  • Real-time collaboration — multiple users edit the same document simultaneously; all changes merge conflict-free via Yjs CRDTs.
  • Live cursors & selections — see every collaborator's cursor in a unique colour, powered by the Yjs Awareness protocol.
  • Syntax highlighting for 20+ languages (JavaScript, TypeScript, Python, Rust, Go, SQL, …)
  • Team Spaces — organise documents into shared workspaces; invite collaborators by email.
  • Persistent documents — Hocuspocus stores the binary Yjs state in PostgreSQL so documents survive server restarts.
  • Auto-detected language from the file extension (e.g. main.py → Python).
  • Inline title editing — click the document name in the header to rename it instantly.
  • Clean VS Code-inspired dark UI with a resizable sidebar.

Project Structure

notepad-online/
├── backend/
│   ├── src/
│   │   ├── server.js          # Express REST API  (port 3001)
│   │   ├── collaboration.js   # Hocuspocus WS server (port 1234)
│   │   ├── db.js              # PostgreSQL pool
│   │   ├── middleware/
│   │   │   └── auth.js        # JWT middleware
│   │   └── routes/
│   │       ├── auth.js        # POST /api/auth/register|login, GET /me
│   │       ├── spaces.js      # CRUD for Spaces + member management
│   │       └── documents.js   # CRUD for Documents
│   ├── schema.sql             # PostgreSQL schema
│   ├── package.json
│   └── .env.example
├── frontend/
│   ├── src/
│   │   ├── App.jsx
│   │   ├── main.jsx
│   │   ├── index.css          # Global dark theme
│   │   ├── api/
│   │   │   └── client.js      # Axios instance
│   │   ├── contexts/
│   │   │   └── AuthContext.jsx
│   │   └── components/
│   │       ├── Auth/
│   │       │   └── AuthPage.jsx
│   │       ├── Layout/
│   │       │   ├── MainLayout.jsx
│   │       │   └── Sidebar.jsx
│   │       └── Editor/
│   │           └── CollaborativeEditor.jsx  ← the core
│   ├── package.json
│   ├── vite.config.js
│   └── .env.example
├── docker-compose.yml         # PostgreSQL via Docker
└── .gitignore

Quick Start

1 — Prerequisites

  • Node.js 18+ and npm 9+
  • PostgreSQL 14+ (or Docker)

2 — Database

Option A — Docker (recommended)

docker compose up -d

This starts PostgreSQL on localhost:5432 and auto-runs schema.sql.

Option B — Local PostgreSQL

psql -U postgres -c "CREATE DATABASE notepad_online;"
psql -U postgres -d notepad_online -f backend/schema.sql

3 — Backend

cd backend
cp .env.example .env       # edit DB credentials and JWT secret
npm install
npm run dev                # starts both API (3001) and WS (1234) servers

The dev script uses concurrently to run both:

  • http://localhost:3001 — REST API
  • ws://localhost:1234 — Collaboration WebSocket

4 — Frontend

cd frontend
cp .env.example .env       # optional: only if ports differ
npm install
npm run dev

Open http://localhost:5173 in your browser.


How Collaboration Works

Browser A                        Hocuspocus Server              Browser B
─────────                        ─────────────────              ─────────
Y.Doc ──── HocuspocusProvider ──► onAuthenticate (JWT)
                                 ─► Database.fetch()  (load from PG)
                                      │
                                      ▼
              ◄──────────── Yjs binary state ────────────────►
             MonacoBinding                              MonacoBinding
             (Monaco ↔ Y.Text)                         (Monaco ↔ Y.Text)

User A types → Yjs encodes the change as an "update"
             → Update is broadcast to all connected clients
             → Browser B's Y.Doc applies the update
             → MonacoBinding reflects the change in Monaco
             → Browser B sees Browser A's text instantly

On disconnect → Hocuspocus calls Database.store()
             → Full Y.Doc state is saved to PostgreSQL as BYTEA
             → Next open: Database.fetch() restores the state

Remote Cursors

The Yjs Awareness protocol carries each user's cursor position and colour. y-monaco's MonacoBinding automatically renders coloured cursor lines and selection highlights for every connected collaborator.


API Reference

Auth

Method Path Body Description
POST /api/auth/register {username, email, password} Create account
POST /api/auth/login {email, password} Login → JWT
GET /api/auth/me — (Bearer token) Current user

Spaces

Method Path Description
GET /api/spaces List user's spaces
POST /api/spaces Create space
DELETE /api/spaces/:id Delete space (owner only)
POST /api/spaces/:id/members Invite user by email
GET /api/spaces/:id/members List members

Documents

Method Path Description
GET /api/documents/spaces/:spaceId List documents in space
POST /api/documents/spaces/:spaceId Create document
GET /api/documents/:id Get document metadata
PATCH /api/documents/:id Update title / language
DELETE /api/documents/:id Delete document

Environment Variables

Backend (backend/.env)

Variable Default Description
DB_HOST localhost PostgreSQL host
DB_PORT 5432 PostgreSQL port
DB_NAME notepad_online Database name
DB_USER postgres Database user
DB_PASSWORD postgres Database password
JWT_SECRET (required) Secret for signing JWTs
API_PORT 3001 REST API port
COLLAB_PORT 1234 WebSocket server port
FRONTEND_URL http://localhost:5173 Allowed CORS origin

Frontend (frontend/.env)

Variable Default Description
VITE_API_URL /api (proxied) REST API base URL
VITE_COLLAB_URL ws://localhost:1234 Hocuspocus WS URL

Key Dependencies Explained

Package Why
@hocuspocus/server WebSocket server that implements the Hocuspocus protocol for Yjs
@hocuspocus/extension-database Persistence plugin — fetch/store binary Yjs state from any DB
@hocuspocus/provider Client-side WebSocket connector for Yjs
yjs The CRDT library powering conflict-free merging of concurrent edits
y-monaco Binds a Y.Text CRDT to a Monaco editor model + renders awareness cursors
@monaco-editor/react React wrapper for Monaco Editor (the engine behind VS Code)

Production Checklist

  • Change JWT_SECRET to a strong random string (openssl rand -hex 64)
  • Use HTTPS/WSS — wrap both servers behind nginx with TLS
  • Set FRONTEND_URL to your production domain in backend .env
  • Use a managed PostgreSQL service (AWS RDS, Supabase, Neon, …)
  • Run Node.js processes with a process manager (PM2, systemd)
  • Consider rate-limiting the auth endpoints to prevent brute-force

Roadmap / Advanced Features

  • Version history (Yjs UndoManager or snapshot table)
  • Document chat sidebar
  • Granular roles (viewer/editor/owner) enforced in the editor
  • Export as .txt, .md, or .pdf
  • AI code suggestions via Claude API
  • File tree with folders within a space

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors