Jaimodiji's picture
Upload folder using huggingface_hub
9575119 verified

ColorRM Pro

A real-time collaborative PDF annotation and drawing application built with modern web technologies.

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Frontend                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                    color_rm.html                          β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚  β”‚  β”‚ ColorRm     β”‚  β”‚ ColorRm     β”‚  β”‚ ColorRm         β”‚   β”‚   β”‚
β”‚  β”‚  β”‚ Session.js  │──│ Renderer.js │──│ LiveSync.js     β”‚   β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Backend                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Cloudflare Workers  β”‚    β”‚  HuggingFace Spaces         β”‚    β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚    β”‚
β”‚  β”‚  β”‚ worker.ts      β”‚  β”‚    β”‚  β”‚ Vite Dev Server       β”‚  β”‚    β”‚
β”‚  β”‚  β”‚ - API Routes   β”‚  β”‚    β”‚  β”‚ - Static files        β”‚  β”‚    β”‚
β”‚  β”‚  β”‚ - R2 Storage   β”‚  β”‚    β”‚  β”‚ - PDF Convert (7861)  β”‚  β”‚    β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚    β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚  β”‚  β”‚ Durable Objectsβ”‚  β”‚                                        β”‚
β”‚  β”‚  β”‚ - ColorRm DO   β”‚  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚    β”‚  Liveblocks                 β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  - Real-time sync           β”‚    β”‚
β”‚                              β”‚  - Presence                  β”‚    β”‚
β”‚                              β”‚  - Room management           β”‚    β”‚
β”‚                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Modules

Frontend (public/scripts/modules/)

Module Description
ColorRmSession.js Main application controller. Handles state, tools, page management, import/export
ColorRmRenderer.js Canvas rendering engine. Draws strokes, shapes, images, handles transformations
ColorRmStorage.js IndexedDB and R2 storage. Manages local persistence and cloud sync
ColorRmLiveSync.js Liveblocks integration. Real-time collaboration, cursors, history sync
ColorRmSvgImporter.js SVG parsing and import. Converts SVG elements to ColorRM history items
ColorRmSvgExporter.js SVG export. Renders history to vector SVG format

Backend (worker/)

File Description
worker.ts Main Cloudflare Worker entry point. Routes API requests
colorRmAssets.ts R2 storage handlers for pages, history, modifications
pdfToSvg.ts PDF conversion job management (placeholder for CF Workers)
ColorRmDurableObject.ts Durable Object for room state management

Commands (cmd/)

Script Description
pdf_convert_server.mjs Local PDF to SVG server using pdf2svg binary
hf_init.mjs HuggingFace authentication initialization
hf_backup.mjs Periodic backup to HuggingFace Hub
hf_restore.mjs Restore from HuggingFace Hub on startup

Data Flow

SVG Import Flow

1. User selects SVG file
   β”‚
2. ColorRmSvgImporter.importSvg() parses SVG
   β”‚
3. Elements are classified:
   β”œβ”€β”€ Images/Text β†’ Rasterized to background blob
   └── Strokes/Shapes β†’ Kept as vector history items
   β”‚
4. Page object created with blob + history
   β”‚
5. Sync to cloud:
   β”œβ”€β”€ Blob β†’ R2 via _uploadPageBlob()
   β”œβ”€β”€ History β†’ R2 via /api/color_rm/history/:sessionId/:pageId
   └── Structure β†’ Liveblocks via _syncPageStructureToLive()
   β”‚
6. Other users receive notification via Liveblocks
   β”‚
7. Other users fetch page blob from R2

History Sync (Delta Architecture)

For pages with base history (SVG imports):

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    R2 Storage (Base)                         β”‚
β”‚  /api/color_rm/history/:sessionId/:pageId                   β”‚
β”‚  - Original SVG items (large, stored once)                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              +
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 Liveblocks (Deltas Only)                     β”‚
β”‚  - New strokes added by users                               β”‚
β”‚  - Modifications to base items (position, color, etc.)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              =
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Final Rendered Page                       β”‚
β”‚  BaseHistory + Deltas + Modifications                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Thresholds

Condition Threshold Action
SVG page history > 400 items Use R2 for base, Liveblocks for deltas
Regular page history > 2000 items Convert to hybrid R2/Liveblocks
Modifications > 100 items Store in R2, sync metadata via Liveblocks

API Endpoints

Page Management

Method Endpoint Description
POST /api/color_rm/page/:sessionId/:pageId Upload page blob
GET /api/color_rm/page/:sessionId/:pageId Download page blob
DELETE /api/color_rm/page/:sessionId/:pageId Delete page

History

Method Endpoint Description
POST /api/color_rm/history/:sessionId/:pageId Upload base history
GET /api/color_rm/history/:sessionId/:pageId Get base history

Page Structure

Method Endpoint Description
GET /api/color_rm/page_structure/:sessionId Get page order
POST /api/color_rm/page_structure/:sessionId Update page order

PDF Conversion (Local Server)

Method Endpoint Description
POST /convert/pdf Upload PDF for conversion
GET /convert/status/:jobId Check conversion status
GET /convert/page/:jobId/:pageNum Download converted SVG page

Development

Local Development

npm install
npm run dev

HuggingFace Spaces Deployment

The Dockerfile runs:

  1. hf_init.mjs - Authenticate with HF
  2. hf_restore.mjs - Restore previous state
  3. npm run dev - Vite dev server (port 7860)
  4. hf_backup.mjs - Periodic backup worker
  5. pdf_convert_server.mjs - PDF conversion (port 7861)

Environment Variables

Variable Description
HF_TOKEN HuggingFace API token
LIVEBLOCKS_SECRET_KEY Liveblocks API key
PORT Dev server port (default: 7860)

Tools

Tool Shortcut Description
Move V Select and move objects
Hand H Pan the canvas
Lasso L Free-form selection
Pen P Freehand drawing
Shape S Draw shapes (rect, ellipse, arrow, etc.)
Text T Add text annotations
Eraser E Erase strokes
Box/Capture B Capture region to clipboard

Collaboration Features

  • Real-time cursors: See other users' cursors
  • Live history sync: Strokes appear instantly for all users
  • Page structure sync: Page order synchronized across users
  • Presence indicators: See who's online in the room