document structure

The top-level CRDT document structure, initialization defaults, ID system, and metadata.

Top-Level Shared Types

A Prezillo document is a Y.Doc with 12 named shared types:

Map Key Yjs Type Description
o Y.Map<StoredObject> All drawable objects keyed by ObjectId
c Y.Map<StoredContainer> Layers and groups keyed by ContainerId
r Y.Array<ChildRef> Root-level children (ordered)
ch Y.Map<Y.Array<ChildRef>> Children arrays keyed by ContainerId
v Y.Map<StoredView> Views (slides/pages) keyed by ViewId
vo Y.Array<string> View order (presentation sequence of ViewId strings)
m Y.Map Document metadata
rt Y.Map<Y.Text> Rich text content keyed by ObjectId (Quill Delta)
st Y.Map<StoredStyle> Global style definitions keyed by StyleId
pl Y.Map<StoredPalette> Palette (single entry keyed by 'default')
tpl Y.Map<StoredTemplate> Templates keyed by TemplateId
tpo Y.Map<Y.Array<string>> Template prototype objects: TemplateIdObjectId[]
Why compact map keys?

Map keys like o, c, r are used instead of objects, containers, rootChildren because these keys appear in every Yjs sync message. Shorter keys reduce wire overhead during real-time collaboration without affecting readability — this documentation provides the complete mapping.

Accessing the Document

import * as Y from 'yjs'

const yDoc = new Y.Doc()

// Access each shared type by its map key
const objects    = yDoc.getMap('o')     // StoredObject entries
const containers = yDoc.getMap('c')     // StoredContainer entries
const root       = yDoc.getArray('r')   // Root ChildRef array
const children   = yDoc.getMap('ch')    // Per-container children
const views      = yDoc.getMap('v')     // StoredView entries
const viewOrder  = yDoc.getArray('vo')  // ViewId ordering
const meta       = yDoc.getMap('m')     // Metadata
const richTexts  = yDoc.getMap('rt')    // Y.Text entries
const styles     = yDoc.getMap('st')    // StoredStyle entries
const palette    = yDoc.getMap('pl')    // StoredPalette
const templates  = yDoc.getMap('tpl')   // StoredTemplate entries
const tplProtos  = yDoc.getMap('tpo')   // Template prototype arrays

ID System

All entity IDs use 72-bit entropy encoded as 12 base64url characters, generated client-side via crypto.getRandomValues().

Six branded types prevent accidental ID mixing at compile time:

Branded Type Used In Example
ObjectId o map keys, ChildRef[1] when [0] is 0 "aB3x_Qm7kL9p"
ContainerId c map keys, ch map keys, ChildRef[1] when [0] is 1 "Xk2nR8vH_wYq"
ViewId v map keys, vo array entries, object vi field "m4Jf_L1pZq8w"
StyleId st map keys, object si/ti fields, style p field "Nz9cK_vW3xRb"
RichTextId rt map keys (same value as ObjectId for text objects) "aB3x_Qm7kL9p"
TemplateId tpl map keys, tpo map keys, view tpl field "Hw5_qT2mLkJx"

ChildRef Convention

The ChildRef tuple encodes a reference that can point to either an object or a container:

type ChildRef = [0 | 1, string]
//               ^       ^
//               |       └── ObjectId or ContainerId
//               └── 0 = object, 1 = container

Examples:

  • [0, "aB3x_Qm7kL9p"] — references an object
  • [1, "Xk2nR8vH_wYq"] — references a container (layer or group)

ChildRef arrays are used in the root children (r) and per-container children (ch) to maintain draw order.

Metadata

The m map stores document-level settings as individual key-value entries:

Key Type Default Description
name string "Untitled Presentation" Document name
defaultViewWidth number 1920 Default width for new views
defaultViewHeight number 1080 Default height for new views
gridSize number Grid spacing in pixels (if grid enabled)
snapToGrid boolean Whether objects snap to grid
snapToObjects boolean Whether objects snap to other objects

Document Initialization

When a new empty document is created, the following defaults are established in a single Yjs transaction:

  1. Default layer: A container of type 'L' named "Layer 1" with expanded state (x: true), added to root children as [1, layerId]
  2. Default view: A view named "Page 1" at position (0, 0) with dimensions 1920×1080, white background, border visible
  3. Metadata: defaultViewWidth: 1920, defaultViewHeight: 1080, name: "Untitled Presentation"
  4. Default palette: The built-in palette with background, text, 6 accent colors, and 4 gradients (see Styling and Palette)
  5. Default styles: 10 built-in styles — 6 shape styles (Default Shape, Primary, Secondary, Accent, Outline, Connector) and 4 text styles (Default Text, Heading, Body, Caption) with parent-child inheritance chains

Rich Text Storage

Text objects (type 'T') store their formatted content as Y.Text entries in the rt map, keyed by the same ObjectId used in the o map. The Y.Text uses Quill Delta format for rich text operations (bold, italic, links, etc.).

A legacy tx field on the stored object held plain text in older documents. On load, migration code automatically converts tx strings to Y.Text entries in rt and removes the tx field.

Separate map for rich text

Rich text content is stored in the rt map, not embedded in the object data in o. This is because Y.Text is a Yjs shared type that needs its own identity for collaborative editing — it cannot be stored as a plain JSON value inside a Y.Map entry.