Conflux: Real-Time Collaborative Editor
Real-time collaborative document editor with multi-cursor presence, live text selection, emoji reactions, and Stripe subscription plans.





Conflux is a production-grade alternative to Notion and Google Docs. The core engineering challenge: making multiple users editing the same document feel instantaneous and conflict-free through room-based WebSocket propagation and cursor positioning layers.
Full System Architecture
Hybrid Real-Time Architecture
An in-depth analysis of the Conflux codebase reveals a sophisticated, hybrid synchronization architecture. Instead of relying on a single sync channel, the platform decouples tasks to optimize latency, bandwith, and state persistence:
- High-Frequency Text Deltas & Cursors (Socket.IO): Next.js API custom WebSocket route broadcasts fast text changes and selection ranges to ensure editing latency stays under 50ms.
- Collaborator Presence Tracking (Supabase Realtime): Collaborative room occupancy, profile states, usernames, and avatar image resolutions are tracked via Supabase Realtime Channels.
- Document Persistence (Drizzle ORM Autosave): Editing edits are debounced (850ms delay) and committed to the Supabase PostgreSQL database using Drizzle ORM.
Technical Deep-Dive: Socket.IO Delta Relay
High-frequency text edits inside the Quill editor are serialized as Quill Deltas (operational transform chunks). When a user types, the client captures the editor input source and pushes it immediately to the room:
// Listen for local editor changes and emit them
quill.on('text-change', (delta, oldDelta, source) => {
if (source !== 'user') return;
socket.emit('send-changes', delta, fileId);
});
// Listen for incoming collaborative changes and apply them
socket.on('receive-changes', (deltas, id) => {
if (id === fileId) {
quill.updateContents(deltas); // Applied directly to Quill representation
}
});These socket events are routed through a custom Next.js API WebSocket server running on HTTP server connections:
// src/pages/api/socket/io.ts
import { Server as ServerIO } from 'socket.io';
const ioHandler = (req: NextApiRequest, res: NextApiResponseServerIo) => {
if (!res.socket.server.io) {
const httpServer = res.socket.server;
const io = new ServerIO(httpServer, {
path: '/api/socket/io',
addTrailingSlash: false,
});
io.on('connection', (socket) => {
// Create room partition per document
socket.on('create-room', (fileId) => {
socket.join(fileId);
});
// Relay changes to all other sockets in the room
socket.on('send-changes', (deltas, fileId) => {
socket.to(fileId).emit('receive-changes', deltas, fileId);
});
// Relay cursor selections
socket.on('send-cursor-move', (range, fileId, cursorId) => {
socket.to(fileId).emit('receive-cursor-move', range, fileId, cursorId);
});
});
res.socket.server.io = io;
}
res.end();
};Collaborator Presence Tracking (Supabase Realtime)
While high-frequency edits utilize a Node.js socket, collaborator presence (avatar lists and online notifications) is tracked via Supabase Realtime Channels. When clients connect, they bind to the presence sync event and track their profile information (avatars, emails, user IDs):
useEffect(() => {
if (!fileId || quill === null) return;
const room = supabase.channel(fileId);
const subscription = room
.on('presence', { event: 'sync' }, () => {
const newState = room.presenceState();
const newCollaborators = Object.values(newState).flat();
setCollaborators(newCollaborators);
if (user) {
const allCursors: any = [];
newCollaborators.forEach((collaborator) => {
if (collaborator.id !== user.id) {
const userCursor = quill.getModule('cursors');
userCursor.createCursor(
collaborator.id,
collaborator.email.split('@')[0],
`#${Math.random().toString(16).slice(2, 8)}`
);
allCursors.push(userCursor);
}
});
setLocalCursors(allCursors);
}
})
.subscribe(async (status) => {
if (status !== 'SUBSCRIBED' || !user) return;
const response = await findUser(user.id);
if (!response) return;
room.track({
id: user.id,
email: user.email?.split('@')[0],
avatarUrl: response.avatarUrl
? supabase.storage.from('avatars').getPublicUrl(response.avatarUrl).data.publicUrl
: '',
});
});
return () => {
supabase.removeChannel(room);
};
}, [fileId, quill, supabase, user]);State Persistence with Drizzle ORM
The application database is built on Supabase PostgreSQL, configured and managed type-safely via Drizzle ORM. As users make modifications, the editor schedules a debounced save (850ms delay) that updates the document content string in the database:
// src/lib/supabase/schema.ts
import { pgTable, uuid, text, timestamp } from "drizzle-orm/pg-core";
export const workspaces = pgTable('workspaces', {
id: uuid('id').defaultRandom().primaryKey().notNull(),
createdAt: timestamp('created_at', { withTimezone: true, mode: 'string' }),
workspaceOwner: uuid('workspace_owner').notNull(),
title: text('title').notNull(),
iconId: text('icon_id').notNull(),
data: text('data'),
inTrash: text('in_trash'),
logo: text('logo'),
bannerUrl: text('banner_url'),
});
export const files = pgTable('files', {
id: uuid('id').defaultRandom().primaryKey().notNull(),
createdAt: timestamp('created_at', { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
title: text('title').notNull(),
iconId: text('icon_id').notNull(),
data: text('data'), // Serialized Quill Delta JSON string
workspaceId: uuid('workspace_id').notNull().references(() => workspaces.id, { onDelete: 'cascade' }),
folderId: uuid('folder_id').notNull().references(() => folders.id, { onDelete: 'cascade' }),
});Key Features
- 🖱️ Real-Time Cursor Presence — Tracks and displays online cursors for every collaborator in the active room via the Socket.io selection-change listener.
- 📝 Live Text Selection Highlight — Visualizes exactly what text selections other collaborators are focusing on.
- 👥 Hybrid Collaborators Hub — Merges Supabase presence tracking with client avatars, showing who is currently inside the document.
- 📁 Logical Folder Structure — Nest files within nested directories to maintain a clean Workspace catalog.
- 🗑️ Soft-Delete System — Moves files/folders into a trash drawer to allow restoration and prevent data loss.
- 🎨 Workspace Customization — Upload workspace logos, choose banner templates, and assign file icons/emojis.
- 💳 Stripe Subscriptions — Features checkouts and automated billing webhooks to update user plans.