Skip to content

feat: add boards drawn with Excalidraw - #76

Merged
AmrMsCLL merged 4 commits into
mainfrom
feat/boards
Oct 8, 2026
Merged

AmrMsCLL merged 4 commits into
mainfrom
feat/boards

Conversation

@AmrMsCLL

@AmrMsCLL AmrMsCLL commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Boards, step B1 from .claude/.Plans/as2026-10-07-strata-boards-and-notion-notes.md: a whiteboard page type drawn with Excalidraw 0.18.1 (MIT) on a white canvas, synced through the existing Hocuspocus server.

How it fits

  • A board is an item of the existing BOARD kind with a notes row, so it sits in the page tree, opens at /notes/:id, and gets permissions, pinning, comments, backlinks, search and version history like a page. POST /spaces/:id/notes takes board: true; responses carry kind. Boards can't be templates, databases or hold pages.
  • Elements live in a board Y.Map (element id → element) in the same Yjs document notes use, so offline drafts (y-indexeddb), presence and size limits work unchanged. Local changes are written every 80 ms; remote ones are merged with Excalidraw's reconcileElements and applied with CaptureUpdateAction.NEVER, so undo only touches your own work.
  • Images upload through /spaces/:id/files (generateIdForFile) and load back by file id. Board text boxes feed search, and board images become attachment links.
  • Restoring a version also restores the board, bumping element versions so open clients take the restored copy.
  • The connection and status code moved from NoteEditor into components/live-document.ts, shared by both.

Build and bundle

  • Excalidraw's fonts are served from /excalidraw/fonts (a small Vite plugin serves them in dev and copies them into the build), because the CSP only allows same-origin fonts.
  • The service worker now precaches only chunks the app can reach (entry, its imports, our own lazy pages), not Excalidraw's internal lazy chunks such as the Mermaid renderers. Precache goes from 1.2 MB to 2.4 MB; without this it would have been about 9 MB.
  • Excalidraw's bundled @radix-ui/react-tabs only declares React 18, which made npm hoist a second React 18 to the workspace root and broke react-router. The root package.json now declares React 19.3.0 with overrides, so the workspace has one React.

Checked in the browser (local stack)

  • The board renders on a white canvas with no CSP violations, and shows "Saved" once connected.
  • A pencil stroke drawn in the browser reached Postgres as a freedraw element; an element added by a second client appeared on the open board; both were still there after a reload.
  • A click with a shape tool that draws nothing no longer leaves a zero-size element behind (fixed here: invisible elements are skipped, as Excalidraw's own collaboration does).
  • Not checked: image upload on a board, offline drawing, and two people's live cursors on screen.
  • npm audit reports 14 advisories that come with Excalidraw (browser bundle only): nanoid 3.3.3, sass/chokidar/braces (build tools listed as runtime dependencies, never run in the browser), lodash-es and Mermaid's parser chain.

Tests: test/document-text.spec.ts, frontend test/notes.spec.tsx and test/journal.spec.tsx, lint and both builds locally. The new board case in test/integration/notes.spec.ts runs in CI.

@github-actions github-actions Bot added the size/xl Over 600 changed lines, excluding lockfiles label Oct 8, 2026
@AmrMsCLL
AmrMsCLL merged commit a718cba into main Oct 8, 2026
7 checks passed
@AmrMsCLL
AmrMsCLL deleted the feat/boards branch October 8, 2026 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl Over 600 changed lines, excluding lockfiles

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant