Document Formats

Detailed specifications of the document formats used by each Cloudillo application.

Overview

Each Cloudillo app stores collaborative documents using application-specific data models. Most apps use Yjs CRDTs for conflict-free concurrent editing, while some use the Real-Time Database (RTDB) for query-oriented structured data. This section provides the complete format specification for each app’s document structure, enabling third-party developers, tool builders, and contributors to understand, extend, and interoperate with Cloudillo documents.

Relationship to CRDT Design Guide

The CRDT Design Guide teaches generic patterns for building collaborative apps (ID-based storage, style inheritance, separate content maps). This section documents the concrete format specifications — the exact field names, types, and structures used by each app.

Application Formats

Application Content Type Storage Complexity Status
Prezillo application/vnd.cloudillo.prezillo+json CRDT (Yjs) High (14 object types, palette, templates) Documented
Calcillo application/vnd.cloudillo.calcillo+json CRDT (Yjs) Medium (cells, formulas, sheets) Documented
Ideallo application/vnd.cloudillo.ideallo+json CRDT (Yjs) Medium (9 object types, linked copies) Documented
Notillo application/vnd.cloudillo.notillo+json RTDB Low (rich text document) Planned
Quillo application/vnd.cloudillo.quillo+json CRDT (Yjs) Low (rich text editor) Planned

Common Conventions

Compact Field Names

CRDT-based apps use short field names (typically 1-3 characters) to minimize wire overhead during real-time synchronization. For example, t for type, xy for position, wh for dimensions. Each app’s format spec documents the mapping from compact names to their meanings.

ID Format

All entity IDs (objects, containers, views, styles, templates) use 72-bit entropy encoded as 12 base64url characters. IDs are generated client-side using crypto.getRandomValues() and are typed using branded types (ObjectId, ContainerId, ViewId, StyleId, RichTextId, TemplateId) for compile-time safety.

ChildRef Tuples

Several apps use a ChildRef tuple to reference children that can be either objects or containers:

type ChildRef = [0 | 1, string]  // [0, objectId] or [1, containerId]

The discriminant (0 or 1) allows a single ordered array to contain references to both types without ambiguity.

v3 Generic Export Format

Starting with format version 3.0.0, all CRDT-based apps use a unified export function (exportYDoc()) from @cloudillo/crdt. This function walks yDoc.share and serializes all shared types with inline @T type markers that preserve the original Yjs type information.

Export Envelope

Every exported document shares this envelope structure:

{
  "contentType": "application/vnd.cloudillo.<app>+json",
  "appVersion": "<semver>",
  "formatVersion": "3.0.0",
  "exportedAt": "<ISO 8601 timestamp>",
  "data": { ... }
}

The data object contains one entry per top-level Yjs shared type, using the raw CRDT key names (e.g., o, r, m instead of objects, rootChildren, meta).

@T Type Markers

Each Yjs type is serialized with an inline marker so importers can reconstruct the correct Yjs type:

Yjs Type Marker Serialized Form
Y.Map "@T": "M" { "@T": "M", "key1": ..., "key2": ... }
Y.Array "@T:A" [ "@T:A", element1, element2, ... ]
Y.Text "@T": "T" { "@T": "T", "text": "...", "delta": [...] }
Y.XmlText "@T": "XT" { "@T": "XT", "text": "...", "delta": [...] }
Y.XmlElement "@T": "XE" { "@T": "XE", "n": "...", "a": {...}, "c": [...] }
Y.XmlFragment "@T": "XF" { "@T": "XF", "c": [...] }

Nested types are serialized recursively. For example, a Y.Map<Y.Text> becomes a map with "@T": "M" containing entries that each have "@T": "T" with text and delta fields.

Primitive values pass through

Plain values (strings, numbers, booleans, null) inside Yjs types are serialized as-is without markers. The @T marker only appears on Yjs shared types.

Changes from Previous Versions

Aspect Pre-v3 v3
Data keys Long descriptive names (objects, rootChildren, richTexts) Raw CRDT keys (o, r, rt)
Type information Implicit (consumer must know the schema) Explicit @T markers on every Yjs type
Text content Plain text string or { plainText, delta } { "@T": "T", "text": "...", "delta": [...] }
Export function App-specific custom serialization Generic exportYDoc() from @cloudillo/crdt
Format version App-specific (1.0.0 or 2.0.0) Unified 3.0.0 across all apps

See Also