Open-source framework for constraint-driven 2D editors.
Dotloom lets you build editors where drawings follow rules: a shelf whose compartments always fill its width, a floor plan whose doors stay in their walls, a schedule whose blocks keep their order. It is
- a Rust engine — geometry, documents, transactions and undo, linear and
nonlinear constraint solving,
.dotlproject files, SVG/DXF import and export — that runs headless or in the browser through WebAssembly in a Web Worker; - a wgpu renderer for WebGPU and WebGL2 (and native GPUs for PNG export);
- a framework-agnostic TypeScript SDK with tools, snapping, storage and plugins;
- an optional React editor with panels, inspector, command palette, themes and English/Turkish messages.
Try it: playground · examples · documentation
Status:
1.1.0(stable), on npm (@dotloomjs/sdk,@dotloomjs/react) and crates.io (dotloom-*). The GitHub Release has the same packages and the CLI for Linux, Windows and macOS. Seedocs/status.mdfor what is verified and what is open, anddocs/requirements.mdfor the evidence behind every requirement.
Install the packages (React is optional):
npm install @dotloomjs/sdk
npm install @dotloomjs/react react react-dom # the ready-made React editorRust (headless engine, .dotl, SVG/DXF):
cargo add dotloom-engine dotloom-ioOr build the npm packages from this repository (bash or PowerShell):
git clone https://github.com/TNYCL/dotloom
cd dotloom
pnpm install
pnpm run build:wasm
pnpm run build
pnpm --filter @dotloomjs/sdk pack --pack-destination "$PWD/dist-packages"
pnpm --filter @dotloomjs/react pack --pack-destination "$PWD/dist-packages"
# in your project: install both tarballs in one command
npm install ../dotloom/dist-packages/dotloomjs-sdk-1.1.0.tgz ../dotloom/dist-packages/dotloomjs-react-1.1.0.tgzA complete editor without a framework:
import { createEditor } from '@dotloomjs/sdk'
const editor = await createEditor(document.getElementById('editor')!)
await editor.engine.apply([
{ op: 'createEntity', entity: { geometry: { type: 'rect', origin: [0, 0], width: 1200, height: 800 } } },
])
await editor.viewport.fit()
editor.core.setTool('line')The React editor:
import { DotloomEditor } from '@dotloomjs/react'
import '@dotloomjs/react/styles.css'
export const App = () => <div style={{ height: '100vh' }}><DotloomEditor theme="system" locale="tr" /></div>Your own object types are plugins — typed properties, anchors, drawing recipes and rules written as expressions:
import { PluginHost } from '@dotloomjs/sdk'
const plugins = new PluginHost(editor.engine, editor.core)
await plugins.register({
id: 'acme.furniture',
version: '1.0.0',
types: [{
typeId: 'acme.table', version: 1,
props: { width: { type: 'number', dim: 'length', default: '120cm' } },
constraints: [{ lhs: 'width', op: '>=', rhs: '60cm' }],
// anchors, render recipes, …
}],
})See Getting started, Plugins and the external plugin example, which is built and tested from the packed tarballs outside this repository in CI.
| Path | What |
|---|---|
crates/geometry, document, constraints, scene, engine, io |
headless Rust core (no DOM, window or GPU dependency — checked in CI) |
crates/render, render-web, wasm, cli |
wgpu renderer, browser bindings, WebAssembly engine binding, dotloom CLI |
packages/sdk, packages/react |
@dotloomjs/sdk, @dotloomjs/react |
apps/docs, apps/playground |
documentation site (VitePress, TypeDoc, rustdoc) and the reference editor |
examples/ |
vanilla, shelf configurator, floor plan, timeline, external plugin |
tests/e2e, tests/fixtures, fuzz |
browser tests and benchmarks, fixtures and baselines, fuzz targets |
docs/ |
requirements, status, ADRs, performance |
Requirements: Rust (version from rust-toolchain.toml, plus wasm32-unknown-unknown),
wasm-bindgen-cli 0.2.129, Node 24 and pnpm. The same commands run locally
(Windows PowerShell, Linux, macOS) and in CI:
| Purpose | Command |
|---|---|
| Format, lint, typecheck | pnpm run check |
| Rust tests | cargo test --workspace --all-features |
| WebAssembly build | pnpm run build:wasm |
| Packages | pnpm run build |
| SDK / React / example tests | pnpm run test |
| Browser tests | pnpm run test:e2e |
| Documentation site | pnpm run build:site |
| Package consumer smoke test | pnpm run smoke:packages |
| Crate consumer smoke test | pnpm run smoke:crates |
| Reference-device benchmarks | pnpm --filter @dotloomjs/e2e run bench |
Read AGENTS.md and CONTRIBUTING.md before
changing code.
Chrome, Edge and Firefox on WebGPU and WebGL2, Safari 27 and 26 (WebGL2; WebGPU where Safari exposes it, not yet verified on Mac hardware), Node.js for headless use, and the Rust crates on Windows, Linux and macOS. The support table lists which combination is verified by which test.
On the reference device (Ryzen 9 5900X, GTX 1060, 1080p at 120 Hz): 10 000 shapes
pan and zoom without a dropped frame, hit-testing and snapping answer in under a
millisecond, editing a 200-variable sketch takes 23 ms at p95, and a 10 000-object
file opens in about 0.1 s. Method and all numbers: docs/performance.md.
.dotl files never execute code or fetch from the network; SVG and DXF imports are
bounded and sanitized. Report vulnerabilities privately as described in
SECURITY.md.
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Third-party assets: the renderer embeds a subset of Inter (SIL Open Font License
1.1, see crates/render/assets/).