# Feature catalog — excalidraw/excalidraw

> Canonical page: https://codevetter.com/unpack/excalidraw/feature-catalog

# Feature catalog — excalidraw/excalidraw

Scanned commit 31df3e6ef245c646b18a055ccf858cd6117c7768 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The editor is a tool-driven canvas plus a large ActionName command set (clipboard, z-order, align, frames, text binding, zoom, theme, export). The host app layers collaboration rooms, encrypted share links, local autosave, PWA install, Excalidraw+ chrome, and two AI surfaces (text-to-diagram and diagram-to-code). Embedders get the same canvas through props, the imperative API, and the Next.js and browser-script examples.
- Pointer dispatch in handleCanvasPointerDown branches on activeTool.type: text, arrow/line, freedraw, custom, frame/magicframe, laser, autoshape, bucketfill, eraser, and a generic creator for rectangle-like tools. Element types include rectangle, diamond, ellipse, stickynote (baseHeight), embeddable, plus linear, image, text, and frame types in packages/element/src/types.ts. — [packages/excalidraw/components/App.tsx#L8927-9019](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/App.tsx#L8927-L9019) [packages/element/src/types.ts#L40-118](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/element/src/types.ts#L40-L118)
- ActionName enumerates the command surface: copy/cut/paste, copyAsPng/copyAsSvg, z-index, align and distribute, flip, group, undo/redo, font and stroke properties, grid/zen/view/stats modes, hyperlink, cropEditor, frame membership, lock, linear editor, searchMenu, and commandPalette. Each action module calls register() so the side-effect import in App.tsx fills the actions array before ActionManager.registerAll. — [packages/excalidraw/actions/types.ts#L45-144](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/actions/types.ts#L45-L144) [packages/excalidraw/actions/register.ts#L1-15](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/actions/register.ts#L1-L15) [packages/excalidraw/actions/actionDeleteSelected.tsx#L208](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/actions/actionDeleteSelected.tsx#L208) [packages/excalidraw/components/App.tsx#L301-348](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/App.tsx#L301-L348)
- History is delta-based. Store emits durable increments for CaptureUpdateAction.IMMEDIATELY, never records NEVER (remote updates and init), and defers EVENTUALLY. History.record consumes those deltas; undo/redo are actions created with createUndoAction/createRedoAction and registered beside the static action list. History deltas deliberately drop version and versionNonce so a local undo still looks like a new collab edit. — [packages/element/src/store.ts#L38-69](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/element/src/store.ts#L38-L69) [packages/excalidraw/history.ts#L15-96](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/history.ts#L15-L96) [packages/excalidraw/components/App.tsx#L941-943](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/App.tsx#L941-L943) [packages/excalidraw/components/App.tsx#L3848-3850](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/App.tsx#L3848-L3850)
- Export to disk uses serializeAsJSON, which writes type excalidraw, VERSIONS.excalidraw (2), source, elements, and appState. type local keeps files (minus those only referenced by deleted elements); type database sets files undefined so blobs are stored elsewhere. saveAsJSON uses the File System Access wrappers in data/filesystem.ts (browser-fs-access). PNG/SVG/clipboard exports are re-exported from @excalidraw/utils/export. — [packages/excalidraw/data/json.ts#L52-90](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/data/json.ts#L52-L90) [packages/common/src/constants.ts#L397-402](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/common/src/constants.ts#L397-L402) [packages/excalidraw/data/filesystem.ts#L1-39](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/data/filesystem.ts#L1-L39) [packages/utils/src/export.ts#L1-18](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/utils/src/export.ts#L1-L18) [dev-docs/docs/codebase/json-schema.mdx#L1-20](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/dev-docs/docs/codebase/json-schema.mdx#L1-L20)
- Shape libraries persist through LibraryPersistenceAdapter (load/save). The app implements LibraryIndexedDBAdapter (idb-keyval store excalidraw-library) and LibraryLocalStorageMigrationAdapter for the legacy localStorage key. Remote library installs are restricted to hostnames excalidraw.com and raw.githubusercontent.com/excalidraw/excalidraw-libraries. — [packages/excalidraw/data/library.ts#L54-95](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/data/library.ts#L54-L95) [excalidraw-app/data/LocalData.ts#L229-277](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/data/LocalData.ts#L229-L277)
- i18n defaults to en from packages/excalidraw/locales/en.json. A locale is listed only if Crowdin coverage meets COMPLETION_THRESHOLD 85 (percentages.json). RTL is flagged for ar-SA, fa-IR, and he-IL. Crowdin syncs en.json to locales/%locale%.json. Vite manualChunks splits non-English locale JSON so the PWA precache can cache them separately. — [packages/excalidraw/i18n.ts#L1-40](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/i18n.ts#L1-L40) [crowdin.yml#L1-2](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/crowdin.yml#L1-L2) [excalidraw-app/vite.config.mts#L106-118](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/vite.config.mts#L106-L118)
- Live collaboration is app-only. ShareDialog calls collabAPI.startCollaboration(null) to create a room or stopCollaboration to leave. Links match /^#room=([a-zA-Z0-9_-]+),([a-zA-Z0-9_-]+)$/ and the key must be 22 characters or the UI alerts invalidEncryptionKey. The socket emits join-room and broadcasts SCENE_INIT, SCENE_UPDATE, MOUSE_LOCATION, IDLE_STATUS, and USER_VISIBLE_SCENE_BOUNDS. — [excalidraw-app/share/ShareDialog.tsx#L186-204](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/share/ShareDialog.tsx#L186-L204) [excalidraw-app/data/index.ts#L131-164](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/data/index.ts#L131-L164) [excalidraw-app/app_constants.ts#L16-30](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/app_constants.ts#L16-L30) [excalidraw-app/collab/Portal.tsx#L37-61](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/collab/Portal.tsx#L37-L61)
- Readonly share links are a different hash: #json=<id>,<key>. exportToBackend generates an AES key, compresses serializeAsJSON(..., 'database'), POSTs the bytes to VITE_APP_BACKEND_V2_POST_URL, then writes the key only into location.hash. Image payloads are encrypted and uploaded under /files/shareLinks/${id} with a 4 MiB cap (FILE_UPLOAD_MAX_BYTES). — [excalidraw-app/data/index.ts#L248-306](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/data/index.ts#L248-L306) [excalidraw-app/app_constants.ts#L11-35](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/app_constants.ts#L11-L35) [excalidraw-app/App.tsx#L228-281](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/App.tsx#L228-L281)
- Text-to-diagram lives in packages/excalidraw/components/TTDDialog. useTextGeneration accepts prompts of 3–10000 characters, streams via an AbortController, and parses mermaid with @excalidraw/mermaid-to-excalidraw. The host wires TTDIndexedDBAdapter (IDB key excalidraw-ttd-chats). Paste detection isMaybeMermaidDefinition recognizes flowchart, sequenceDiagram, C4Context, mindmap, and other mermaid headers. — [packages/excalidraw/components/TTDDialog/hooks/useTextGeneration.ts#L23-99](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/TTDDialog/hooks/useTextGeneration.ts#L23-L99) [packages/excalidraw/mermaid.ts#L1-32](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/mermaid.ts#L1-L32) [excalidraw-app/app_constants.ts#L49](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/app_constants.ts#L49) [excalidraw-app/components/AI.tsx#L1-18](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/components/AI.tsx#L1-L18)
- Diagram-to-code is a host plugin. DiagramToCodePlugin calls app.setPlugins({ diagramToCode }). AIComponents exports the selected frame to JPEG, collects text with getTextFromElements, and POSTs {texts, image, theme} to ${VITE_APP_AI_BACKEND}/v1/ai/diagram-to-code/generate-streaming, parsing the SSE body and treating HTTP 429 as a rate limit. — [packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx#L1-19](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx#L1-L19) [excalidraw-app/components/AI.tsx#L19-80](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/components/AI.tsx#L19-L80)
- Charts (bar, line, radar) are a paste path under packages/excalidraw/charts. Command palette UI is packages/excalidraw/components/CommandPalette/CommandPalette.tsx (fuzzy match over actions); defaultCommandPaletteItems.ts is an empty module. Analytics trackEvent only emits categories command_palette, export, and ai, and only when VITE_APP_ENABLE_TRACKING is the string true and window.sa_event exists. — [packages/element/src/types.ts#L18](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/element/src/types.ts#L18) [packages/excalidraw/components/CommandPalette/CommandPalette.tsx#L1-39](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/CommandPalette/CommandPalette.tsx#L1-L39) [packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts#L1](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts#L1) [packages/excalidraw/analytics.ts#L6-40](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/analytics.ts#L6-L40)
- The hosted shell adds AppMainMenu, AppWelcomeScreen, AppSidebar, ShareDialog plus QR (uqr), language picker, Excalidraw+ promo and iframe export (VITE_APP_PLUS_APP / VITE_APP_PLUS_EXPORT_PUBLIC_KEY), and a beforeinstallprompt capture for PWA install. Collaboration is disabled when isRunningInIframe() is true. Examples with-nextjs dynamically imports the editor with ssr:false and sets window.EXCALIDRAW_ASSET_PATH. — [excalidraw-app/App.tsx#L102-150](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/App.tsx#L102-L150) [excalidraw-app/App.tsx#L173-188](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/App.tsx#L173-L188) [excalidraw-app/App.tsx#L375-379](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/App.tsx#L375-L379) [examples/with-nextjs/src/app/page.tsx#L6-25](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/examples/with-nextjs/src/app/page.tsx#L6-L25) [excalidraw-app/package.json#L28-40](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/excalidraw-app/package.json#L28-L40)
- Embeddables and hyperlinks are host-gated. Excalidraw props include validateEmbeddable, renderEmbeddable, onLinkOpen, and generateLinkForSelection. SVG export leaves embeddables out unless renderEmbeddables is set. Links are passed through sanitizeUrl from @braintree/sanitize-url in packages/common/src/url.ts. — [packages/excalidraw/index.tsx#L111-112](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/index.tsx#L111-L112) [packages/excalidraw/index.tsx#L253-254](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/index.tsx#L253-L254) [packages/excalidraw/scene/export.ts#L477-493](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/excalidraw/scene/export.ts#L477-L493) [packages/common/src/url.ts#L1-10](https://github.com/excalidraw/excalidraw/blob/31df3e6ef245c646b18a055ccf858cd6117c7768/packages/common/src/url.ts#L1-L10)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
