Atlasdraw is an open-source map studio that you host yourself. You draw on a real map with the Excalidraw tools, and every shape stays at its place on the ground when you pan, zoom or share. The map is MapLibre GL JS.
Note
Latest release: v1.0.0 (2026-05-15). The changes since then are under
"Unreleased" in CHANGELOG.md.
Use it when you must sketch, annotate and discuss a place, not only drop pins.
- Drawing on a map. Freehand, shapes, arrows, text and pins. A drawing is stored in world coordinates, so it does not drift when the map moves.
- Your data. Import GeoJSON, CSV (with lat/lon or WKT columns), Shapefile (zip), KML, KMZ, GPX and GeoTIFF. Style a layer by a property, show points as clusters or a heatmap, label and filter a layer, and read its attribute table. Add raster tiles from an XYZ URL.
- Measure. Distance, area and radius, on the ellipsoid.
- Share and embed. A read-only link or an
<iframe>embed. A server link lasts until you stop it. It shows your latest save, or one version that you choose. The server keeps earlier versions of each map. - Edit together. Live rooms with cursors, names and comments. The relay keeps a room between sessions.
- Open files. Export PNG (1x, 2x, 3x), PDF, GeoJSON, CSV, KML, GPX and
the
.atlasdrawbundle (zipped JSON and GeoJSON). - Self-host. No telemetry. The default basemap is a file on your own server.
The code is a Yarn 4 workspace in code/. Use Node 22 (.nvmrc).
cd code
corepack enable # gives the yarn version that package.json pins
yarn install
yarn start # the editor on http://localhost:5174Two Docker Compose stacks are in infra/:
infra/docker-compose.minimal.yml—webandstorage(SQLite and files). One port,3000.infra/docker-compose.yml—web,storage,postgresandcaddy(TLS). Map bytes go to an S3-compatible bucket that you supply; the stack runs no object store. The relay for live rooms starts with therealtimeprofile.
First run: docs/self-host/README.md.
Production: docs/self-host/production.md.
The default basemaps ("Light" and "Dark") make no request to another server: the tiles, label fonts and icons are in the image. The "Bright" and "OSM" basemaps and the tile layers that a user adds load from their own servers. The self-host guide tells you how to turn these off.
apps/atlas-app uses every package. The packages depend on few others.
| Part | Path | What it does |
|---|---|---|
| Editor | code/apps/atlas-app |
The editor, the read-only viewer and the embed |
| Excalidraw fork | code/packages/{excalidraw,element,math,common,utils} |
The drawing engine. Owned outright, not tracked |
| Geo | code/packages/geo |
World coordinates and measurement. Pure functions |
| Map | code/packages/basemap |
MapLibre host, basemaps, camera bridge, layer styles |
| Tools | code/packages/tools |
The pin tool, the measure session, unit text |
| Data | code/packages/data |
.atlasdraw read and write, importers, exporters |
| Protocol | code/packages/protocol |
Room links, the comment schema, every size limit |
| Storage server | code/apps/storage |
Fastify HTTP API: maps, write keys, share links |
| Relay | code/apps/realtime |
One Y.Doc per room over y-websocket, saved to SQLite |
| CLI | code/packages/cli |
lint and convert. Frozen (ADR-0016) |
Repository layout
atlasdraw/
├── code/ # Yarn 4 workspace
│ ├── apps/
│ │ ├── atlas-app/ # editor — Vite + React 19
│ │ ├── realtime/ # relay — ws + y-protocols + SQLite
│ │ └── storage/ # HTTP API — Fastify
│ ├── packages/
│ │ ├── geo/ basemap/ data/ tools/ protocol/ cli/
│ │ └── excalidraw/ element/ math/ common/ utils/ # the fork
│ ├── decisions/ # ADR 0001–0010: fork, licence, early design
│ └── LICENSING.md
├── docs/
│ ├── architecture/adr/ # ADR 0006 and later: product decisions
│ ├── self-host/ # operator guides
│ ├── performance/
│ └── security/
├── infra/ # Compose files, Caddyfile, Makefile
├── PRD.md PRFAQ.md atlasdraw-tech-spec.md
└── SECURITY.md CHANGELOG.md VENDOR.md
The Excalidraw fork is plain files in code/, with no submodule. The fork
point, and how to port a security fix, are in VENDOR.md.
| Concern | Choice |
|---|---|
| UI | React 19 |
| Drawing | Excalidraw fork (@atlasdraw/excalidraw) |
| Map | maplibre-gl 6, PMTiles |
| Live rooms | yjs, y-websocket |
| State | zustand |
| Local saves | IndexedDB (idb) |
| Schemas | zod |
pdf-lib |
|
| Build and tests | Vite 7, Vitest 3, Playwright |
| Storage server | Fastify; SQLite and files, or Postgres and S3 |
| Relay | ws, y-protocols, better-sqlite3 |
Run these from code/:
yarn start # editor dev server, port 5174
yarn build # production build of the editor
yarn test:typecheck # TypeScript, all workspaces
yarn test --watch=false # Vitest, all workspaces
yarn test:all # typecheck, lint, prettier, test scan, vitest
yarn workspace @atlasdraw/atlas-app e2e # Playwright, chromiumRead code/CONTRIBUTING.md. Decisions are ADRs in
code/decisions/ and
docs/architecture/adr/. The two series use some
of the same numbers, so cite an ADR by its file path.
Atlasdraw uses three open-source licences. The full table is
code/LICENSING.md.
| Component | Licence |
|---|---|
apps/atlas-app, apps/realtime, apps/storage |
AGPL-3.0-only |
packages/{cli,geo,data,protocol} |
MIT |
packages/{basemap,tools} |
MPL-2.0 |
The fork: packages/{excalidraw,element,math,common,utils} |
MIT (upstream) |
Licence files: code/LICENSE-AGPL,
code/LICENSE-MIT,
code/LICENSE-MPL,
code/LICENSE-EXCALIDRAW-UPSTREAM.
PRD.md— product requirements, and what has shippedPRFAQ.md— the read-only map embedatlasdraw-tech-spec.md— the first engineering spec, kept as history. The code and the ADRs replace it.SECURITY.md— trust-boundary findings and their fixesVENDOR.md— the Excalidraw fork pointCHANGELOG.md— release history