From 829287ae8f93f2ac894942d4195e72af6d7c3d9c Mon Sep 17 00:00:00 2001
From: sinansrk
Date: Mon, 9 Feb 2026 11:13:39 +0530
Subject: [PATCH 01/57] readme
---
README.md | 91 +++++++++++++++++++++++++++++++------------------------
1 file changed, 52 insertions(+), 39 deletions(-)
diff --git a/README.md b/README.md
index d4d04bd..4c50eef 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,30 @@
-# Blogify π
+# OG Docs π
-**A modern, collaborative blogging platform built for speed, security, and developer-centric content control.**
+**A modern, real-time collaborative documentation platform built for speed, security, and developer-centric content control.**
## About The Project
-**Blogify** is a full-stack web application designed to streamline the way developers write and share articles. The project focuses on structured content delivery, moving away from standard plain-text storage to a robust, custom-tailored data architecture.
+**OG Docs** is a full-stack web application designed to streamline the way teams and developers write, edit, and share documentation together. The platform emphasizes structured content delivery and real-time collaboration, moving beyond traditional plain-text storage toward a robust, custom-tailored data architecture.
-Built as a high-performance **MERN** application, Blogify provides a seamless writing experience while giving authors granular control over their content's metadata and presentation.
+Built as a high-performance **MERN** application, OG Docs enables multiple collaborators to work simultaneously in a shared workspace, with changes reflected instantly for everyoneβensuring smooth, efficient, and transparent collaboration.
---
## π Key Features
-* **Custom Slate.js Engine:** Uses a custom-built implementation to structure content into JSON format, ensuring consistent styling and portability.
+* **Real-Time Collaborative Workspace:** A dedicated editing area where multiple collaborators can make changes simultaneously, with updates reflected in real time.
+* **Custom Slate.js Engine:** A custom-built implementation that structures content into JSON format for consistent styling and long-term portability.
* **Modern UI/UX:** A clean, responsive interface built with **React 19**, **Tailwind CSS 4.0**, and **CoreUI** components.
-* **Secure Authentication:** Integrated **Google OAuth** for quick and secure user access.
+* **Secure Authentication:** Integrated **Google OAuth** for fast and secure user access.
* **Developer-Friendly Build:** Optimized with **Vite** for near-instant hot module replacement (HMR).
-* **Robust Security:** Hardened backend using **Helmet**, **HPP**, **Rate Limiting**, and **Zod** for schema validation.
+* **Robust Security:** Hardened backend using **Helmet**, **HPP**, **Rate Limiting**, and **Zod** for strict schema validation.
---
## π The Tech Stack
### Frontend
+
* **Library:** React 19
* **Styling:** Tailwind CSS 4.0 & CoreUI
* **Editor:** Slate.js (Custom JSON Content Engine)
@@ -30,12 +32,14 @@ Built as a high-performance **MERN** application, Blogify provides a seamless wr
* **Build Tool:** Vite
### Backend
+
* **Runtime:** Node.js
* **Framework:** Express.js (v5)
* **Authentication:** JWT & Google Auth Library
* **Validation:** Zod
### Database
+
* **Database:** MongoDB
* **ODM:** Mongoose
@@ -43,51 +47,56 @@ Built as a high-performance **MERN** application, Blogify provides a seamless wr
## βοΈ How It Works
-The core logic of Blogify revolves around a structured data pipeline:
-
-1. **The Input:** Authors use a custom editor powered by **Slate.js**. Instead of generating messy HTML, it outputs a clean **JSON tree** representing the document structure.
-2. **The Storage:** This JSON object is validated via **Zod** and stored in **MongoDB** through **Mongoose** models.
-3. **The Rendering:** On the frontend, our custom engine traverses the JSON tree and dynamically "paints" the content using Tailwind-styled React components.
-
+The core logic of OG Docs revolves around a structured, collaborative data pipeline:
+1. **The Input:** Contributors write using a custom editor powered by **Slate.js**. Instead of generating raw HTML, the editor produces a clean **JSON tree** representing the document structure.
+2. **The Collaboration Layer:** Multiple users can edit the same document simultaneously, with real-time updates synchronized across all active sessions.
+3. **The Storage:** The JSON structure is validated using **Zod** and securely stored in **MongoDB** via **Mongoose** models.
+4. **The Rendering:** On the frontend, a custom rendering engine traverses the JSON tree and dynamically paints the content using Tailwind-styled React components.
---
## π¦ Installation & Setup
-Follow these steps to get a copy of Blogify running locally.
+Follow these steps to run OG Docs locally.
### Prerequisites
+
* [Node.js](https://nodejs.org/) (Latest LTS)
-* [MongoDB](https://www.mongodb.com/) account or local instance.
+* [MongoDB](https://www.mongodb.com/) account or local instance
### Steps
-1. **Clone the Repository**
- ```bash
- git clone [https://github.com/shamil-tp/Blogify.git](https://github.com/shamil-tp/Blogify.git)
- cd blogify
- ```
+1. **Clone the Repository**
+
+ ```bash
+ git clone https://github.com/shamil-tp/Blogify.git
+ cd blogify
+ ```
-2. **Setup Backend**
- ```bash
- cd backend
- npm install
- ```
- Create a `.env` file in the `backend` folder and add your `MONGODB_URI`, `JWT_SECRET`, and `PORT`.
+2. **Setup Backend**
-3. **Setup Frontend**
- ```bash
- cd ../frontend
- npm install
- ```
+ ```bash
+ cd backend
+ npm install
+ ```
-4. **Run Development Servers**
- * **Backend:** `npm run test` (uses nodemon)
- * **Frontend:** `npm run dev` (uses vite)
+ Create a `.env` file in the `backend` folder and add your `MONGODB_URI`, `JWT_SECRET`, and `PORT`.
-5. **View the App**
- Open `http://localhost:5173` for the frontend.
+3. **Setup Frontend**
+
+ ```bash
+ cd ../frontend
+ npm install
+ ```
+
+4. **Run Development Servers**
+
+ * **Backend:** `npm run test` (nodemon)
+ * **Frontend:** `npm run dev` (Vite)
+
+5. **View the App**
+ Open `http://localhost:5173` in your browser.
---
@@ -95,6 +104,10 @@ Follow these steps to get a copy of Blogify running locally.
This project was collaboratively designed and developed by:
-* **Shamil** - [GitHub](https://github.com/shamil-tp)
-* **Sinan** - [GitHub](https://github.com/sinanrahman/)
-* **Ranfees** - [GitHub](https://github.com/Ranfees)
\ No newline at end of file
+* **Sinan** β [GitHub](https://github.com/sinanrahman/)
+* **Hana** β [GitHub](https://github.com/Hana-Haris3)
+* **Salih** β [GitHub](https://github.com/salih85)
+
+---
+
+OG Docs is built with collaboration at its coreβdesigned to help teams write, iterate, and ship documentation together, faster and cleaner.
From f73ce734ef665aafb6c321d7010d37453bc74468 Mon Sep 17 00:00:00 2001
From: sinansrk
Date: Mon, 9 Feb 2026 12:50:40 +0530
Subject: [PATCH 02/57] model changed slightly
---
README.md | 166 +++++++++++++++++++++++
backend/models/Blog.js | 55 +++++++-
backend/package-lock.json | 266 +++++++++++++++++++++++++++++++++++++
backend/package.json | 2 +
frontend/package-lock.json | 184 ++++++++++++++++++++++++-
frontend/package.json | 4 +
6 files changed, 674 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 4c50eef..fdd7d32 100644
--- a/README.md
+++ b/README.md
@@ -111,3 +111,169 @@ This project was collaboratively designed and developed by:
---
OG Docs is built with collaboration at its coreβdesigned to help teams write, iterate, and ship documentation together, faster and cleaner.
+
+
+
+
+
+
+
+
+
+
+frontend/src/
+βββ collaboration/
+β βββ socket.js
+β βββ ydoc.js
+β βββ awareness.js
+β βββ collabTypes.js
+β
+βββ hooks/
+β βββ useAuth.jsx
+β βββ useCollaboration.js β NEW
+β
+βββ components/
+β βββ GridEditor/
+β βββ GridEditor.jsx
+β βββ withCollaboration.js β NEW
+β βββ TextWidget.jsx
+β βββ ImageWidget.jsx
+β βββ VideoWidget.jsx
+
+
+
+
+
+
+
+
+backend/
+βββ socket/
+β βββ index.js
+β βββ auth.js
+β βββ rooms.js
+β βββ handlers/
+β βββ joinDoc.js
+β βββ syncUpdate.js
+β βββ awareness.js
+β βββ disconnect.js
+β
+βββ collaboration/
+β βββ yjs/
+β β βββ createDoc.js
+β β βββ applyUpdate.js
+β βββ persistence/
+β βββ loadSnapshot.js
+β βββ saveSnapshot.js
+
+
+
+
+
+π€ Teammate A β Backend (Realtime Engine)
+π― Responsibility
+
+Everything related to:
+
+Socket.IO
+
+Yjs document sync
+
+MongoDB snapshots
+
+π Files they touch
+backend/
+βββ socket/
+βββ collaboration/
+βββ models/Blog.js
+
+
+They do NOT touch frontend.
+
+π§ Their Tasks (Very Exact)
+A1 β Socket.IO server
+
+Attach Socket.IO to Express
+
+JWT auth on connection
+
+Rooms per blogId
+
+A2 β Yjs document manager
+
+Create Yjs doc per blog
+
+Load collabSnapshot
+
+Keep docs in memory
+
+A3 β Sync protocol
+
+Receive Yjs updates
+
+Broadcast to room
+
+Prevent echo loops
+
+A4 β Persistence
+
+Save snapshot when:
+
+last user leaves
+
+OR every 30s
+
+π¦ Output
+
+socket.emit("doc:update", update)
+socket.emit("doc:sync", state)
+
+
+
+
+
+π€ Teammate B β Frontend (Quill + Yjs)
+π― Responsibility
+
+Bind Quill editor β Yjs β Socket.IO.
+
+π Files they touch
+frontend/src/
+βββ collaboration/
+β βββ socket.js
+β βββ ydoc.js
+β βββ awareness.js
+β
+βββ components/GridEditor/
+β βββ GridEditor.jsx
+β βββ withCollaboration.js
+
+
+They do NOT touch backend.
+
+π§ Their Tasks (Very Exact)
+B1 β Yjs + Quill binding
+
+Create Y.Doc
+
+Create Y.Text
+
+Bind using y-quill
+
+import { QuillBinding } from 'y-quill'
+
+B2 β Socket sync
+
+Send Yjs updates to backend
+
+Apply remote updates
+
+B3 β Presence & cursors
+
+Use quill-cursors
+
+Show colored cursors per user
+
+π¦ Output
+
+
\ No newline at end of file
diff --git a/backend/models/Blog.js b/backend/models/Blog.js
index f80246e..b0b18b5 100644
--- a/backend/models/Blog.js
+++ b/backend/models/Blog.js
@@ -1,3 +1,34 @@
+// const mongoose = require('mongoose')
+
+// const blogSchema = new mongoose.Schema(
+// {
+// author: {
+// type: mongoose.Schema.Types.ObjectId,
+// ref: 'User',
+// required: true
+// },
+// title: {
+// type: String,
+// required: true,
+// trim: true
+// },
+// slug: {
+// type: String,
+// required: true,
+// unique: true
+// },
+// content: {
+// type: Array,
+// required: true,
+// default: []
+// }
+// },
+// { timestamps: true }
+// )
+
+// module.exports = mongoose.model('Blog', blogSchema)
+
+
const mongoose = require('mongoose')
const blogSchema = new mongoose.Schema(
@@ -7,20 +38,42 @@ const blogSchema = new mongoose.Schema(
ref: 'User',
required: true
},
+
title: {
type: String,
required: true,
trim: true
},
+
slug: {
type: String,
required: true,
unique: true
},
+
content: {
type: Array,
- required: true,
default: []
+ },
+
+ // π₯ Yjs snapshot for collaboration
+ collabSnapshot: {
+ type: Buffer, // store encoded Yjs state
+ default: null
+ },
+
+ // Optional: track who is currently editing
+ activeEditors: [
+ {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: 'User'
+ }
+ ],
+
+ // Collaboration versioning (future-proof)
+ collabVersion: {
+ type: Number,
+ default: 1
}
},
{ timestamps: true }
diff --git a/backend/package-lock.json b/backend/package-lock.json
index 87a95d9..30cea88 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -21,6 +21,8 @@
"mongoose": "^9.1.5",
"nanoid": "^3.3.11",
"slugify": "^1.6.6",
+ "socket.io": "^4.8.3",
+ "yjs": "^13.6.29",
"zod": "^4.3.6"
},
"devDependencies": {
@@ -78,6 +80,30 @@
"node": ">=14"
}
},
+ "node_modules/@socket.io/component-emitter": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
+ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/cors": {
+ "version": "2.8.19",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
+ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "25.2.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.2.tgz",
+ "integrity": "sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
"node_modules/@types/webidl-conversions": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
@@ -195,6 +221,15 @@
],
"license": "MIT"
},
+ "node_modules/base64id": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
+ "license": "MIT",
+ "engines": {
+ "node": "^4.5.0 || >= 5.9"
+ }
+ },
"node_modules/bignumber.js": {
"version": "9.3.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
@@ -553,6 +588,78 @@
"node": ">= 0.8"
}
},
+ "node_modules/engine.io": {
+ "version": "6.6.5",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz",
+ "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/cors": "^2.8.12",
+ "@types/node": ">=10.0.0",
+ "accepts": "~1.3.4",
+ "base64id": "2.0.0",
+ "cookie": "~0.7.2",
+ "cors": "~2.8.5",
+ "debug": "~4.4.1",
+ "engine.io-parser": "~5.2.1",
+ "ws": "~8.18.3"
+ },
+ "engines": {
+ "node": ">=10.2.0"
+ }
+ },
+ "node_modules/engine.io-parser": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
+ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/engine.io/node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/engine.io/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -1213,6 +1320,16 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"license": "ISC"
},
+ "node_modules/isomorphic.js": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz",
+ "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==",
+ "license": "MIT",
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
@@ -1289,6 +1406,27 @@
"node": ">=18.0.0"
}
},
+ "node_modules/lib0": {
+ "version": "0.2.117",
+ "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz",
+ "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==",
+ "license": "MIT",
+ "dependencies": {
+ "isomorphic.js": "^0.2.4"
+ },
+ "bin": {
+ "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
+ "0gentesthtml": "bin/gentesthtml.js",
+ "0serve": "bin/0serve.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
@@ -2093,6 +2231,90 @@
"node": ">=8.0.0"
}
},
+ "node_modules/socket.io": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz",
+ "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "base64id": "~2.0.0",
+ "cors": "~2.8.5",
+ "debug": "~4.4.1",
+ "engine.io": "~6.6.0",
+ "socket.io-adapter": "~2.5.2",
+ "socket.io-parser": "~4.2.4"
+ },
+ "engines": {
+ "node": ">=10.2.0"
+ }
+ },
+ "node_modules/socket.io-adapter": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz",
+ "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "~4.4.1",
+ "ws": "~8.18.3"
+ }
+ },
+ "node_modules/socket.io-parser": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz",
+ "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.4.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/socket.io/node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/socket.io/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/socket.io/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/socket.io/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
@@ -2285,6 +2507,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "license": "MIT"
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -2446,6 +2674,44 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
+ "node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/yjs": {
+ "version": "13.6.29",
+ "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.29.tgz",
+ "integrity": "sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "lib0": "^0.2.99"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=8.0.0"
+ },
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/zod": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
diff --git a/backend/package.json b/backend/package.json
index a62d360..2dd999f 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -24,6 +24,8 @@
"mongoose": "^9.1.5",
"nanoid": "^3.3.11",
"slugify": "^1.6.6",
+ "socket.io": "^4.8.3",
+ "yjs": "^13.6.29",
"zod": "^4.3.6"
},
"devDependencies": {
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index b3836fb..da667e6 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -19,6 +19,7 @@
"is-hotkey": "^0.2.0",
"lodash": "^4.17.23",
"quill": "^2.0.3",
+ "quill-cursors": "^4.0.4",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-grid-layout": "^2.2.2",
@@ -26,7 +27,10 @@
"react-router-dom": "^7.12.0",
"react-secure-storage": "^1.3.2",
"slate-history": "^0.113.1",
+ "socket.io-client": "^4.8.3",
"uuid": "^13.0.0",
+ "y-quill": "^1.0.0",
+ "yjs": "^13.6.29",
"zod": "^4.3.6"
},
"devDependencies": {
@@ -1263,6 +1267,12 @@
"win32"
]
},
+ "node_modules/@socket.io/component-emitter": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
+ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
+ "license": "MIT"
+ },
"node_modules/@swc/core": {
"version": "1.15.10",
"dev": true,
@@ -2074,7 +2084,6 @@
},
"node_modules/debug": {
"version": "4.4.3",
- "dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -2128,6 +2137,28 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/engine.io-client": {
+ "version": "6.6.4",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz",
+ "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==",
+ "license": "MIT",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.4.1",
+ "engine.io-parser": "~5.2.1",
+ "ws": "~8.18.3",
+ "xmlhttprequest-ssl": "~2.1.1"
+ }
+ },
+ "node_modules/engine.io-parser": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
+ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/enhanced-resolve": {
"version": "5.18.4",
"license": "MIT",
@@ -2793,6 +2824,16 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/isomorphic.js": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz",
+ "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==",
+ "license": "MIT",
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/jiti": {
"version": "2.6.1",
"license": "MIT",
@@ -2872,6 +2913,27 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lib0": {
+ "version": "0.2.117",
+ "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz",
+ "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==",
+ "license": "MIT",
+ "dependencies": {
+ "isomorphic.js": "^0.2.4"
+ },
+ "bin": {
+ "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
+ "0gentesthtml": "bin/gentesthtml.js",
+ "0serve": "bin/0serve.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/lightningcss": {
"version": "1.30.2",
"license": "MPL-2.0",
@@ -3229,7 +3291,6 @@
},
"node_modules/ms": {
"version": "2.1.3",
- "dev": true,
"license": "MIT"
},
"node_modules/murmurhash-js": {
@@ -3441,6 +3502,12 @@
"npm": ">=8.2.3"
}
},
+ "node_modules/quill-cursors": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/quill-cursors/-/quill-cursors-4.0.4.tgz",
+ "integrity": "sha512-beHOYwRZ/I+Ift3bsvMnNWZ7gX25upW3b0aREpklUTR273MFJgxsCYmlgd/6otBE0FtFefOfh2/xU6xbkkxgIg==",
+ "license": "MIT"
+ },
"node_modules/quill-delta": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
@@ -3687,6 +3754,34 @@
"slate": ">=0.65.3"
}
},
+ "node_modules/socket.io-client": {
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz",
+ "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==",
+ "license": "MIT",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.4.1",
+ "engine.io-client": "~6.6.1",
+ "socket.io-parser": "~4.2.4"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/socket.io-parser": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz",
+ "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.4.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"license": "BSD-3-Clause",
@@ -3900,11 +3995,96 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xmlhttprequest-ssl": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
+ "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/y-protocols": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz",
+ "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==",
+ "license": "MIT",
+ "dependencies": {
+ "lib0": "^0.2.85"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=8.0.0"
+ },
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ },
+ "peerDependencies": {
+ "yjs": "^13.0.0"
+ }
+ },
+ "node_modules/y-quill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/y-quill/-/y-quill-1.0.0.tgz",
+ "integrity": "sha512-WpYBXsFXdofGuaAVyvKpZ3rg+TklWtKtpemUziY044NLhnwud0D+QTX2mdGKMrLON+BshKQeT77FbXa68ZJbcA==",
+ "license": "MIT",
+ "dependencies": {
+ "lib0": "^0.2.93",
+ "y-protocols": "^1.0.6"
+ },
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ },
+ "peerDependencies": {
+ "quill": "^2.0.0",
+ "quill-cursors": "^4.0.2",
+ "yjs": "^13.6.14"
+ }
+ },
"node_modules/yallist": {
"version": "3.1.1",
"dev": true,
"license": "ISC"
},
+ "node_modules/yjs": {
+ "version": "13.6.29",
+ "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.29.tgz",
+ "integrity": "sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "lib0": "^0.2.99"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=8.0.0"
+ },
+ "funding": {
+ "type": "GitHub Sponsors β€",
+ "url": "https://github.com/sponsors/dmonad"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"dev": true,
diff --git a/frontend/package.json b/frontend/package.json
index 6e24551..1e7c71b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -21,6 +21,7 @@
"is-hotkey": "^0.2.0",
"lodash": "^4.17.23",
"quill": "^2.0.3",
+ "quill-cursors": "^4.0.4",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-grid-layout": "^2.2.2",
@@ -28,7 +29,10 @@
"react-router-dom": "^7.12.0",
"react-secure-storage": "^1.3.2",
"slate-history": "^0.113.1",
+ "socket.io-client": "^4.8.3",
"uuid": "^13.0.0",
+ "y-quill": "^1.0.0",
+ "yjs": "^13.6.29",
"zod": "^4.3.6"
},
"devDependencies": {
From 0c93d1d08d9828750307654818b494a44d334a10 Mon Sep 17 00:00:00 2001
From: Hana
Date: Mon, 9 Feb 2026 12:51:39 +0530
Subject: [PATCH 03/57] titleChange
---
frontend/index.html | 2 +-
frontend/src/components/Sidebar.jsx | 2 +-
frontend/src/pages/HomeFeed.jsx | 4 ++--
frontend/src/pages/login.jsx | 2 +-
frontend/src/pages/startPage.jsx | 5 ++---
5 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/frontend/index.html b/frontend/index.html
index 089e053..432c230 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -5,7 +5,7 @@
- blogify
+ ogDoc
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
index 2250591..0ca7031 100644
--- a/frontend/src/components/Sidebar.jsx
+++ b/frontend/src/components/Sidebar.jsx
@@ -39,7 +39,7 @@ export const Sidebar = () => {
- Blogify
+ ogDoc
diff --git a/frontend/src/pages/HomeFeed.jsx b/frontend/src/pages/HomeFeed.jsx
index 57fe944..d826c9c 100644
--- a/frontend/src/pages/HomeFeed.jsx
+++ b/frontend/src/pages/HomeFeed.jsx
@@ -124,7 +124,7 @@ export default function HomeFeed() {
{/* --- MINIMAL NAVIGATION --- */}
- Blogify
+ ogDoc
@@ -232,6 +232,6 @@ export default function HomeFeed() {
+ © 2026 ogDoc Engine
);
}
diff --git a/frontend/src/pages/login.jsx b/frontend/src/pages/login.jsx
index b20244d..c6de92d 100644
--- a/frontend/src/pages/login.jsx
+++ b/frontend/src/pages/login.jsx
@@ -71,7 +71,7 @@ function Login() {
- Continue to Blogify
+ Continue to ogDoc
diff --git a/frontend/src/pages/startPage.jsx b/frontend/src/pages/startPage.jsx
index d43d210..bec5457 100644
--- a/frontend/src/pages/startPage.jsx
+++ b/frontend/src/pages/startPage.jsx
@@ -79,13 +79,12 @@ export default function StartPage() {
Welcome to{" "}
- Blogify
+ ogDoc
- A minimalist space to document your journey,
- explore new perspectives, and share stories.
+ A dedicated workspace where multiple collaborators can make changes simultaneously, with updates reflected in real time to ensure smooth and efficient collaboration.
Date: Mon, 9 Feb 2026 02:58:43 -0500
Subject: [PATCH 04/57] color theme change
---
frontend/src/components/Sidebar.jsx | 10 ++++----
frontend/src/pages/CreatePost.jsx | 26 +++++++++++---------
frontend/src/pages/HomeFeed.jsx | 38 ++++++++++++++---------------
frontend/src/pages/login.jsx | 16 ++++++------
frontend/src/pages/startPage.jsx | 27 ++++++++++----------
5 files changed, 59 insertions(+), 58 deletions(-)
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
index 2250591..0ceb5b3 100644
--- a/frontend/src/components/Sidebar.jsx
+++ b/frontend/src/components/Sidebar.jsx
@@ -35,17 +35,17 @@ export const Sidebar = () => {
},[localStorage.getItem('theme')])
return (
-
-
-
+
+
+
Blogify
-
- MENU
+
+ MENU
diff --git a/frontend/src/pages/CreatePost.jsx b/frontend/src/pages/CreatePost.jsx
index 760955c..d5e50d0 100644
--- a/frontend/src/pages/CreatePost.jsx
+++ b/frontend/src/pages/CreatePost.jsx
@@ -16,7 +16,7 @@ const initialWidgets = [
const ToolbarContainer = ({ children }) => (
-
+
{children}
)
@@ -25,7 +25,7 @@ const ToolbarButton = ({ onClick, children, title }) => (
{children}
@@ -221,7 +221,7 @@ const CreatePost = () => {
}
return (
-
+
-
-
+
+
New Story
setIsDark(!isDark)}
- className="text-[10px] uppercase tracking-[0.2em] font-bold text-slate-400 dark:text-slate-500 hover:text-slate-900 dark:hover:text-slate-100 transition-colors"
+ className="text-[10px] uppercase tracking-[0.2em] font-bold text-slate-400 dark:text-gray-400 hover:text-slate-900 dark:hover:text-gray-300 transition-colors"
>
{isDark ? : }
Publish
@@ -252,7 +252,7 @@ const CreatePost = () => {
-
+
@@ -272,13 +272,13 @@ const CreatePost = () => {
backgroundColor: "transparent",
transition: "all 0.3s ease",
}}
- className="w-full font-['Outfit',_sans-serif] text-[#ffffffff] text-2xl md:text-4xl font-bold bg-transparent border-none focus:outline-none p-0 text-slate-700 placeholder:text-slate-300 dark:placeholder:text-slate-600 dark:text-slate-500"
+ className="w-full font-['Outfit',_sans-serif] text-[#ffffffff] text-2xl md:text-4xl font-bold bg-transparent border-none focus:outline-none p-0 text-slate-700 placeholder:text-slate-300 dark:placeholder:text-gray-400 dark:text-gray-400"
/>
{/* TOOLBAR */}
-
+
- Add Content:
+ Add Content:
text_fields Text
@@ -304,7 +304,9 @@ const CreatePost = () => {
{/* GRID EDITOR CANVAS */}
-
+
+
+
diff --git a/frontend/src/pages/HomeFeed.jsx b/frontend/src/pages/HomeFeed.jsx
index 57fe944..4671d33 100644
--- a/frontend/src/pages/HomeFeed.jsx
+++ b/frontend/src/pages/HomeFeed.jsx
@@ -8,17 +8,17 @@ const DeleteConfirmationModal = ({ show, onClose, onConfirm, postTitle }) => {
return (
-
-
+
+
Confirm Deletion
-
+
Are you sure you want to delete the post: **{postTitle}**? This action cannot be undone.
Cancel
@@ -110,7 +110,7 @@ export default function HomeFeed() {
return (
+ bg-slate-50 text-slate-800 dark:bg-black dark:text-gray-400">
-
-
+
+
-
+
Welcome Back
-
- Continue to Blogify
+
+ Continue to Blogify
@@ -81,10 +81,10 @@ function Login() {
>
-
+
navigate("/")}
- className="text-[10px] uppercase tracking-[0.2em] font-bold text-slate-400 hover:text-slate-600 dark:hover:text-slate-200 transition-colors"
+ className="text-[10px] uppercase tracking-[0.2em] font-bold text-slate-400 hover:text-slate-600 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
>
Back to Start
diff --git a/frontend/src/pages/startPage.jsx b/frontend/src/pages/startPage.jsx
index d43d210..7d1df7a 100644
--- a/frontend/src/pages/startPage.jsx
+++ b/frontend/src/pages/startPage.jsx
@@ -30,7 +30,7 @@ export default function StartPage() {
className="
min-h-screen relative overflow-hidden transition-colors duration-500
bg-slate-50 text-slate-800 font-['Inter',_sans-serif]
- dark:bg-[#0f172a] dark:text-slate-400
+ dark:bg-black dark:text-gray-400
"
>
);
diff --git a/frontend/src/components/GridEditor/VideoWidget.jsx b/frontend/src/components/GridEditor/VideoWidget.jsx
index 5358693..0e864eb 100644
--- a/frontend/src/components/GridEditor/VideoWidget.jsx
+++ b/frontend/src/components/GridEditor/VideoWidget.jsx
@@ -10,7 +10,7 @@ const VideoWidget = ({ url }) => {
}
return (
-
+
{/* Overlay to allow dragging over the iframe without getting captured by the iframe */}