# Excalidraw Monorepo Brownfield Architecture Document ## Introduction This document captures the current, real-world state of the Excalidraw monorepo in this workspace. It is intentionally pragmatic: it highlights how the system is wired today, the trade-offs that exist, and the external services the app relies upon so that future contributors—human or AI—can work effectively without reverse‑engineering the project from scratch. ### Document Scope Comprehensive documentation of the entire repository (full brownfield analysis; no PRD scoping provided). ### Change Log | Date | Version | Description | Author | | ---------- | ------- | ----------------------------------- | ------- | | 2025-09-22 | 1.1 | Full repo sweep & accuracy refresh | Winston | | 2025-09-21 | 1.0 | Initial brownfield analysis | BMad Master | ## Quick Reference — Key Files and Entry Points - Monorepo root: `package.json`, `yarn.lock`, `package-lock.json` (Yarn workspaces with legacy npm lockfile still present). - Web app entry: `excalidraw-app/index.tsx`, `excalidraw-app/App.tsx`, `excalidraw-app/index.html`. - Core editor package: `packages/excalidraw/index.tsx`, `packages/excalidraw/components/*`, `packages/excalidraw/scene/*`. - Build config: `excalidraw-app/vite.config.mts`, root `vitest.config.mts`, `scripts/buildPackage.js` (esbuild bundler for packages). - Env baselines: `.env.development`, `.env.production`, plus optional `.env.local` overlays. - Tests setup: `setupTests.ts`, `vitest.config.mts`. - Docker delivery: `Dockerfile`, `docker-compose.yml`. - Deployment settings: root `vercel.json`, `public/_headers`. - External rules: `firebase-project/*` (Firestore + Storage rules for libraries/collab). ### Environment Profiles | Mode | Source file | Notable Overrides | | ------- | ------------------- | ----------------- | | Dev | `.env.development` | Local WS server, AI backend `http://localhost:3015`, plus exports to local Plus host. | | Prod | `.env.production` | OSS production endpoints, Excalidraw Plus host, AI SaaS backend, enforced lint/PWA defaults. | | Docker | `Dockerfile` args | `VITE_APP_DISABLE_SENTRY=true`, build into nginx static image. | | CI | GitHub Actions YAML | Runs `yarn test:all`, release, docker, Sentry release, Crowdin sync. | ## High Level Architecture ### Technical Summary - **Monorepo** using Yarn v1 workspaces (`excalidraw-app`, `packages/*`, `examples/*`, `dev-docs`). - **Frontend**: React 19 (runtime) + TypeScript 4.9; state via custom Jotai store (`excalidraw-app/app-jotai.ts`). - **Bundling**: Vite 5.x for `excalidraw-app`; esbuild for package builds; custom font pipeline. - **Collaboration**: Socket.IO client with custom Portal, backed by Firebase RTDB/Storage & `VITE_APP_WS_SERVER_URL` collab server. - **Persistence**: LocalStorage/IndexedDB for offline; Firebase storage for binary files; `VITE_APP_BACKEND_V2_*` REST endpoints for share links. - **AI Add-ons**: Optional Diagram-to-Code & Text-to-Diagram flows via `VITE_APP_AI_BACKEND` with hard rate limiting. - **Telemetry**: Sentry browser integration gated by env; selective analytics via `packages/excalidraw/analytics.ts`. - **Docs**: Docusaurus site in `dev-docs`; run independently on port 3003. ### Actual Tech Stack (from manifests) | Category | Technology / Version | Notes | | --------------- | ---------------------------------------- | ----- | | Runtime | Node.js 18 – 22 | Enforced via `engines`. | | Framework | React 19.0.0 | Editor + app; types pinned to 19 as well. | | Language | TypeScript 4.9.4 | Shared across packages (lagging behind React 19 features). | | Bundler (app) | Vite 5.0.12 + `@vitejs/plugin-react` | Custom aliases map to package sources. | | Bundler (pkgs) | esbuild + `esbuild-sass-plugin` | `scripts/buildPackage.js`. | | State | Jotai 2.11 (custom store) | `app-jotai.ts` wraps primitives. | | Testing | Vitest 3.0.6 + jsdom 22 | Coverage thresholds enforced (60/63/70). | | Lint/Format | ESLint (`@excalidraw/eslint-config`), Prettier 2.6 | CLI scripts `test:code`, `test:other`. | | Styling | SCSS, CSS modules, custom fonts (Virgil, Cascadia, Assistant). | | Collaboration | Socket.IO client 4.7, Firebase 11.3 | External collab server + GCP Storage. | | Build Artifacts | Docker (nginx 1.27) | `Dockerfile` builds static site. | | Deployment | Vercel routes (`vercel.json`), GitHub Actions | Sentry release, docker publish. | ### Repository Structure Reality Check ```text excalidraw/ ├─ excalidraw-app/ # Vite-powered OSS app shell and integrations │ ├─ components/ # UI surface, menus, dialogs, AI hooks │ ├─ collab/ # Portal + Socket.IO + Firebase glue │ ├─ data/ # Share-link API wrappers, storage adapters │ ├─ app-jotai.ts # Central Jotai store export │ ├─ App.tsx # Composes editor + integrations │ ├─ vite.config.mts # Alias map back into packages/* │ └─ index.html # EJS template, theme bootstrap, meta ├─ packages/ │ ├─ excalidraw/ # Published editor package (@excalidraw/excalidraw) │ │ ├─ components/, scene/, renderer/, data/, hooks/, tests/ │ │ ├─ analytics.ts, workers.ts, polyfill.ts │ │ └─ index.tsx, index-node.ts │ ├─ element/ # Geometry + binding logic │ ├─ common/ # Shared constants, utilities, event emitters │ ├─ math/ # Vector & matrix helpers │ └─ utils/ # Canvas helpers, bbox, visual debug ├─ examples/ │ ├─ with-nextjs/ # App Router integration example │ └─ with-script-in-browser/ # Script-tag embedding demo ├─ dev-docs/ # Docusaurus developer documentation site ├─ docs/architecture/ # Brownfield + standards docs ├─ firebase-project/ # Firestore/Storage rules used by the live app ├─ scripts/ # Build/release tooling, font converters, locales ├─ public/ # Static assets, fonts, legacy SW killer ├─ Dockerfile, docker-compose.yml ├─ vitest.config.mts, setupTests.ts └─ .github/workflows/ # CI definitions ``` ### Workspace Overview | Workspace | Purpose | | ------------------- | ------------------------------------------ | | `excalidraw-app` | OSS web experience & integration playground | | `packages/common` | Shared constants, colors, emitters | | `packages/element` | Shape modeling & delta math | | `packages/excalidraw` | Public React editor package + plugins | | `packages/math` | Geometry helpers (vectors, curves, intersections) | | `packages/utils` | Canvas/shape utilities, debug overlays | | `examples/*` | Integration samples (Next.js, vanilla) | | `dev-docs` | Developer docs (Docusaurus) | ## Source Tree and Module Organization ### `excalidraw-app` (OSS web app shell) - **Purpose**: Hosts the public Excalidraw experience, wires the core editor with collaboration, AI, sharing, and Plus upsell flows. - **State management**: `app-jotai.ts` exports a preconfigured Jotai store; helpers like `useAtomWithInitialValue` wrap default hydration for atoms. - **Composition** (`App.tsx`): - Imports bulk of `@excalidraw/excalidraw` components, `CommandPalette`, share dialogs, etc. - Mounts `Collab` Portal, file manager, Share dialog, AI plugin, Excalidraw Plus iframe export. - Handles theme bootstrapping, PWA install prompt, analytics gating (`trackEvent`). - **Collaboration** (`collab/`): - `Collab.tsx` manages Socket.IO lifecycle, Firebase uploads, room metadata, idle states, pointer broadcasts; expects `VITE_APP_WS_SERVER_URL` & Firebase config. - `Portal.tsx` coordinates broadcast vs local render, replicating CRA patterns. - `CollabError.tsx` surfaces connectivity & persistence issues via Jotai atoms. - **Data layer** (`data/`): - `index.ts`: share link encode/decode, REST calls to `VITE_APP_BACKEND_V2_*`, encryption helpers, random room ID generation. - `LocalData.ts`: IndexedDB adapter for library items; gracefully migrates old LocalStorage via `LibraryLocalStorageMigrationAdapter`. - `FileManager.ts`: Encodes binary files (images) for Firebase storage and ensures TTL for deleted files. - `tabSync.ts`: Cross-tab consistency; warns when another tab has fresher data. - **AI features** (`components/AI.tsx`): - Wraps `DiagramToCodePlugin` and `TTDDialog` from the editor package. - Hits `VITE_APP_AI_BACKEND` endpoints with strict rate limit handling (HTTP 429 => friendly HTML error + Plus upsell). - **Configuration**: - `vite.config.mts` sets up aliasing back into package source directories, configures fonts chunking, Workbox PWA caching, ESLint overlay toggles, WOFF2 relocation plugin, and sitemap generation. - `index.html` uses EJS placeholders to inject PROD font preload vs dev asset path fallback, handles dark mode preflight, and cookie-based redirects to Excalidraw Plus. - `.env.*` lists all required `VITE_APP_*` flags controlling PWA, lint overlay, overlays, Firebase, AI, ws server, tracking. - **Sentry** (`sentry.ts`): environment detection by hostname, sanitized console instrumentation, release annotation via `VITE_APP_GIT_SHA`. - **Fonts**: `public/Assistant-Regular.woff2`, `Virgil.woff2`, `Cascadia.woff2` served with custom headers and cached long-term. - **Custom stats/debug**: `CustomStats.tsx`, `components/DebugCanvas`, `isVisualDebuggerEnabled` toggled via local storage. ### `packages/excalidraw` (published editor) - **Exports**: `Excalidraw` React component, imperative API types, `DiagramToCodePlugin`, `TTDDialog`, `LiveCollaborationTrigger`, `exportToBlob`, etc. - **Structure**: - `components/`: core UI (toolbars, dialogs, command palette, stats, library, context menu). - `scene/`: rendering pipeline, canvas layers, export helpers (`scene/export.ts`), scrollbars, zoom management. - `renderer/`: canvas primitives, `roundRect`, background tiling, frame rendering, pointer overlay. - `data/`: serialization/deserialization (`restore.ts`), encryption, blob helpers, library sync & merge strategies (`data/library.ts`). - `hooks/`: internal hooks for selection, pointer, library, keyboard. - `workers.ts`: pooled web worker manager with TTL; throws explicit `WorkerInTheMainChunkError` if bundler inlines workers by mistake. - `analytics.ts`: extremely restrictive tracking (only whitelisted categories) to avoid privacy issues. - `polyfill.ts`: ensures missing DOM APIs (Intl, PointerEvent) exist in environments (used both in tests and runtime). - `tests/`: Vitest suites for charts, clipboard, mermaid import, etc., using `vitest-canvas-mock` / fake IndexedDB. - `index-node.ts`: Node script showcasing headless export via `canvas` bindings (registering Virgil/Cascadia fonts) — used for docs automation. - **Build artifacts**: `dist/dev` and `dist/prod` output ESM bundles, CSS, type declarations; exports map ensures type resolution for sub-path imports. - **Dependencies**: Jotai (mirrored from app), Radix UI (popover/tabs), `perfect-freehand`, `roughjs`, `fractional-indexing`, `@excalidraw/laser-pointer`, etc. - **Technical quirks**: - React peer dependency declared for 17/18/19; ensures host apps remain in control. - `env.cjs` used by `buildPackage.js` to inject `.env` values into bundles. ### `packages/element`, `packages/common`, `packages/math`, `packages/utils` - **common**: constants (colors, themes, stats panels), `Emitter`, queue, promise pool, throttle/debounce wrappers, pointer utilities, environment detection. - **element**: shape definitions, binding logic, history diffs, arrow editing, delta calculations, lasso, lasers, frames, WYSIWYG integration; exports reused by tests and plugin authors. - **math**: low-level vector math, intersection algorithms, geometry utilities supporting snapping/frames. - **utils**: bounding box calculations, export helpers, debug draws, shape utilities used by renderer and tests. ### `examples` - `with-nextjs`: demonstrates embedding the editor in Next.js App Router; includes dynamic import patterns and custom asset path configuration. - `with-script-in-browser`: minimal CDN script tag usage; used for manual testing and docs. - Scripts expect `yarn build:packages` prior to running to ensure compiled artifacts exist. ### `dev-docs` - Docusaurus site for contributor docs; uses the published `@excalidraw/excalidraw` package directly. - Commands: `yarn --cwd dev-docs start`, `yarn build` for static output, `yarn typecheck` with dedicated TS config. - Deployed separately (Vercel config lives within this workspace). ### `firebase-project` - `firebase.json`, `firestore.rules`, `storage.rules`, `firestore.indexes.json` govern OSS Firebase project (libraries & collab rooms). - Storage prefixes align with `FIREBASE_STORAGE_PREFIXES` in app constants. - No emulators provided; local dev relies on remote dev project credentials embedded in `.env.development`. ### `scripts` - `buildPackage.js`: esbuild driver; bundles dev/prod ESM output, handles Sass, injects env variables, writes chunked bundles. - `release.js`: interactive multi-package release (test/next/latest tags), updates package versions, rebuilds packages, optionally commits & publishes to npm. - `build-locales-coverage.js`, `locales-coverage-description.js`: translation health metrics (Crowdin integration). - `build-node.js`, `build-version.js`: orchestrate app build metadata (Git SHA) and distribution version stamping. - `woff2/` utilities: transform font assets for Web. ### Other notable areas - `public/service-worker.js`: “self-destruct” service worker to retire old CRA installs when migrating to Vite; safe to remove once adoption confirmed. - `public/_headers`: CORS & cache rules for fonts (Excalidraw’s CDN expects permissive font access). - `.bmad-core/`: project governance for Codex CLI — do not alter without regeneration. - `node_modules/`: currently present in workspace (not checked into git by default but can inflate AI context; treat as generated). ## Data Models and Persistence ### Core Runtime Types - `ExcalidrawElement` (and `OrderedExcalidrawElement`): canonical shape model (id, versioning, roughness, seeds, z-order). Stored in exported `.excalidraw` JSON and broadcast over collaboration. - `AppState`: large shape describing editor UI state (tool selection, theme, zoom, frames, binding toggles). `getDefaultAppState()` seeds defaults (note: `currentItemRoundness` forced `"round"` outside tests). - `BinaryFileData`: metadata for embedded images/files; stored separately and referenced by `FileId`. - `LibraryItems`: array of reusable element groups persisted via IndexedDB + optional remote sources. ### Client Storage & Sync - **LocalStorage keys** (`STORAGE_KEYS` in `app_constants.ts`): interactive state, offline scenes, theme, debug toggles; version keys guard migrations. - **IndexedDB**: `LibraryIndexedDBAdapter` stores library items; migrations fall back to LocalStorage for legacy data. - **Cross-tab**: `tabSync.ts` compares version stamps to avoid silent clobbering when multiple tabs are open. ### Remote Persistence - **Share Link Backend (`json.excalidraw.com`)**: - GET `VITE_APP_BACKEND_V2_GET_URL`: fetch scene by share code. - POST `VITE_APP_BACKEND_V2_POST_URL`: upload encrypted scene; uses `compressData` + AES-GCM (`encryptData`). - **Firebase**: - Storage buckets store binary files per room/share (`files/rooms/`, `files/shareLinks/`). - `saveFilesToFirebase` batches uploads after filtering duplicates; rate limited via `FILE_UPLOAD_MAX_BYTES` (4MiB) and TTL for deleted records. - **Collaboration server**: - Socket.IO namespace provides `WS_EVENTS`/`WS_SUBTYPES` channels for scene init, incremental updates, cursor positions, idle status, viewport bounds, and user follow. - Encryption key exchanged via URL hash; enforcement done client-side (`RE_COLLAB_LINK`). - **Libraries API**: - Public library metadata fetched from `https://libraries.excalidraw.com` and associated Cloud Function backend. - `ALLOWED_LIBRARY_URLS` restricts remote imports for security. ### AI Integrations - Diagram-to-code: sends image (JPEG dataURL) + text to `/v1/ai/diagram-to-code/generate`; expects HTML snippet back. - Text-to-diagram: posts prompt to `/v1/ai/text-to-diagram/generate`; returns `generatedResponse` plus rate limit headers. - Error handling returns HTML for 429 to display inside plugin iframe. ### Telemetry & Observability - `analytics.ts` only allows `command_palette` and `export` categories; respects `VITE_APP_ENABLE_TRACKING` and dev/test environments. - Sentry config ignores known browser noise (IndexedDB closing, SW fetch failures, quota errors) and rewrites console errors with stack traces. - Debug canvases and custom stats accessible through UI toggles; test harness logs `act()` misuse in yellow for easier triage. ### Internationalization - Translation catalog: `packages/excalidraw/locales/*.json` (Crowdin pipeline configured via `crowdin.yml`). - `app-language/` handles detection (`language-detector` using `i18next-browser-languagedetector`), state atoms, and runtime toggles. ### Node/Server Usage - `packages/excalidraw/index-node.ts` demonstrates headless rendering by bundling `canvas` and fonts; useful for PDF/image exports in server contexts. ## Build, Tooling, and Developer Workflow ### Core Commands | Command | Description | | ------- | ----------- | | `yarn install` | Installs workspace dependencies (respects `resolutions`). | | `yarn start` | Starts Vite dev server on `VITE_APP_PORT` (defaults 3000). | | `yarn build:packages` | Builds `@excalidraw/{common,math,element,excalidraw}` via esbuild. | | `yarn build` | Builds `excalidraw-app` (depends on built packages) and version metadata. | | `yarn test` / `yarn test:app` | Runs Vitest with jsdom. | | `yarn test:all` | `tsc` + ESLint + Prettier check + Vitest (CI default). | | `yarn fix` | Prettier write + ESLint `--fix`. | | `yarn build:app:docker` | Vite production build with Sentry disabled (for Dockerfile). | | `yarn release[:test|:next|:latest]` | Runs release pipeline; manages versioning & publishing. | | `docker compose up` | Builds nginx image from `Dockerfile`, serves built app on host `3000`. | | `yarn --cwd dev-docs start` | Serve Docusaurus docs on port 3003. | ### Testing & Quality - **Vitest**: jsdom environment, `setupTests.ts` loads canvas mock, fake IndexedDB, fonts, reroutes `setPointerCapture`, adds matchMedia stub. - **Coverage thresholds**: lines ≥60%, branches ≥70%, functions ≥63% (enforced in config; failing thresholds fail CI). - **Linting**: `yarn test:code` uses ESLint with custom config; `yarn test:other` ensures formatting via Prettier. - **Type safety**: `yarn test:typecheck` runs `tsc` in build mode across workspaces; pinned to TS 4.9 (React 19 inference gaps exist). - **Unit focus**: heavy emphasis on deterministic snapshot tests around elements, clipboard, mermaid import; integration/E2E tests absent. ### Build & Release Flow 1. `yarn build:packages` (esbuild) produces `dist/dev|prod` bundles with inlined env definitions. 2. `yarn build` triggers Vite build with Workbox PWA, fonts relocation, sitemap rewrite. 3. `scripts/build-version.js` writes git SHA to `excalidraw-app/build/version.json` & populates `window.__EXCALIDRAW_SHA__`. 4. Docker image built from multi-stage `Dockerfile` (node builder → nginx static). 5. `vercel.json` controls headers, redirects, and output directory for hosting (Excalidraw uses Vercel for OSS site). 6. Release process: `yarn release --tag= [--version=x.y.z]` updates package versions, rebuilds, optionally publishes to npm and commits with 🎉 message; manual prompts remain (tech debt for automation). ### Developer Ergonomics - `VITE_APP_ENABLE_ESLINT` toggles dev overlay; disable if overlay is noisy. - `VITE_APP_DEV_DISABLE_LIVE_RELOAD` modifies WebSocket constructor to silence HMR — critical when debugging service workers. - `VITE_APP_ENABLE_PWA` enables Workbox precaching for local testing (disabled by default). - `VITE_APP_COLLAPSE_OVERLAY` controls Vite overlay collapsed state (useful with multi-agent workflows). - Font bundling: Workbox deliberately omits locale chunks & fonts to rely on CDN caching; manual chunk naming ensures translation JS loads lazily. ### Documentation Tooling - Docusaurus uses older React 18 & `@excalidraw/excalidraw@0.18.0`; keep in sync when bumping core package to avoid breakage. - `yarn --cwd dev-docs write-translations` integrates with Crowdin for docs localization. ## Technical Debt, Risks, and Gotchas - **Dual lockfiles**: `package-lock.json` lingers alongside Yarn; avoid `npm install` to prevent divergence. - **TypeScript version**: 4.9 lacks latest JSX transforms; React 19 features may require manual typing or upgrade plan. - **Node_modules footprint**: directory currently present (likely untracked) — ensure CI clean installs. - **Workers & bundlers**: external consumers must ensure worker files remain separate; `WorkerInTheMainChunkError` surfaces if bundlers inline them (not obvious until runtime). - **External service reliance**: Collaboration requires running `excalidraw-room` server + Firebase credentials; without them, collab buttons fail silently except for toast. - **AI backend**: Hard-coded rate limits; endpoints unreachable in offline dev unless local backend (3015) provided, causing plugin UI errors. - **Legacy service worker**: `public/service-worker.js` only unregisters CRA workers. Removing prematurely reintroduces white-screen issues for old caches. - **Release automation**: manual prompts for publishing/committing; automating or documenting CLI usage is essential to avoid half-published versions. - **Fonts pipeline**: WOFF2 names assume certain hyphenation; adding new fonts requires updating `vercel.json` headers + `public/_headers` to maintain CORS. - **Env sprawl**: dozens of `VITE_APP_*` toggles; missing any yields runtime errors (Sentry, overlays, collab). Use `.env.example` (not provided) or replicate `.env.development`. ## Integration Points and External Services | Service / Endpoint | Purpose | Configuration | Integration Notes | | ------------------ | ------- | ------------- | ----------------- | | `VITE_APP_WS_SERVER_URL` (Socket.IO) | Real-time collaboration | `.env.*` | Requires external `excalidraw-room` server; handles `SCENE_*`, cursor, idle updates. | | `VITE_APP_BACKEND_V2_*` (json.excalidraw.com) | Shareable scene persistence | `.env.*` | AES-encrypted payloads; failure surfaces via `ShareableLinkDialog`. | | Firebase (Firestore & Storage) | Library sync + binary file storage | `.env.*` + `firebase-project` rules | `firebase` SDK 11.3; uses Storage JSON config for dev/prod. | | `VITE_APP_LIBRARY_URL` / Cloud Functions | Public shape libraries | `.env.*` | Controlled via whitelist; merges using `mergeLibraryItems`. | | `VITE_APP_AI_BACKEND` | Diagram-to-code & text-to-diagram | `.env.*` | Optional; rate limits 429; returns HTML/JSON. | | Sentry (`@sentry/browser`) | Error reporting | `sentry.ts` | Disabled in dev & Docker builds; sanitized console errors. | | `@excalidraw/random-username` | Anonymous usernames | autop-run | Used in collab; ensures deterministic collaborator names. | | Crowdin (`crowdin.yml`) | i18n pipeline | root config | Maps `en.json` → `%locale%.json` for translations. | | Excalidraw Plus (links & exports) | Upsell & export integration | `VITE_APP_PLUS_*` | Buttons export to Plus; `ExcalidrawPlusIframeExport` handles iframe handshake. | ## Development & Deployment Notes - **Asset Hosting**: Fonts relocated into `/fonts//` with Workbox caching rules; `vercel.json` ensures proper CORS & caching for fonts and WOFF2. - **PWA**: `vite-plugin-pwa` configured to ignore locale chunks; runtime caching for fonts, locales, chunk JS. PWA disabled in dev unless `VITE_APP_ENABLE_PWA=true`. - **Theme handling**: `index.html` inlines theme bootstrap script to avoid white flash; theme stored in LocalStorage, respects “system” option. - **AI plugin UI**: Renders inside plugin panel; errors returned as HTML are directly displayed — ensure backend HTML escapes content. - **Docker**: Compose mounts repository into `/opt/node_app/app` with delegated volume but intentionally mounts `node_modules` to a named volume (`notused`) to avoid host conflict; run `yarn build:app:docker` prior to compose. - **Docs**: `dev-docs` not part of main build; deploy separately (Vercel project expects static output in `dev-docs/build`). ## Testing Reality & Observability - Unit coverage moderate; integration with external services largely unmocked (Firebase interactions bypassed in tests with fakes or `AbortError`). - `DebugCanvas` + `visualdebug.ts` support runtime visual debugging of hit-tests and bounding boxes (toggle via local storage or query params). - `setupTests.ts` intercepts `console.error` to highlight missing `act()` usage, preventing noisy logs in Vitest runs. - Worker pool extensively unit-tested; ensure tests trigger `WorkerInTheMainChunkError` when bundler misconfigured. - No automated end-to-end tests; manual validation relies on OSS community and Plus product pipeline. ## Useful Commands & Scripts (Appendix) ```bash # Install dependencies (clean) yarn clean-install # Build everything yarn build:packages && yarn build # Start dev server on custom port yarn start -- --port 4000 # Run selective test suites yarn test --run Tests/components.test.tsx # Launch docs site yarn --cwd dev-docs start # Build Docker image DOCKER_BUILDKIT=1 docker build -t excalidraw:oss . # Run locales coverage report node scripts/build-locales-coverage.js # Publish prerelease (interactive) yarn release --tag=next --non-interactive ``` ## Appendix — Reference Documents - Coding standards: `docs/architecture/coding-standards.md` - Tech stack primer: `docs/architecture/tech-stack.md` - Source tree guidance: `docs/architecture/source-tree.md` - Firestore/Storage rules: `firebase-project/*` - BMAD agent configuration: `.bmad-core/`