# excalidraw: the npm package has no collaboration, the app does

> excalidraw/excalidraw holds two different things under one repository: a React editor published as @excalidraw/excalidraw, and the excalidraw-app that runs at excalidraw.com with real-time collaboration, end-to-end encryption and offline support. Those app features are not in the package, and the project says they will arrive as plugins later.

**excalidraw/excalidraw** — Virtual whiteboard for sketching hand-drawn like diagrams

- Repository: https://github.com/excalidraw/excalidraw
- Website: https://excalidraw.com
- Stars: 132,994 · Forks: 15,484
- Language: TypeScript
- License: MIT
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/excalidraw-excalidraw

## One repository, two products: the package and the showcase app

The README separates the two halves before it lists anything. The editor is an npm package, and the list of what it supports belongs to that package: an infinite canvas, hand-drawn style, dark mode, image support, shape libraries, localization, export to PNG, SVG and clipboard, an open format, a range of tools from rectangle and diamond to free-draw and eraser, arrow-binding and labeled arrows, undo and redo, zoom and panning.

Adding the editor to your own application is one install, and the note above it says these instructions are for the npm package rather than for running the repository:

```bash
npm install react react-dom @excalidraw/excalidraw
# or
yarn add react react-dom @excalidraw/excalidraw
```

What lands in your dependency list is the package and the two React packages, and nothing else: no server, no database, no collaboration client.

Separately, the app hosted at excalidraw.com is called a minimal showcase of what you can build with Excalidraw, and its source sits in this repository too, under excalidraw-app. Consequence: the app you open in a browser and the component you embed in a product are not the same surface with the same feature list, and the README prints the two lists one under the other.

## Collaboration, encryption and offline are the app, not the package

Five features belong to the hosted app: PWA support that works offline, real-time collaboration, end-to-end encryption, local-first support that autosaves to the browser, and shareable links exported as a readonly link. The package list ends at shape libraries and clipboard export.

The README is explicit about the gap and about the intent: these features will be added as drop-in plugins for the npm package in the future. Until then that sentence is the whole contract. Consequence for an integrator: real-time multiplayer, offline storage and encrypted sharing become your engineering problem rather than a config flag, and the only thing that crosses between your app and someone else's is the `.excalidraw` JSON file. If any of those five is on your requirement list, the hosted app answers it and the package does not.

## The .excalidraw JSON file is the only format described as re-openable

Export comes in three flavours: PNG, SVG and the clipboard, plus an open format that writes a drawing as a `.excalidraw` json file. That last one is what makes a drawing portable rather than a picture of a drawing, and it is the only representation described as something you export and keep.

No import path is described for a flattened image, which means a diagram that leaves as a PNG comes back as a picture. Consequence: if a workflow ends in a slide deck, a ticket or a commit message, keep the JSON next to the PNG or the sketch becomes something you have to redraw. The same reasoning covers the rest of the editing surface, since shape libraries, labeled arrows and image support are all part of what that file has to carry.

## yarn 1.22.22 workspaces, and a build script per package

The manifest is a monorepo that has not moved to a newer package manager. `packageManager` is pinned to yarn@1.22.22, the workspaces are excalidraw-app, packages/* and examples/*, and the engine floor is Node 18 or newer. Every build target names its own directory: build:common, build:element, build:excalidraw and build:math each change into a package under packages, build:app targets excalidraw-app, and a separate build-node script runs scripts/build-node.js.

The toolchain around it is just as specific: TypeScript 5.9.3, Vite 5.0.12, Vitest 3.0.6, prettier 2.6.2, husky 7.0.4 with lint-staged 12.3.7, and shared configs published as @excalidraw/eslint-config and @excalidraw/prettier-config. Consequence: this is Yarn classic, not Yarn berry, and a contributor who reaches for a newer major version hits a lockfile mismatch before any code is compiled.

## The Docker image builds with node and serves with nginx

The Dockerfile has two stages. The first is node 24 pinned by digest, and it copies the whole tree in and installs with a frozen lockfile and a ten minute network timeout. Above that line sits a comment reading do not ignore optional dependencies, followed by the failure it prevents: Cannot find module @rollup/rollup-linux-x64-gnu. That is a recorded error, not a stylistic note.

The second stage is nginx, and it copies one directory out of the build, the excalidraw-app build output, into the nginx html root, with a healthcheck that wgets localhost. Consequence: the runtime image contains no Node at all, so what you deploy is static files. Server-side behaviour, a collaboration backend included, cannot live in this image and has to be compiled into the bundle or hosted somewhere else.

## compose publishes port 80 as 3000 and disables the healthcheck

The compose file is written for development. It builds from the repository root with NODE_ENV=development passed as a build arg and as an environment variable, names the container excalidraw, publishes port 80 inside as 3000 on the host, sets restart to on-failure, opens stdin, and then does something worth noticing: the healthcheck entry is present and set to disable.

The volumes explain the rest. The repository is bind-mounted over the app directory with the delegated flag, package.json and yarn.lock are mounted individually, and a volume literally named notused is mounted over node_modules so the host copy is ignored. Consequence: docker compose up gives you a development server on localhost:3000 with readiness checks switched off, so you read the logs rather than the container state, and nothing in this file is a production topology.

## v0.17.3 to v0.18.1: still pre-1.0, months past the last tag

The release history is short and recent only at the end: v0.17.3 in February 2024, v0.18.0 in March 2025, and v0.18.1 in April 2026. The last push to the master branch was on 2026-09-26, so commits are landing well after the newest tag.

The version number is itself the warning. Below 1.0 a minor bump is allowed to break an API, and whatever sits on master today past v0.18.1 is unreleased. Consequence: pin the exact @excalidraw/excalidraw version you tested and read the notes for the bump instead of tracking a range. Remember too that the VS Code integration, the marketplace extension pomdtr.excalidraw-editor, is a separate artifact maintained outside this repository, so it can lag the package you depend on.

## Conclusion

Use the npm package when you want a drawing surface inside your own product and can build persistence, sharing and multiplayer yourself. Use the hosted app when you want those features today, and accept that the drawing format is the handoff between them. Before you integrate, read the split carefully, check which of the five app features you actually need, and pin a version: the release line is still below 1.0, moving from v0.17.3 in February 2024 to v0.18.1 in April 2026.

## FAQ

### What is Excalidraw used for?

It is a virtual whiteboard for hand-drawn style diagrams and wireframes on an infinite canvas. The editor also supports images, shape libraries, labeled arrows, localization, and export to PNG, SVG, the clipboard or an .excalidraw json file.

### Is Excalidraw free or paid?

The editor is published as an npm package under MIT and described as free and open source. The project also points at Excalidraw+ and at Open Collective sponsorship, without stating what any paid tier includes.

### Is Excalidraw built with React?

Yes, the integration instructions install react and react-dom alongside the package. The repository itself carries React type definitions, a Vite React plugin, and a react-app ESLint config among its development dependencies.

### How do I install Excalidraw?

For embedding the editor in your own app, install it with npm or yarn together with react and react-dom. To run the repository itself for development, the project points to its Development Guide rather than to a command in the README.

### How do I use Excalidraw in VS Code?

The project lists a VS Code extension from the marketplace, pomdtr.excalidraw-editor, as one of its two integrations alongside the npm package. That extension is maintained outside this repository, so it is versioned separately from the package you depend on.

### How do I use Excalidraw for a system design diagram?

Draw it on the canvas with the shape tools, then connect boxes with arrow-binding and labeled arrows so the relationships read clearly. Export as PNG or SVG for a document, or keep the .excalidraw json file so the diagram can be edited again later.

## Sources

- [Official documentation](https://excalidraw.com)
- [Official README](https://github.com/excalidraw/excalidraw#readme)
- [Project repository](https://github.com/excalidraw/excalidraw)
- [Release notes](https://github.com/excalidraw/excalidraw/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/excalidraw-excalidraw
