Concepts

The note primitive

Notr knows what a note is and nothing more. Understanding that one primitive — and what it deliberately leaves out — is most of what there is to learn.

Anatomy of a note

type Note = {
  id: string                          // stable, never changes
  ydoc: Uint8Array                    // canonical Yjs document (source of truth)
  markdown: string                    // derived projection, read-only
  metadata?: Record<string, unknown>  // yours — Notr never interprets it
  createdAt: Date
  updatedAt: Date
}
  • The Yjs document is the source of truth. It's a CRDT — concurrent edits from any number of collaborators merge deterministically. You never read or write it directly; the editor and the collaboration server do.
  • Markdown is a projection. Notr re-derives it from the Yjs document every time the note is stored. It's what you read over the REST API. Writing to it is not supported — it would immediately be overwritten by the next sync.
  • Metadata is an uninterpreted bag. Tag notes with anything your integration needs (an external ID, a source label). Notr stores and returns it, nothing else.

The consumer ownership model

Your application keeps its own entities and its own database. A Notr note never knows what it's for — the association lives on your side:

your backend
// 1. create the note in Notr
const res = await fetch('https://notr.example/api/notes', {
  method: 'POST',
  headers: { 'x-api-key': process.env.NOTR_KEY }
})
const note = await res.json()

// 2. attach it to YOUR entity, in YOUR database
await db.meetings.create({
  title: 'Weekly Sync',
  noteId: note.id
})

The same pattern covers wiki pages, documentation, CRM records, support tickets, and AI agent memory. One primitive, any domain.

What Notr will never model

Hierarchies, folders, projects, meetings, tasks, calendars, permissions between your end-users — these are application concepts, and different applications model them differently. Notr's rule of thumb: if two consumers would reasonably implement something in two different ways, it doesn't belong in the infrastructure.

The same line holds for files and images. A note can contain media, but Notr stores only a reference — a URL plus a little metadata — never the bytes. Your application owns storage, just as it owns the database. The editor's onUpload hook is the seam: you take the file, put it wherever you keep blobs, and hand back a URL. Notr stays a note engine, not a file manager.

Lifecycle

  1. CreatePOST /api/notes from your backend. The note starts empty.
  2. Edit — collaborators connect through the editor; changes sync live and are persisted automatically (debounced, at most a few seconds behind).
  3. ReadGET /api/notes/:id returns the markdown projection and metadata whenever you need the content outside the editor.
  4. DeleteDELETE /api/notes/:id removes the note permanently. Your noteId reference stops resolving; clean it up on your side.

Next: Identity & keys — who owns notes and how requests authenticate.