# dash-excalidraw — Excalidraw drawing canvas for Dash

> dash-excalidraw — the Excalidraw whiteboard as a Dash component. JSON-safe props, imperative commands, event snapshots, AI scenes. By Pip Install Python.

> **`dash-excalidraw` — the [Excalidraw](https://excalidraw.com/) whiteboard as a first-class [Dash](https://dash.plotly.com/) component.** By [Pip Install Python](https://2plot.dev).

Every canvas on this site is a running Dash app. Draw on them.

```bash
pip install dash-excalidraw
```

---

## The problem this solves

Excalidraw is a React application with a large imperative API. Wrapping it for Dash
means answering one question honestly: **what can cross the Python/JavaScript bridge?**

Only JSON can. Functions, RegExps and class instances cannot. Most wrappers stop
there and hand you a `clientside_callback` for anything interesting — which means
writing JavaScript to use a Python component.

This one translates the entire surface into three JSON-safe patterns, so you write
ordinary `@callback`s and never touch JavaScript.

| Upstream shape | What Python sees | Why |
|---|---|---|
| Callbacks (`onPaste`, `onPointerUpdate`, …) | **Snapshot props** — `lastPaste`, `lastPointerMove`, … each with a `timestamp` | A callback can't be serialized; a record of it firing can. The timestamp is how you dedupe. |
| Imperative methods (`updateScene`, `exportToSvg`, …) | **`command`** — `{id, type, payload}`, dispatched once per unique `id` | One prop covers twelve methods, and a re-render can't re-fire a command. |
| Async results | **`lastExport`**, carrying the `id` you dispatched | Exports resolve out of order under load. The id is how you correlate. |
| `validateEmbeddable` RegExp | A **list of glob strings**, compiled to RegExps on the JS side | A RegExp has no JSON form. `"*.youtube.com"` does. |

---

## Thirty seconds to a canvas

```python
from dash import Dash, Input, Output, callback, html
from dash_excalidraw import DashExcalidraw

app = Dash(__name__)

app.layout = html.Div([
    DashExcalidraw(id="canvas", height="600px"),
    html.Pre(id="count"),
])


@callback(Output("count", "children"), Input("canvas", "elements"))
def show(elements):
    return f"{len(elements or [])} elements on the canvas"


if __name__ == "__main__":
    app.run(debug=True)
```

Nothing else is required. The Excalidraw bundle, its stylesheet and its UI font ship
inside the wheel as one self-contained JavaScript file — no CDN dependency at load
time, no `external_stylesheets` entry, no build step.

---

## Where to go next

**Start here** — [Basic usage](/basic) is the smallest useful app.
[initialData](/initial-data) seeds a scene at mount.

**Reading the canvas** — [Events](/events) shows every callback as a snapshot prop.
[Persistence](/persistence) streams `serializedData` to a store and restores it.

**Driving the canvas** — [Command dispatch](/commands) is the imperative API from
Python. [Export](/export) is the async round-trip. [Library](/library) reads and
writes the shape library.

**Appearance** — [Theming](/theming), [View modes](/view-modes), [UIOptions](/ui-options).

**At scale** — [File uploads](/file-uploads) keeps canvas JSON small by pushing
pasted images to storage and swapping the base64 for URLs.
[Collaboration](/collaboration) drives the collaborator UI and live cursors.

**AI** — [AI agent](/ai-agent) turns a natural-language prompt into a scene, and is
honest about what that costs.

---

## Excalidraw 0.18

Pinned exactly at 0.18.1, which brings elbow arrows, flowchart shortcuts, scene
search, image cropping, element linking and the command palette — and patches the
mermaid XSS advisory.

One upgrade note worth reading before you dispatch a scene from Python: 0.18 replaced
`commitToHistory` with `captureUpdate`, and **changed what the default means**. 0.17
left undo history untouched; 0.18 folds a programmatic push into the *next* captured
action, so a user's first Ctrl+Z after your `updateScene` would also roll back their
own previous edit. Nothing errors and nothing warns.

This wrapper defaults to `IMMEDIATELY`, so a Python-dispatched push is one discrete,
individually undoable step. [Command dispatch](/commands) covers the override.

---

## For agents

Append `/llms.txt` to any URL on this site for the machine-readable Markdown of that
page. The index is at [/llms.txt](/llms.txt), and every page document opens with a
navigation block back to the site and network indexes rather than being a dead end.

## Other sizes of this document

- [/llms-small.txt](https://excalidraw.2plot.dev/llms-small.txt): compact briefing — start here if context is tight. (4.8 KB, ~1.2k tok)
- [/llms.txt](https://excalidraw.2plot.dev/llms.txt): this document — the index you are reading. (14.3 KB, ~3.6k tok)
- [/llms-full.txt](https://excalidraw.2plot.dev/llms-full.txt): every page's prose in one document — 20 pages. (281.0 KB, ~71.9k tok)

## Access policy

- Terms: these documents are free to fetch. A free account unlocks any gated document.
- Identity: agents may present a key by appending `?key=<value>` to any document URL. Get one: https://2plot.ai
- Rate: prefer ONE `/llms-full.txt` fetch over N per-page fetches. On 429, honour `Retry-After` and back off exponentially.
- Coordination: start at https://2plot.dev/llms.txt — one index enumerates every site; do not rediscover the network by crawling it.
- Crawler policy (mirrors /robots.txt): allowed: GPTBot, ClaudeBot, CCBot, Google-Extended, FacebookBot, Omgili, ByteSpider, Amazonbot, Applebot-Extended, meta-externalagent, AI2Bot, Diffbot, Timpibot, ImagesiftBot, ChatGPT-User, Claude-User, Claude-SearchBot, PerplexityBot, OAI-SearchBot, Perplexity-User, Googlebot, Bingbot, Slurp, DuckDuckBot, GoogleOther, Google-InspectionTool, Storebot-Google, AdsBot-Google.
- Accounting: every document read is logged with the requesting vendor (verified against published IP ranges where the operator publishes them). See https://2plot.dev/llms.txt

## Pages

Every page in this application. Each has a Markdown version at the `llms.txt` URL beside it.

- [dash-excalidraw — Excalidraw drawing canvas for Dash](https://excalidraw.2plot.dev/): dash-excalidraw — the Excalidraw whiteboard as a Dash component. JSON-safe props, imperative commands, event snapshots, AI scenes. By Pip Install Python.
  - Machine-readable: https://excalidraw.2plot.dev/llms.txt (14.3 KB, ~3.6k tok)
- [AI agent](https://excalidraw.2plot.dev/ai-agent): Turn a natural-language prompt into an Excalidraw scene with Claude, ChatGPT or Gemini, and what it costs.
  - Machine-readable: https://excalidraw.2plot.dev/ai-agent/llms.txt (46.4 KB, ~11.9k tok)
- [API](https://excalidraw.2plot.dev/api): Component props reference for dash_excalidraw.
  - Machine-readable: https://excalidraw.2plot.dev/api/llms.txt (8.4 KB, ~2.1k tok)
- [Basic usage](https://excalidraw.2plot.dev/basic): The minimum viable DashExcalidraw — one component, default props, a working canvas.
  - Machine-readable: https://excalidraw.2plot.dev/basic/llms.txt (5.0 KB, ~1.3k tok)
- [Benchmark](https://excalidraw.2plot.dev/benchmark): Run one prompt across several efforts, token budgets or models — Claude against ChatGPT — and compare the drawings side by side.
  - Machine-readable: https://excalidraw.2plot.dev/benchmark/llms.txt (35.8 KB, ~9.2k tok)
- [Changelog](https://excalidraw.2plot.dev/changelog): Version history of dash-excalidraw, rendered from CHANGELOG.md.
  - Machine-readable: https://excalidraw.2plot.dev/changelog/llms.txt (54.7 KB, ~14.0k tok)
- [Collaboration](https://excalidraw.2plot.dev/collaboration): Drive the collaborator UI and live cursors from Python — the wrapper exposes the knobs, you bring the transport.
  - Machine-readable: https://excalidraw.2plot.dev/collaboration/llms.txt (3.5 KB, ~897 tok)
- [Command dispatch](https://excalidraw.2plot.dev/commands): Call Excalidraw's imperative API from Python through a JSON-safe command prop dispatched once per id.
  - Machine-readable: https://excalidraw.2plot.dev/commands/llms.txt (9.3 KB, ~2.4k tok)
- [Coverage](https://excalidraw.2plot.dev/coverage): The three commands and ten props no other example reaches — the leftovers of the prop surface, in one runnable place.
  - Machine-readable: https://excalidraw.2plot.dev/coverage/llms.txt (16.7 KB, ~4.3k tok)
- [Events](https://excalidraw.2plot.dev/events): Every Excalidraw callback surfaced as a timestamped snapshot prop you can read from a Dash callback.
  - Machine-readable: https://excalidraw.2plot.dev/events/llms.txt (5.0 KB, ~1.3k tok)
- [Export round-trip](https://excalidraw.2plot.dev/export): Export to SVG, PNG blob or canvas through an async command/lastExport round-trip correlated by id.
  - Machine-readable: https://excalidraw.2plot.dev/export/llms.txt (6.8 KB, ~1.7k tok)
- [File uploads](https://excalidraw.2plot.dev/file-uploads): Keep canvas JSON small: push pasted images to external storage and swap the base64 for URLs.
  - Machine-readable: https://excalidraw.2plot.dev/file-uploads/llms.txt (32.1 KB, ~8.2k tok)
- [initialData](https://excalidraw.2plot.dev/initial-data): Pre-populate the canvas on mount with elements, appState overrides and library items.
  - Machine-readable: https://excalidraw.2plot.dev/initial-data/llms.txt (3.7 KB, ~958 tok)
- [Library](https://excalidraw.2plot.dev/library): Read and write the Excalidraw shape library from Python with lastLibraryChange and updateLibrary.
  - Machine-readable: https://excalidraw.2plot.dev/library/llms.txt (3.9 KB, ~996 tok)
- [Migrating from 0.0.x](https://excalidraw.2plot.dev/migration): What changed between the PyPI 0.0.x releases and the current build — no prop was removed or renamed, but three defaults did change.
  - Machine-readable: https://excalidraw.2plot.dev/migration/llms.txt (5.0 KB, ~1.3k tok)
- [Persistence](https://excalidraw.2plot.dev/persistence): Stream serializedData to a Store or a database and restore a scene later via updateScene.
  - Machine-readable: https://excalidraw.2plot.dev/persistence/llms.txt (4.5 KB, ~1.1k tok)
- [Theming](https://excalidraw.2plot.dev/theming): Light and dark canvas themes, and how to keep them in step with your Mantine colour scheme.
  - Machine-readable: https://excalidraw.2plot.dev/theming/llms.txt (2.1 KB, ~525 tok)
- [Trace an image](https://excalidraw.2plot.dev/trace-image): Upload a reference image and have a vision model redraw it as an Excalidraw scene, then compare the two side by side.
  - Machine-readable: https://excalidraw.2plot.dev/trace-image/llms.txt (27.6 KB, ~7.1k tok)
- [UIOptions](https://excalidraw.2plot.dev/ui-options): The JSON-safe subset of Excalidraw's UIOptions: hide toolbar actions, tools and the welcome screen.
  - Machine-readable: https://excalidraw.2plot.dev/ui-options/llms.txt (8.4 KB, ~2.2k tok)
- [View modes](https://excalidraw.2plot.dev/view-modes): View mode, zen mode and grid mode — three declarative booleans that flip the editor's behaviour.
  - Machine-readable: https://excalidraw.2plot.dev/view-modes/llms.txt (2.7 KB, ~697 tok)

## About The 2plot network

Open-source Dash component libraries by Pip Install Python. Each component has its own documentation site and its own llms.txt; 2plot.dev indexes all of them, and 2plot.ai is the hub.

Network index: [https://2plot.dev](https://2plot.dev/llms.txt)

## Network

Other applications in this network. Same operator; each one serves its own `/llms.txt` in this format.

- [2plot.ai](https://2plot.ai): Network hub and account origin.
  - Machine-readable: https://2plot.ai/llms.txt
- [2plot.dev](https://2plot.dev): Package index for every open-source component in the network.
  - Machine-readable: https://2plot.dev/llms.txt
- [Documentation boilerplate](https://boilerplate.2plot.dev): The markdown-driven documentation template every satellite site is built from.
  - Machine-readable: https://boilerplate.2plot.dev/llms.txt
- [dash-leaflet2](https://leaflet.2plot.dev): Leaflet 2 maps as Dash components.
  - Machine-readable: https://leaflet.2plot.dev/llms.txt
- [dash-mui-scheduler](https://muischeduler.2plot.dev): MUI X Scheduler — calendars and event scheduling for Dash.
  - Machine-readable: https://muischeduler.2plot.dev/llms.txt
- [dash-mui-charts](https://muicharts.2plot.dev): MUI X charts, tree views and time pickers for Dash.
  - Machine-readable: https://muicharts.2plot.dev/llms.txt
- [flexlayout-dash](https://flexlayout.2plot.dev): IDE-style dockable, resizable and floatable window panels.
  - Machine-readable: https://flexlayout.2plot.dev/llms.txt
- [dash-improve-my-llms](https://llms.2plot.dev): The AI/LLM and SEO package every site in this network is built on.
  - Machine-readable: https://llms.2plot.dev/llms.txt
- [dash-flows](https://flows.2plot.dev): Node-graph editors built on React Flow.
  - Machine-readable: https://flows.2plot.dev/llms.txt
- [dash-pannellum](https://pannellum.2plot.dev): 360° panorama and virtual-tour viewer.
  - Machine-readable: https://pannellum.2plot.dev/llms.txt
- [dash-emoji-mart](https://emojimart.2plot.dev): Emoji picker component.
  - Machine-readable: https://emojimart.2plot.dev/llms.txt
- [dash-email](https://email.2plot.dev): Email composition and delivery components.
  - Machine-readable: https://email.2plot.dev/llms.txt
- [dash-model-viewer](https://modelviewer.2plot.dev): 3D model viewer with AR support, built on Google's model-viewer.
  - Machine-readable: https://modelviewer.2plot.dev/llms.txt

## Related projects

Projects by the same author on their own domains. Built on the same stack, but not part of the primary network.

- [Pirate's Bargain](https://piratesbargain.com): Deal aggregator built on the same Dash stack.
  - Machine-readable: https://piratesbargain.com/llms.txt
- [ai-agent.buzz](https://ai-agent.buzz): Agent tooling directory.
  - Machine-readable: https://ai-agent.buzz/llms.txt
- [2plot.media](https://2plot.media): Media and streaming, on the same Dash stack.
  - Machine-readable: https://2plot.media/llms.txt

## External references

Third-party documentation this project depends on or references. Not affiliated — listed so an agent can follow a dependency directly instead of searching for it.

- [Dash Mantine Components](https://www.dash-mantine-components.com): The UI component layer these docs are built with.
  - Machine-readable: https://www.dash-mantine-components.com/llms.txt
- [Plotly Dash documentation](https://dash.plotly.com): Upstream framework documentation.
  - Machine-readable: https://dash.plotly.com/llms.txt
