Templates allow editors to centrally control content and reuse content. They allow a developer to not have to hard code layout decisions and instead use rules to apply user layouts in template content stored separately from the page, or give the user a choice on which layout they want.
Templates:
allowedTemplates and allowedLayouts applied to the blocks schema let the developer control loading templates: which templates are available for use, which are automatically applied as layouts, and which the editor can switch betweenexpandTemplates / expandTemplatesSync) to refresh templates found in the page content from the template content, and apply layouts based on rules (such as forcing a layout based on content type or metadata). Alternatively the frontend can write its own merge logic.Templates are analogous to blocks themselves but are made up of blocks with special properties. Each block in a template can be one of:
fixed: false / unset) — a named region (slotId) where editors can add their own blocks. Similar to a block field. The "default" slot receives leftover content.The slot a block lives in is identified by its slotId. This is the field name used by expandTemplates / expandTemplatesSync and by the merge rules below — not placeholder.
Configure templates in page.schema.properties on the blocks field:
null allows for a no-template option. If none of those templates are already set as the layout then during editing, the first is applied automatically.Use expandTemplates (async) or expandTemplatesSync (sync with pre-fetched templates) to merge template content during rendering.
isEditMode() and pass blocks through unchanged (just adding @uid). The admin handles template merging and adds nodeId attributes for inline editing.isEditMode() returns false so templates are expanded — this is correct since edit mode only exists in the browser iframe.Sync vs Async:
`loadTemplates(data, loadTemplate)` scans page data for templateId references and loads them all in parallel. It follows nested references (templates referencing other templates) and has a 5s per-template timeout. It only loads templates actually in the page data — allowedLayouts options are loaded on demand when a forced layout is applied.
Options:
{} and share across calls — tracks state for nested containersThe merge algorithm follows these rules:
templateId to replace, storing any that aren't fixed and readOnly by slotId.slotId; if a slot block, don't insert it, but insert the previous blocks with the same slotId."default" if it exists, otherwise are dropped.When a layout is applied, the rules are the same but applied across a whole blocks field. Content without a slotId ends up:
"default" slot if it existsYour frontend might want to force a layout to apply regardless of whether one is saved, for example to ensure a footer layout. Pass allowedLayouts:
Note: during editing the admin side will load the templates so in order to apply the same rules of forcing a layout you will need to set allowedLayouts in page.schema.properties to ensure the page loads with the right template.