# How DrawDB Handles Notes and Annotations in Diagrams: A Technical Deep-Dive

> Learn how DrawDB manages notes and annotations with its dedicated React context and useNotes hook. Effortlessly create, position, edit, and delete draggable elements on your diagrams.

- Repository: [drawDB/drawdb](https://github.com/drawdb-io/drawdb)
- Tags: deep-dive
- Published: 2026-08-14

---

**DrawDB manages notes through a dedicated React context that provides CRUD operations, with UI components consuming a `useNotes` hook to create, position, edit, and delete draggable annotations on the canvas.**

Notes and annotations in database diagrams serve a critical purpose: documenting design decisions, marking TODOs, or explaining complex relationships. DrawDB implements this feature as a lightweight, fully-integrated subsystem rather than an afterthought. This article examines the architecture, state management, and persistence mechanisms that power DrawDB's note functionality, based on the `drawdb-io/drawdb` source code.

## State Management with NotesContext

The foundation of DrawDB's note system resides in [`src/context/NotesContext.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/context/NotesContext.jsx). This file establishes a **React context** that centralizes all note-related state across the application.

The context provider wraps the entire editor, ensuring any component can access notes without prop drilling. The context stores an array of note objects, each containing:

- `id`: Unique identifier for the note
- `x`, `y`: Canvas coordinates for positioning
- `content`: The annotation text
- `theme`: Background color styling

According to the `drawdb-io/drawdb` source code, the context exposes four primary actions: `addNote`, `updateNote`, `removeNote`, and `getNotes`. These pure functions modify the React state, triggering re-renders wherever notes are consumed.

## The useNotes Hook Interface

To abstract the context API, DrawDB provides [`src/hooks/useNotes.js`](https://github.com/drawdb-io/drawdb/blob/main/src/hooks/useNotes.js). This custom hook simplifies component integration by returning an object with the available actions.

Components throughout the editor—toolbar buttons, canvas elements, and export utilities—all rely on this hook rather than directly importing the context. This pattern decouples the UI from state implementation details and enables easier testing.

```js
// Consuming the notes API in a component
import { useNotes } from '../hooks/useNotes';

function CanvasNotes() {
  const { addNote, updateNote, removeNote, notes } = useNotes();
  
  // Component logic using note operations
  return notes.map(note => <NoteElement key={note.id} note={note} />);
}

```

## Creating Notes: The Toolbar Integration

User interaction begins at the toolbar through [`src/icons/IconAddNote.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/icons/IconAddNote.jsx). Clicking this icon invokes `addNote` with the current cursor position.

The creation flow works as follows:

1. User clicks the **Add Note** icon
2. Event coordinates are captured from `e.nativeEvent`
3. `addNote` receives position data plus default styling from [`src/data/constants.js`](https://github.com/drawdb-io/drawdb/blob/main/src/data/constants.js)
4. A new note object enters the context state
5. React re-renders the canvas, displaying the draggable note

```js
// Triggering note creation from toolbar
import { useNotes } from '../hooks/useNotes';
import { defaultNoteTheme } from '../data/constants';

function AddNoteButton() {
  const { addNote } = useNotes();

  const handleClick = (e) => {
    const { x, y } = e.nativeEvent;
    addNote({ 
      x, 
      y, 
      content: '', 
      theme: defaultNoteTheme 
    });
  };

  return <IconAddNote onClick={handleClick} />;
}

```

## Rendering and Editing Note Elements

Each note renders as a **draggable, resizable DOM element** positioned absolutely on the canvas. The note component—integrated within [`src/pages/Editor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/pages/Editor.jsx)—consumes the `NotesContext` for live updates.

The editing interface supports:

- **Inline text editing** via a `<textarea>` element
- **Drag repositioning** with coordinate updates on `onDragEnd`
- **Theme customization** through color selection
- **Deletion** with immediate context removal

```js
// Core note component implementation pattern
import { useNotes } from '../hooks/useNotes';

function Note({ note }) {
  const { updateNote, removeNote } = useNotes();

  return (
    <div
      className="drawdb-note"
      style={{ 
        left: note.x, 
        top: note.y, 
        background: note.theme 
      }}
      draggable
      onDragEnd={(e) => updateNote(note.id, { x: e.x, y: e.y })}
    >
      <textarea
        value={note.content}
        onChange={(e) => updateNote(note.id, { content: e.target.value })}
      />
      <button onClick={() => removeNote(note.id)}>
        Delete
      </button>
    </div>
  );
}

```

## Styling and Theming Configuration

Visual consistency for notes originates in [`src/data/constants.js`](https://github.com/drawdb-io/drawdb/blob/main/src/data/constants.js). The `defaultNoteTheme` constant defines the initial background color (`#fcf7ac`, a light yellow) that distinguishes notes from tables and relationships.

Users can override this default per-note through the editing UI. The selected theme persists in the note object's state and survives export/import cycles.

## Persisting Annotations Across Formats

Notes integrate into DrawDB's export pipeline, ensuring annotations survive beyond the current editing session. Two primary export paths handle note serialization:

**DBML Export ([`src/utils/exportAs/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportAs/dbml.js))**

The DBML formatter appends note declarations after table definitions:

```js
function exportDbml(tables, notes) {
  const tablePart = tables.map(formatTable).join('\n');
  const notesPart = notes
    .map((n) => `Note ${n.id} "${n.content}" at (${n.x}, ${n.y})`)
    .join('\n');
  return `${tablePart}\n${notesPart}`;
}

```

**Documentation/Image Export**

The [`src/utils/exportAs/documentation.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportAs/documentation.js) utility includes notes in generated PNG exports and shareable URLs. Position and content data serialize alongside schema information, enabling full diagram restoration.

## Complete Interaction Flow

Understanding the full lifecycle clarifies how these subsystems cooperate:

1. **Initialization**: `NotesContextProvider` mounts in [`Editor.jsx`](https://github.com/drawdb-io/drawdb/blob/main/Editor.jsx), establishing empty note state
2. **Creation**: Toolbar click → `useNotes().addNote()` → state update → canvas re-render
3. **Positioning**: User drags note → `onDragEnd` fires → `updateNote` commits new coordinates
4. **Editing**: Text input → `onChange` debounced → `updateNote` synchronizes content
5. **Styling**: Color picker selection → `updateNote` applies new theme value
6. **Deletion**: Remove button → `removeNote` filters state → component unmounts
7. **Export**: Formatter iterates `notes` array → serializes to target format

## Summary

- **Centralized state**: [`NotesContext.jsx`](https://github.com/drawdb-io/drawdb/blob/main/NotesContext.jsx) maintains the source of truth for all diagram annotations
- **Clean API**: `useNotes` hook provides ergonomic access to CRUD operations without context boilerplate
- **Visual integration**: Notes render as first-class canvas elements with drag, resize, and edit capabilities
- **Customizable appearance**: Default theming from [`constants.js`](https://github.com/drawdb-io/drawdb/blob/main/constants.js) with per-note overrides
- **Persistence guarantee**: Export utilities in [`dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/dbml.js) and [`documentation.js`](https://github.com/drawdb-io/drawdb/blob/main/documentation.js) preserve notes across formats
- **React-native architecture**: Pure state updates ensure UI consistency without external dependencies

## Frequently Asked Questions

### Where are notes stored in DrawDB's codebase?

Notes live in a React context defined in [`src/context/NotesContext.jsx`](https://github.com/drawdb-io/drawdb/blob/main/src/context/NotesContext.jsx), with the hook interface at [`src/hooks/useNotes.js`](https://github.com/drawdb-io/drawdb/blob/main/src/hooks/useNotes.js). This pattern keeps note state accessible throughout the component tree while avoiding prop drilling.

### Can notes be exported with the database schema?

Yes. The DBML export utility in [`src/utils/exportAs/dbml.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportAs/dbml.js) serializes notes alongside tables, including their content and canvas coordinates. Notes also appear in PNG exports and shareable URLs through [`src/utils/exportAs/documentation.js`](https://github.com/drawdb-io/drawdb/blob/main/src/utils/exportAs/documentation.js).

### How does DrawDB position notes on the canvas?

Each note stores `x` and `y` pixel coordinates in its state object. When rendered, the note component applies these as absolute CSS positioning values. Drag operations update these coordinates through `updateNote`, with the new position persisting immediately.

### Is there a default style for new notes?

Yes. [`src/data/constants.js`](https://github.com/drawdb-io/drawdb/blob/main/src/data/constants.js) exports `defaultNoteTheme` set to `#fcf7ac` (light yellow). This value applies automatically when creating notes, though users can change individual note colors through the editing interface.