Custom layouts are Handlebars templates. This page is the reference: the Handlebars you'll actually use, every token the renderer hands you, and which page surfaces each token resolves on.
New to custom layouts? Start with the overview first; this page assumes you know what a layout and a surface are.
Handlebars in 30 seconds
{{token}}— insert a value, HTML-escaped. Safe for text.{{{token}}}— insert a value raw, no escaping. Use this only for values that are already HTML:{{{article.body}}}and{{{theme.cssBlock}}}.{{#if token}} … {{/if}}— render the block only when the value is present/true. The way to make one template handle multiple surfaces.{{#each list}} … {{/each}}— loop. Inside the block, the item's own fields are in scope directly ({{title}}, not{{articles.title}}).{{> partialId}}— include a partial.{{! a comment }}— not rendered.
{{article.title}} on the channel home (where there's no single article) just produces nothing — it doesn't break the page. That's why one layout can safely cover several surfaces if you wrap the surface-specific parts in {{#if article}} / {{#if articles}} / {{#if asset}}.
Where tokens resolve
A layout can be used on any surface. These groups are always available:
- channel, theme, site — resolve on every surface.
These depend on the surface the layout is rendering:
- article — article & page detail pages only.
- articles, topArticle — the channel home only.
- asset — asset pages only.
channel — everywhere
| Token | Value |
|---|---|
{{channel.name}} | Channel title |
{{channel.slug}} | URL permalink |
{{channel.tagline}} | Tagline from the theme header |
{{channel.logo}} | Logo URL from the theme header |
{{channel.description}} | Channel description |
theme — everywhere
| Token | Value |
|---|---|
{{{theme.cssBlock}}} | Pre-built <style> + Google Fonts <link> exposing the palette as --brand-* variables. Triple-stash, put it in <head>. |
{{theme.colors.primary}} | Primary hex (also accent, surface, text, muted) |
{{theme.fonts.heading}} | Heading font family (also body) |
{{theme.footer.copyright}} | Footer copyright line (also text) |
{{#each theme.social}} | Social links; each item has icon, url, label |
Prefer the CSS variables from {{{theme.cssBlock}}} over the raw hex tokens: write color: var(--brand-primary) in your styles, not color: {{theme.colors.primary}}. The variables update automatically when the palette changes; interpolated hex is frozen at render time. The variables are --brand-primary, --brand-accent, --brand-surface, --brand-text, --brand-muted, --brand-font-heading, --brand-font-body.
site — everywhere
| Token | Value |
|---|---|
{{site.url}} | Site base URL |
{{site.currentYear}} | Current year (handy for a footer) |
{{site.cultureCode}} | Culture, e.g. en — use in <html lang> |
article — article & page detail
| Token | Value |
|---|---|
{{article.title}} | Title |
{{{article.body}}} | Rendered article HTML. Triple-stash. |
{{article.excerpt}} | Short description / SEO summary |
{{article.publishedAt}} | Publish timestamp |
{{article.coverImage}} | Main image URL |
{{article.url}} | Canonical path to this article |
{{article.author.name}} | Byline name (also author.avatar, author.slug) |
{{#each article.tags}} | Tags; each item is the tag string ({{this}}) |
articles & topArticle — channel home
{{#each articles}} iterates the home list. Inside the loop each item exposes title, excerpt, publishedAt, coverImage, url, and author.name. {{topArticle.title}} (and the same fields) is the single most prominent article, for a hero slot.
{{#each articles}}
<article>
<a href="{{url}}"><h2>{{title}}</h2></a>
{{#if excerpt}}<p>{{excerpt}}</p>{{/if}}
</article>
{{/each}}
asset — asset pages
| Token | Value |
|---|---|
{{asset.title}} | Asset title |
{{asset.description}} | Description |
{{asset.url}} | The file URL |
{{#if asset.isImage}} | True for images — render an <img> |
{{#if asset.isVideo}} | True for video — render a <video> |
Partials
Include a partial with {{> partialId}}, where partialId is the Id shown in the Partials table on the Theme page. A partial sees the same data context as the layout that calls it — all the tokens above work inside a partial too — and a partial may include other partials. Use them for shared chrome: header, footer, a left menu, a reusable card.
- On the Theme page (Custom layouts mode), create a partial called Site footer with body
<footer>© {{site.currentYear}} {{channel.name}}</footer>. Its reference shows as{{> site-footer}}. - In a layout, add
{{> site-footer}}just before</body>. Preview — the footer renders with the channel name and year filled in. - Edit the partial (change the text), save, re-preview the layout — the change shows without touching the layout.
See also
- Custom layouts — the overview and the mode switch.
- Layout recipes — complete copy-paste templates that use these tokens.