Commit Graph
43 Commits
Author SHA1 Message Date
forkless bb710b46b0 fix: suppress CORS flood from excalidraw.com/og-image-3.png fetch
Docker Build (ARM64) / Build & Push (push) Successful in 2m4s
2026-06-25 00:52:35 +02:00
forkless 7f01d76c2b fix: preserve ws:// vs wss:// scheme in URL normalization
Docker Build (ARM64) / Build & Push (push) Successful in 2m3s
2026-06-24 21:01:31 +02:00
forkless a1db6e782d feat: fully normalize CUSTOM_VITE_WS_URL (strip scheme/path, keep port)
Docker Build (ARM64) / Build & Push (push) Successful in 2m2s
2026-06-24 20:59:17 +02:00
forkless 7222c9ae63 feat: auto-prefix wss:// if CUSTOM_VITE_WS_URL is just host
Docker Build (ARM64) / Build & Push (push) Successful in 2m2s
2026-06-24 20:56:35 +02:00
forkless a8ee1c229e feat: env-var-ize WS URL as CUSTOM_VITE_WS_URL, add .env.example
Docker Build (ARM64) / Build & Push (push) Successful in 50s
2026-06-24 20:55:02 +02:00
forkless a06c3d2e36 cleanup: remove broken patch script ref + unused collab props
Docker Build (ARM64) / Build & Push (push) Successful in 2m1s
2026-06-24 20:25:09 +02:00
forkless 547fd6affb fix: add onCollabDialogOpen to show share button
Docker Build (ARM64) / Build & Push (push) Successful in 2m3s
2026-06-24 18:40:40 +02:00
forkless 32188d93b4 fix: collab WS path /socket.io for Excalidraw library
Docker Build (ARM64) / Build & Push (push) Has been cancelled
2026-06-24 18:31:37 +02:00
forkless 4dceeb2e7f fix: point frontend WS to wss://excalidraw.forkless.com
Docker Build (ARM64) / Build & Push (push) Successful in 2m2s
2026-06-24 18:18:19 +02:00
forkless a4a1b03215 fix: redirect collab WS to excalidraw.forkless.com
Docker Build (ARM64) / Build & Push (push) Successful in 2m24s
2026-06-24 18:09:31 +02:00
forkless f91082d2a3 fix: disable Excalidraw collaboration WS to oss-collab.excalidraw.com
Docker Build (ARM64) / Build & Push (push) Has been cancelled
2026-06-24 18:08:40 +02:00
9846e0ba0f feat(canvas): native field preservation, label materialization, batch workspace delete (#12)
* feat(canvas): native field preservation, label materialization, batch workspace delete

- fillNativeFields() + repairContainerBinding() in db layer ensure every
  element stored in SQLite is a complete, round-trippable Excalidraw element
  with correct containerId ↔ boundElements bidirectional binding
- materializeLabel() in server.ts: shapes with label.text/text produce a
  native bound text element at write time (create, update, batch) so text
  follows its container when moved — matches VSCode Excalidraw extension behavior
- Batch workspace UI: Select/Unselect All, per-row checkboxes, Delete N
  workspaces button with confirmation
- POST /api/tenants/batch-delete: delete up to 50 tenants in one request
- 42 new backend tests; 519 total passing
- Bump version 1.0.6 → 1.1.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(tests): update e2e assertions for label materialization

phase2-regressions: label is now a native bound text element
(id: pos-stable-1-label) — check bound text element text instead
of container.label?.text which is no longer stored.

sync-flows FTS: search now matches the bound text element (fts-el-label)
rather than the container — accept either id as valid match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 21:12:01 +02:00
d14d767c75 feat(tenants): add workspace delete UI and fix project switch element loading (#11)
- Add DELETE /api/tenants/:id endpoint with cascade (projects, elements, snapshots)
- Add delete buttons with inline confirm in workspace switcher panel
- Fix project switch not loading elements: switchProjectUI now directly clears
  canvas and calls loadExistingElements() instead of relying on WS roundtrip

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:37:11 +02:00
Maxime Roy (new.blacc)andGitHub 1166ea5b3f chore: release v1.0.5 (#10)
feat(projects): project management UI, sync countdown, fix project switching
2026-04-06 13:18:03 +02:00
newblaccandClaude Sonnet 4.6 64ebfc6791 fix: gauntlet hardening — alignment regression tests, cleanup, DRY, docker labels
- test: 3 regression tests for textAlign/verticalAlign/containerId REST round-trip
  (Zod was silently stripping these fields before the schema fix)
- fix: pendingTitleTimerRef cleanup on unmount (App.tsx)
- fix: localStorage JSON.parse wrapped in try/catch to prevent crash (App.tsx)
- refactor: extract seedKnownContainers() helper — 4 identical loops → 1 (App.tsx)
- chore: remove unnecessary `as any` cast on subtitle element type (index.ts)
- docs: test counts updated to 446 (README.md, CLAUDE.md)
- chore: fix stale LABEL source URLs in Dockerfile and Dockerfile.canvas

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 21:20:14 +02:00
newblaccandClaude Sonnet 4.6 90cae43193 fix: resolve double-WS race and WS-delivered title injection; add curved arrow e2e
- Block CONNECTING state in WS guard to prevent second connection seeding
  knownContainerIdsRef before element_created fires
- Call handleCanvasChange() explicitly after element_created updateScene
  (CaptureUpdateAction.NEVER suppresses onChange in Excalidraw 0.18)
- E2E: curved arrow stays deformable after sync round-trip
- E2E: auto-title injection test now reliably passes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 18:33:18 +02:00
newblacc f1db126566 test: add phase security/smoke/e2e coverage and tighten MCP contract handling 2026-03-30 15:52:24 +02:00
newblaccandClaude Opus 4.6 a605a15282 feat: auto title/subtitle, Nunito default, position-preserving sync, draggable font widget
- Default font changed to Nunito (id 6)
- Containers auto-inject "Title" + "Text here" subtitle on draw (grouped)
- MCP create_element defaults to title/subtitle card layout for containers
- Sync preserves element geometry (x/y/width/height) across refreshes
- normalizeForBackend preserves native bound text instead of collapsing to label.text
- Rate limits raised to 500 req/15min general, 30 req/min sync writes
- Draggable "Font px" widget with localStorage position persistence
- Left panel widened for full Opacity visibility
- Updated rate-limit tests to match new limits (30 write, 500 general)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:56:59 +02:00
newblaccandClaude Opus 4.6 1e535a5e31 fix: labels stored as label.text now persist across page refresh
convertToExcalidrawElements silently dropped label.text on reload.
Added expandLabelsToNative() that pre-expands server-format labels
into native Excalidraw bound text elements before the scene is set,
ensuring labels survive DB round-trips.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 00:43:50 +02:00
newblaccandClaude Sonnet 4.6 d8ef0379f5 feat: set dark theme as default
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 00:29:37 +02:00
newblaccandClaude Sonnet 4.6 d993355a54 fix: bidirectional sync conflict and labeled element update rendering
- Update lastSyncedElementsRef on every WS-applied scene change so
  auto-sync does not revert MCP writes back to stale browser state
- Fix labeled container updates (rect/ellipse/diamond/arrow) to use
  convertToExcalidrawElements with bound-text ID transplant, preventing
  text clipping and empty labels after update
- Fix standalone text element updates to write into text/originalText
  so Excalidraw renders the new value immediately
- Fix convertTextToLabel to handle arrows and empty string text values

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 00:23:41 +02:00
newblaccandClaude Sonnet 4.6 5539235004 feat(security): harden canvas server with auth, rate-limiting, and validation
- Add security.ts: helmet, CORS allowlist, timing-safe API key auth, prototype
  pollution guard, Mermaid input limits, rate limiting (general/destructive/burst)
- WS auth challenge-response with 5 s timeout and close code 4001
- Fix sync crash: array check before logger access (500 → 400)
- Fix sync/v2: validate element type before write (invalid → 400)
- Upgrade zod 3.22.4 → 3.25.5 (fixes ERR_PACKAGE_PATH_NOT_EXPORTED on startup)
- Extract ElementSharedFieldsSchema; move VALID_ELEMENT_TYPES to module level
- Docker: resource limits, .dockerignore hardening
- Add .project-hooks/pre-commit; expand test coverage (369 tests)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 16:06:04 +02:00
Sanjib DevnathandGitHub 2e743c1356 🐛 fix(sync): resolve delete persistence regression and harden data-safety invariants (#13)
Deletions made in the UI were silently lost on page reload because the sync
baseline (lastSyncedElementsRef) was never populated after initial load,
making the delta algorithm unable to detect removed elements. Additionally,
import_scene and restore_snapshot used a non-atomic clear+create pattern
that could permanently lose all canvas data if the batch create failed
after clearing, and duplicate_elements copied stale binding references
pointing to original element IDs instead of remapped duplicates.

🔧 Sync baseline restoration:
- Populate deletion-detection baseline on every server-to-client data path
  (page load, delta resync, hello handshake, initial elements broadcast)
- Establish sync version and hash baselines to prevent phantom re-syncs

🛡️ Data-loss prevention:
- Backup current scene before destructive clear in replace-mode operations
- Atomic restore from backup when subsequent batch create fails
- Remap all binding references (start/end IDs, boundElements, containerId)
  to new IDs during element duplication

 Comprehensive test coverage (154 new tests, 344 total):
- Delta sync flows including deletion persistence and bidirectional sync
- Multi-tenant element/sync/WebSocket isolation
- Arrow binding resolution across all shape types and edge cases
- MCP tool integration covering backup-restore and binding remapping
- Input validation and security boundary testing
- Frontend sync algorithm unit tests reproducing the exact regression

🎯 Eliminates the most critical data-integrity risks: deletions now
persist reliably, destructive operations are rollback-safe, and the
full test suite provides regression coverage for every sync path.
2026-03-18 10:07:07 +05:30
7c59972bb1 🐛 fix(mcp): resolve race conditions, sync failures, and preference regressions (#12)
Fix 6 bugs discovered during MCP tool usage:

1. syncToCanvas error handling: Distinguish network errors (return null)
   from API errors (re-throw with actual message). Fixes misleading
   "HTTP server unavailable" on batch_create_elements.

2. USER_PREFS fallbacks: create_element and batch_create_elements now
   apply fontFamily/roughness/fontSize/strokeWidth from preferences.json
   when not explicitly provided by the caller.

3. Hello handshake: Frontend sends `hello` on tenant_switched and handles
   `hello_ack`. Server resolves projectId from tenantId when absent.
   Fixes WS connections being registered under wrong scope.

4. Serialized broadcasts: Add serializedBroadcastWithAck() that queues
   broadcasts per tenant/project scope. Prevents race condition where
   parallel MCP create_element calls produce overlapping WS messages
   that clobber each other in the frontend.

5. Viewport screenshot: get_canvas_screenshot passes captureViewport=true,
   frontend captures DOM canvas via toDataURL() instead of exportToBlob()
   which always rendered the full scene bounding box.

6. Viewport animate:false: set_viewport uses animate:false for instant
   positioning, preventing mid-animation screenshot captures.

Tests: 14 new tests (8 API, 6 WS) + 9 E2E specs covering all fixes.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 08:28:00 +05:30
2cca18153f feat(sync): implement scoped sync architecture with ACK model and comprehensive tests (#11)
Implement a complete sync architecture overhaul (12 tasks) replacing the flat
WebSocket broadcast with scoped, acknowledged delivery:

**Backend (server.ts, db.ts, types.ts, index.ts):**
- Scoped connection registry: Map<tenant, Map<project, Set<ClientConnection>>>
- Hello handshake: WS clients identify tenant/project, server responds with scoped elements
- broadcastToScope() replaces global broadcast for element mutations
- broadcastWithAck() waits for browser ACK before returning syncedToCanvas status
- sync_version: monotonic counter per project, stamped on every mutation
- Delta sync v2: POST /api/elements/sync/v2 for incremental sync with version tracking
- GET /api/sync/version endpoint
- Honest syncedToCanvas + canvasStatus in all mutation responses
- Fixed silent try/catch in tenant switch verification

**Frontend (App.tsx):**
- ACK sending after every updateScene() with element verification
- Delta sync v2 integration in syncToBackend()
- Gap detection: triggers resync when sync_version gaps are detected
- lastSyncVersion tracking via refs + localStorage persistence

**Tests (40 new tests, 168 total):**
- db.test.ts: +11 tests for sync_version CRUD, scoping, getChangesSince
- ws.test.ts: +8 tests for hello handshake, scoped broadcast, ACK model
- api.test.ts: +10 tests for sync/v2, sync/version, canvasStatus responses
- helpers.test.ts: +11 tests for isImageElement, normalizeImageElement, restoreBindings
- canvas.spec.ts: +8 e2e tests including full ACK pipeline verification
- Fixed stale tenant state bug in api.test.ts beforeEach

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 23:44:17 +05:30
63209f9d5a feat: add test suite, CI/CD pipeline, setup wizard, and upstream feature ports (#6)
Establish comprehensive quality infrastructure for a project that previously
had zero tests, enabling confident refactoring and community contributions
with automated guardrails. Port upstream enhancements for font normalization,
image element support, and arrow binding preservation.

🏗️ Testing infrastructure:
- Unit tests for SQLite persistence layer and element validation helpers
- Integration tests for REST API, WebSocket broadcast, and arrow binding
- E2E tests with Playwright for canvas rendering and real-time sync
- Vitest + Playwright configuration with proper isolation

👷 CI/CD pipeline:
- Auto-versioning from conventional commits on push to main
- Auto-publish to NPM and Docker Hub on GitHub release
- Matrix testing across Node 18/20/22 with pinned dependencies
- Docker health check with diagnostic logging on failure
- Preserve rollup status checks for branch protection gates

📦 Developer experience:
- Interactive setup wizard for first-time configuration
- Canvas clear confirmation and scene description tools
- Frontend helpers extracted for testability

🔧 Upstream feature ports:
- Font family normalization (string names to numeric IDs)
- Image element support with file management API
- Arrow binding preservation through server round-trips
- Vite config fix for font subsetting worker chunk names
- Idempotent database initialization for standalone Docker mode

🐛 Docker fixes:
- Set EXCALIDRAW_DB_PATH in both Dockerfiles to writable /app/data/
- Make initDb() idempotent and closeDb() reset-safe for test isolation

🎯 Provides the safety net needed for rapid iteration — every PR is
validated across 120 test cases before merge, and releases are fully
automated from commit to published package.

Co-authored-by: sanjibdevnathlabs <devnath.sanjib@gmail.com>
2026-03-13 12:08:07 +05:30
7143b5e41e feat: add SQLite persistence, multi-tenancy, auto-sync, and CI/Docker improvements (#1)
Replace in-memory storage with SQLite (WAL mode), add workspace-based
multi-tenancy with auto-detection via server.listRoots(), and embed the
canvas server into the MCP process for single-process operation.

🔧 Core enhancements:
- SQLite persistence with versioning, element history, and search
- Multi-tenancy: isolated canvases per workspace (SHA-256 tenant IDs)
- Embedded canvas lifecycle (single node process starts MCP + canvas)
- Auto-sync with 3s debounce and manual override toggle
- Configurable canvas port via CANVAS_PORT env var
- 6 new MCP tools (search, history, tenants, projects)
- Workspace switcher UI with dropdown search
- Sync normalization to prevent bound-text breakage on reload

🐳 Docker & CI improvements:
- BuildKit cache mounts for faster npm installs across builds
- Skip native compilation in frontend-builder stage (--ignore-scripts)
- Build only linux/amd64 on PRs, multi-arch on push to main
- Docker Hub registry with proper build tools for better-sqlite3
- CI and Docker status check gates (github/ci-status-check, github/docker-build-check)

📦 Package & publishing:
- Renamed to @sanjibdevnath/mcp-excalidraw-local (v3.0.0)
- Updated npm-publish workflow for scoped package
- Updated bin entry, keywords, and files list

📝 Documentation:
- README with UI screenshots, architecture diagram, and full feature docs
- Updated agent skill with 32-tool cheatsheet and workflow playbooks
- Fork attribution and upstream comparison table

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-19 10:17:29 +05:30
yctimlinandGitHub 4a17c47b54 Feat/canvas toolkit v2 (#41)
* feat: enhance Excalidraw MCP with advanced canvas toolkit features

- Rename skill to `excalidraw-skill` with expanded playbook and cheatsheet.
- Add new MCP tools for iterative refinement: `describe_scene` and `get_canvas_screenshot`.
- Implement layout tools (`align_elements`, `distribute_elements`) and `duplicate_elements`.
- Add file I/O support for `.excalidraw` JSON and image export (PNG/SVG).
- Introduce named snapshots for canvas state management.
- Add server-side element CRUD and WebSocket handlers for real-time sync.
- Normalize `points` format for arrows and lines.

* docs: update README with v2.0 features and official MCP comparison

* feat: implement arrow binding and edge-to-edge routing

* fix: enhance security with path sanitization and improve export error handling

* feat: add viewport control, design guide, and excalidraw.com URL export

* feat: enhance excalidraw.com export with proper scene formatting and labels
2026-02-12 18:09:56 +08:00
d73fa53cde Feat/excalidraw skill (#38)
* feat(skill): add excalidraw-mcp skill with export/import helpers

* fix(skill): correct url trailing-slash normalization in scripts

* feat(skill): add create/update/delete helpers and document CRUD test

* docs: restructure README and document skill usage

* docs: make README skill guidance tool-agnostic and SEO-friendly

* docs: add Claude Code skill installation instructions

* feat: Introduce skill creation tools and an agent-browser skill with templates and reference documentation.

* fix(frontend): keep server element ids for WS updates

Ensure WS delete/update events match scene element IDs by disabling ID regeneration when converting server payloads.

* feat: Add Zod library and OpenCode AI SDK dependencies, and introduce new Excalidraw skill scripts for element deletion and health checks.

* chore: Install project dependencies including Zod and OpenCode AI SDK, and add an Excalidraw reference cheatsheet.

---------

Co-authored-by: YC Lin <yclin@YCdeMacBook-Air.local>
2026-01-26 00:17:18 +08:00
YC Linandyctimlin 45af2758cf fix(frontend): point index.html at main.tsx 2026-01-25 01:09:31 +08:00
yctimlin 381bc98bff refactor: improve type safety in Mermaid integration
- Replace all `any` types with proper Excalidraw types
- Add proper type imports from @excalidraw/excalidraw
- Improve MermaidConversionResult interface with ExcalidrawElement[] and BinaryFiles
- Add mermaidDiagram and config fields to WebSocketMessage interface
- Remove unused ElementBinding interface
- Remove all `as any` type casts throughout App.tsx
- Fix Vite security vulnerability (1 of 6 moderate vulns)

Changes:
- frontend/src/App.tsx: Restored proper TypeScript types, removed 12+ `as any` casts
- frontend/src/utils/mermaidConverter.ts: Added proper return types
- package-lock.json: Updated vite to fix security issue

Remaining security issues:
- 5 moderate vulnerabilities from @excalidraw/mermaid-to-excalidraw dependencies
- These are upstream issues in dompurify, nanoid, and mermaid packages
- No fixes available without major version upgrades
- Risk is acceptable for this use case (diagram rendering)
2025-11-08 00:34:25 +08:00
francisco b8e2de76f1 feat: implement WebSocket-based Mermaid conversion with auto-sync
- Add WebSocket message handler for mermaid_convert type
- Make handleWebSocketMessage async to support conversion
- Add automatic backend sync after diagram generation
- Integrate convertMermaidToExcalidraw utility
- Remove test button and handleMermaidTest function
- Fix: Add missing Excalidraw CSS import for proper UI rendering
- Enhance server endpoint with WebSocket broadcast support
- Add mermaid_convert to WebSocketMessageType union
2025-11-01 13:58:23 -03:00
francisco dce247f4d6 fix: resolve TypeScript compilation errors in App.tsx and complete Mermaid test function 2025-11-01 13:58:22 -03:00
francisco f8c003db71 feat: add create_from_mermaid MCP tool and frontend integration with test button 2025-11-01 13:58:22 -03:00
francisco f8c0c85491 feat: add Mermaid to Excalidraw converter utility in frontend 2025-11-01 13:58:22 -03:00
yctimlin 5043a67385 Refactor project structure and enhance TypeScript support
- Updated package.json to point to compiled TypeScript files in the dist directory.
- Improved TypeScript configuration with stricter type checks and removed JavaScript support.
- Migrated frontend entry point to TypeScript and added a new App component with enhanced functionality.
- Implemented a new server structure with TypeScript, including WebSocket support and improved element management.
- Updated README to reflect changes in architecture and usage instructions.
- Added comprehensive type definitions for Excalidraw elements and server responses.
2025-08-20 15:31:42 +00:00
yctimlin a07a53c22a update logging messages 2025-08-07 16:11:22 +00:00
songmd b1f2aacfad fix: 优化元素处理逻辑,移除本地存储,直接通过HTTP服务器进行元素的创建、更新和删除操作。更新了前端与后端的同步机制,增强了错误处理和日志记录,确保操作的成功反馈。 2025-08-07 20:34:51 +08:00
songmd 60c8af9ca8 Fix MCP delete/update methods and add frontend sync functionality
- Fix MCP server update_element method parameter parsing issue
- Add comprehensive delete operation debugging and validation
- Implement frontend sync button with real-time status feedback
- Add elements sync API endpoint (/api/elements/sync) for manual synchronization
- Enhance WebSocket message handling with proper element validation
- Add binding validation and cleanup for Excalidraw elements
- Improve error handling and logging throughout the sync process
- Add sync status tracking and user feedback in the UI
2025-08-06 19:55:25 +08:00
yctimlin 86232d9c94 fix text label bugs 2025-07-12 09:01:51 +00:00
ycsahara 11309c731b Refactor project structure and update configurations
- Update .gitignore to include additional build artifacts, logs, and editor files
- Modify package.json scripts for improved development workflow and remove unused scripts
- Change Vite output directory to 'dist' for consistency
- Simplify App.jsx by removing unused state and functions, enhancing readability
- Adjust server.js to serve static files from the new 'dist' directory
2025-07-11 19:31:22 +00:00
ycsahara c5ba87db6e Simplify frontend UI and build system 2025-07-11 19:31:11 +00:00
ycsahara 1be9f3b47b Add frontend React app and server components
- Add React frontend with Excalidraw integration (App.jsx, main.jsx)
- Add Express server with MCP protocol support (server.js)
- Update CLI with new functionality (cli.js)
- Add Vite configuration for frontend build
- Update package.json with new dependencies
- Add public assets and build files
- Update .gitignore to exclude build artifacts
2025-07-11 17:49:07 +00:00