Accent

The content region

Where authored content lands, and what a template owns around it.


A document template marks where the page's body lands by putting data-accent-content on an element — the same attribute a section's editable regions use. Declaring the region hands the reins to the canvas: the CMS owns that element's interior.

<main class="container py-4" data-accent-content>
  <p>Placeholder — shown when the template is previewed standalone.</p>
</main>

The rules

  • The element survives; its children are replaced. Whatever the source puts inside the region is standalone-preview placeholder — the page body replaces it at render. Style the region element directly; it is the wrapper.
  • First in source order wins. If several elements are marked, the body lands in the first one.
  • No region means a static template. It renders exactly as written — the import story: bring a static HTML file in as a template, bind it, done. Nothing warns and nothing blocks; binding is the whole story.
  • No live composition inside a region. A require() as a region child is illegal — the reins were handed over.
  • data-zone (an id, for the API lanes) and data-label (a human name) are welcome on the region and mean the same thing they mean everywhere; neither changes where the body lands.

Regions arriving through require()

The render decides whether to inject by reading the template's own file — so a region living inside a require()d wrap doesn't fire by itself. To use one, declare the intent in the template's frontmatter:

---
kind: document
id: pages/universal-page
receives: page-content
---
<!doctype html>
<html><body>
  <%- require('/site/templates/sections/two-column.ejs')() %>
</body></html>

receives: page-content says "this template receives the page body" — the splice then targets the first region in the rendered output, wherever it came from. Authored intent, never inference. (Declaring it while also printing <%- content %> renders the body twice — the declaration is your statement that you don't.)

Where templates stop

A template carries at most one landing region — it is the document shell, not a composition surface. If you want several editable areas arranged around the body ("Zone 1", "Zone 2", each with its own editor and its own row in the document map), that is a Layout — set the type's Content renderer to Layout and compose it visually. Editable zones inside the body are sections (see Sections and regions). The division is deliberate: templates are design-in-code chrome; Layouts are the visual way to build the same kind of artifact; neither duplicates the other.

This holds for imported pages too: when bringing a multi-area page in as a template, swap its chrome for require() mounts (fixed, design-owned) and keep one landing region — structure that should edit goes in the body as sections.

The legacy marker

Templates written as classic EJS shells keep working, permanently:

<main><%- content %></main>

content is an EJS local the render supplies. New templates should prefer the region form — one grammar across templates, sections, and layouts.

There is no "document" flag

Nothing inspects a template to decide what it is — no capability flag, no source sniffing, no warnings. Bind a template to a type (or a page, under delegation) and it renders; with a region the body lands inside it, without one it renders as-is. If classifying templates ever becomes useful, that will be an authored System Taxonomy — never inference.

Deep records

The content model — design record — the full marker lineage and each ruling's reasoning, ending in the region grammar.