Your first annotation
On this page
Documentation index · Choose an adapter
Your application supplies an anchor, the engine places a note, and a renderer displays it. This guide starts with one point in a new browser project.
Choose your version
The tutorial installs published 0.9.1. The website and repository examples
track main; use the tagged API reference
for this release or the 0.7 guide
for older applications. Read the migration guide when
upgrading from 0.6.
Start a new application without cloning this repository
Use Node 22.12.0 or newer (see compatibility):
mkdir annotation-demo
cd annotation-demo
npm init -y
npm install @ponchia/annotations@0.9.1
npm install --save-dev vite@8
Create index.html with:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>My first annotation</title>
<link rel="icon" href="data:," />
</head>
<body>
<script type="module" src="/main.ts"></script>
</body>
</html>
Use it in a browser application
Create main.ts next to index.html. In an existing TypeScript app with CSS
imports, use an entry point that runs after the document body exists:
import {
resolveAnnotationLayout,
renderAnnotationsSvg,
type Annotation
} from '@ponchia/annotations';
import '@ponchia/annotations/bronto.css';
const annotations: Annotation[] = [{
id: 'peak',
anchor: { type: 'point', point: { x: 60, y: 120 } },
note: { title: 'Peak response', body: 'An explanation attached to this point.' },
placement: { side: 'right' }
}];
const layout = resolveAnnotationLayout({
annotations,
bounds: { x: 0, y: 0, width: 400, height: 240 },
padding: 16
});
const container = document.createElement('div');
container.style.maxWidth = '640px';
container.style.fontFamily = 'system-ui, sans-serif';
container.style.aspectRatio = '400 / 240';
container.innerHTML = renderAnnotationsSvg(layout, {
title: 'An annotated point',
markerIdPrefix: 'first-annotation'
});
document.body.append(container);
Run npx vite --host 127.0.0.1 and open the printed URL. You should see a
Peak response note and connector. Stop the server with Ctrl+C.
The point coordinates stand in for your chart's geometry. The CSS import styles
the output without requiring BrontoUI, and the container scales to narrow screens.
Run npx vite build for a static build and npx vite preview --host 127.0.0.1
to preview it. Vite transforms TypeScript; add a separate type check to your
app's CI.
renderAnnotationsSvg returns a complete SVG element. For an existing chart,
follow the SVG example's layering pattern and match
the host's viewBox and preserveAspectRatio.
Use it in React
Use the same package install in an existing React application. Keep its supported
react and react-dom peer dependencies. This component needs no chart library:
import { AnnotationLayer } from '@ponchia/annotations/react';
import '@ponchia/annotations/bronto.css';
export function AnnotatedPoint() {
return (
<AnnotationLayer
annotations={[{
id: 'peak',
anchor: { type: 'point', point: { x: 60, y: 120 } },
note: { title: 'Peak response' },
placement: { side: 'right' }
}]}
bounds={{ x: 0, y: 0, width: 400, height: 240 }}
style={{ width: '100%', maxWidth: 640, height: 'auto', aspectRatio: '400 / 240' }}
label="An annotated point"
markerIdPrefix="react-first-annotation"
/>
);
}
Render <AnnotatedPoint /> from your application. It creates an SVG and wrapper;
the style makes the wrapper responsive. The React example
shows alignment with a host chart. Continue with rendering and editing
when you need measurements or edit callbacks; your app owns note state and persistence.
Coordinate and layout basics
bounds, anchors, obstacles, manual positions, and note sizes use one coordinate
space. A screen-pixel rectangle is not automatically a viewBox rectangle.
Use the DOM or host adapter when measuring rendered content.
All note IDs must be stable and unique within a layer. Give independent layers
distinct markerIdPrefix values so their SVG connector definitions do not collide.
Automatic placement chooses among candidates. It cannot make unlimited text fit
a small viewport. Inspect evaluateAnnotationLayout, adjust placement options,
or reduce the visible notes when a layout is crowded. See the
core guide and troubleshooting.
Version and ownership boundaries
See API stability before adopting experimental features. Chart rendering, graph layout, selection, undo/redo, Worker lifetime, and persistence belong to your application.
Try the existing examples
The example catalog has clone-and-run instructions for complete host integrations. To connect your own surface, start with one note on an SVG figure, DOM report, or React Flow graph.