Back to Help

Layout tokens

May 17, 2026

The full token reference for custom layouts — every value you can interpolate, where each one resolves, the Handlebars basics, and the theme.cssBlock helper.


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.
Missing tokens render empty, not error. Referencing {{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

TokenValue
{{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

TokenValue
{{{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

TokenValue
{{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

TokenValue
{{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

TokenValue
{{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.

Try it.
  1. 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}}.
  2. In a layout, add {{> site-footer}} just before </body>. Preview — the footer renders with the channel name and year filled in.
  3. Edit the partial (change the text), save, re-preview the layout — the change shows without touching the layout.

See also

channels custom-layouts tokens handlebars reference