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
```bash
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