templates and prototypes

Templates provide reusable slide backgrounds, dimensions, snap guides, and prototype objects for consistent presentation design.

What Templates Provide

A template defines:

  • Default dimensions for views using this template
  • Background (color, gradient, and/or image) that views inherit when their own background fields are absent
  • Snap guides for aligning objects to a consistent layout grid
  • Prototype objects that views can instantiate with single-level property inheritance

StoredTemplate Fields

Templates are stored in the tpl map, keyed by TemplateId.

Field Type Default Description
n string (required) Template name (e.g., "Title Slide", "Two Column")
w number (required) Default page width
h number (required) Default page height
bc string Background color (hex)
bg StoredBackgroundGradient Background gradient
bi string Background image file ID
bf 'contain' | 'cover' | 'fill' | 'tile' Background image fit mode
sg StoredSnapGuide[] Snap guides for object alignment

Snap Guides

Snap guides are visual and functional alignment lines defined by templates.

StoredSnapGuide

Field Type Description
d 'h' | 'v' Direction: h=horizontal, v=vertical
p number Position: percentage (0–1) or absolute pixels
a boolean If true, p is in absolute pixels; otherwise p is a percentage of the view dimension

Example: A centered two-column layout with margin guides:

{
  "sg": [
    { "d": "v", "p": 0.1 },
    { "d": "v", "p": 0.5 },
    { "d": "v", "p": 0.9 },
    { "d": "h", "p": 0.1 },
    { "d": "h", "p": 0.9 }
  ]
}

Template-to-View Relationship

A view references a template via its tpl field:

// View with template
{
  name: 'Title Slide',
  x: 0, y: 0,
  width: 1920, height: 1080,
  tpl: 'Hw5_qT2mLkJx'  // TemplateId
  // No backgroundColor → inherits from template
}

Background resolution: The view’s own background fields (backgroundColor, backgroundGradient, backgroundImage) take precedence. When absent, the template’s background (bc, bg, bi) is used as a fallback.

Prototype System

Templates can define prototype objects — objects that serve as editable defaults for views using the template.

How It Works

graph LR
    T["Template<br/>(tpl map)"] -->|"defines"| P["Prototype Object<br/>(o map, referenced via tpo)"]
    P -->|"proto field"| I["Instance Object<br/>(o map, in a view)"]

    style T fill:#d4e6f1,stroke:#2980b9
    style P fill:#d5f5e3,stroke:#27ae60
    style I fill:#fdebd0,stroke:#e67e22
  1. Template prototype objects are stored in the tpo map: TemplateId → Y.Array<ObjectId>. These are regular objects stored in the o map, but logically belonging to a template.
  2. Instance objects reference a prototype via their proto field (an ObjectId pointing to the prototype).
  3. Property inheritance: Instance objects inherit all properties from their prototype. Only overridden properties need to be stored on the instance.

Storage

// tpo: Y.Map<Y.Array<string>>
// Key: TemplateId
// Value: array of ObjectIds that are prototypes for this template

const protoIds = doc.tpo.get(templateId)  // Y.Array<string>
// e.g., ["aB3x_Qm7kL9p", "Xk2nR8vH_wYq"]

Property Override Tracking

When a user modifies an instance:

  • The changed properties are stored directly on the instance object
  • Unchanged properties continue to resolve from the prototype
  • At render time, instance properties override prototype properties (similar to the style cascade)
Single-level inheritance

Prototype inheritance is deliberately single-level — an instance references one prototype, and prototypes do not chain to other prototypes. This keeps conflict resolution predictable: when two users concurrently modify a prototype and an instance, the CRDT can resolve the conflict without ambiguity across multiple inheritance levels.

Lock/Unlock

Prototype instances can be locked or unlocked:

  • Locked (k: true): The instance cannot be individually edited; it reflects prototype changes automatically
  • Unlocked: The instance can be edited independently, with changes stored as overrides