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
- Template prototype objects are stored in the
tpomap:TemplateId → Y.Array<ObjectId>. These are regular objects stored in theomap, but logically belonging to a template. - Instance objects reference a prototype via their
protofield (anObjectIdpointing to the prototype). - 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