---
title: Getting started with jeeboard
description: Shows how to install the jeeboard packages and wire a minimal editor with a canvas renderer.
---
# Getting started
This guide builds a minimal editor.
The editor shows one rectangle on an infinite canvas.
It has no tools and no persistence.
Later sections link to the packages that add these features.
## Install
Install the packages for the minimal editor:
```sh
pnpm add @jeeboard/core @jeeboard/dom @jeeboard/renderer-canvas2d
```
- `@jeeboard/core` holds the elements and the change history.
- `@jeeboard/dom` marks the host element for the editor.
- `@jeeboard/renderer-canvas2d` draws the elements.
## Prepare the page
Add a host element and a canvas to your HTML:
```html
```
Give the canvas a size with CSS.
The renderer reads the CSS size when you call `resize`.
## Create the editor core
The editor core holds all elements.
Create it and add one element in a transaction:
```ts
import { createEditorCore, elementId } from "@jeeboard/core";
const core = createEditorCore();
core.transact("create rectangle", (tx) =>
tx.create({
id: elementId("rectangle-1"),
type: "shape",
bounds: { x: 0, y: 0, width: 160, height: 100 },
properties: { shape: "rectangle" },
})
);
```
Each transaction that mutates elements becomes one undo step.
See [@jeeboard/core](core/index.md) for the full data model.
## Create the renderer
Create the renderer on the canvas element:
```ts
import {
createCanvas2DRenderer,
type Camera,
} from "@jeeboard/renderer-canvas2d";
const canvas = document.querySelector("#board")!;
const renderer = createCanvas2DRenderer(canvas, { background: "#ffffff" });
const camera: Camera = { center: { x: 80, y: 50 }, zoom: 1 };
renderer.resize(canvas.clientWidth, canvas.clientHeight, window.devicePixelRatio);
```
The camera has a center point in world coordinates and a zoom factor.
The zoom must be finite and positive.
## Mark the host element
Attach the editor core to the host element:
```ts
import { createEditorHost } from "@jeeboard/dom";
const editorHost = createEditorHost(document.getElementById("editor")!);
editorHost.attach(core);
```
The `attach` method sets the `data-jeeboard-editor` attribute and an aria label.
See [@jeeboard/dom](dom/index.md) for text portals and the accessibility mirror.
## Render frames
Render one frame now.
Render a new frame each time the core changes:
```ts
function renderFrame(): void {
renderer.present({
camera,
visibleElements: core.list(),
});
}
renderFrame();
core.subscribe(() => renderFrame());
```
NOTE: `core.list()` returns all elements. For large boards, query only the visible elements with the spatial index from [@jeeboard/scene](scene/index.md).
Check `renderer.diagnostics().pendingTileCount` after `present`.
Request another animation frame when the count is greater than zero.
The renderer then rasterizes the remaining tiles.
## Next steps
Add the features that your editor needs:
1. Add [@jeeboard/scene](scene/index.md) for fast viewport queries and hit tests.
2. Add [@jeeboard/ink](ink/index.md) for freehand strokes.
3. Add [@jeeboard/text-prosemirror](text-prosemirror/index.md) for rich-text editing.
4. Add [@jeeboard/storage](storage/index.md) for local persistence.
5. Add [@jeeboard/automerge](automerge/index.md) for CRDT sync and collaboration.
The [playground](playground/index.md) is a complete application that composes all packages.
Use it as the reference for a full integration.