Skip to content

Core concepts

Documents

Documents are the unit of sync in Syndra typed JSON trees that merge automatically.

On this page

A document is a JSON value identified by a path such as lists/groceries. Every client that opens the same path shares the same state.

ts
const doc = syndra.doc("boards/roadmap")

Anatomy of a document

Under the hood, each document is a CRDT: a history of small operations rather than a single blob. That’s what lets two people edit the same document at the same time without overwriting each other.

Property Type Description
path string Unique identifier within the project.
state T The current merged value.
version VersionVector Which operations this replica has seen.
status 'synced' | 'pending' | 'offline' Whether local changes have reached the server.

Reading

Read the current value synchronously, or subscribe to changes:

ts
const current = doc.get()

const unsubscribe = doc.subscribe((state, meta) => {
  console.log(state, meta.origin) // 'local' | 'remote'
})

Selecting part of a document

Pass a selector to only re-run when a slice changes. This keeps large documents cheap to observe.

ts
doc.subscribe(
  (state) => state.items.length,
  (count) => (badge.textContent = String(count)),
)

Writing

All writes go through update. The draft is a mutable proxy change it however you like, and Syndra turns your edits into operations.

ts
doc.update((draft) => {
  draft.title = "Q3 Roadmap"
  draft.columns[0].cards.push({ id: "c_91", text: "Ship presence v2" })
})

Lifecycle

Documents load lazily and are released when nothing references them. Call doc.dispose() in long-lived apps when a view unmounts; framework bindings do this for you.