Working starting points. Paste one into a new layout, hit Preview, then make it yours. Every recipe uses only the documented tokens — see the token reference for what each one does, and the overview for how to create and bind a layout.
All of these put {{{theme.cssBlock}}} in the <head> so the channel palette flows through as --brand-* CSS variables. Change the look by editing the palette in Default-appearance mode, not by hard-coding colours here.
1. Article / page detail
Bind this as the default article/page layout, or pick it on a single article.
<!doctype html>
<html lang="{{site.cultureCode}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{article.title}} — {{channel.name}}</title>
{{{theme.cssBlock}}}
<style>
body { margin: 0; background: var(--brand-surface); color: var(--brand-text);
font-family: var(--brand-font-body); }
main { max-width: 720px; margin: 3rem auto; padding: 0 1rem; line-height: 1.7; }
h1 { font-family: var(--brand-font-heading); font-size: 2.25rem; }
.byline { color: var(--brand-muted); margin-bottom: 2rem; }
img { max-width: 100%; height: auto; }
a { color: var(--brand-primary); }
</style>
</head>
<body>
{{> site-header}}
<main>
<h1>{{article.title}}</h1>
<p class="byline">
{{#if article.author.name}}By {{article.author.name}} · {{/if}}{{article.publishedAt}}
</p>
{{#if article.coverImage}}<img src="{{article.coverImage}}" alt="">{{/if}}
{{{article.body}}}
</main>
{{> site-footer}}
</body>
</html>
2. Channel home (article list)
Bind this as the Channel home layout.
<!doctype html>
<html lang="{{site.cultureCode}}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{channel.name}}</title>
{{{theme.cssBlock}}}
<style>
body { margin: 0; background: var(--brand-surface); color: var(--brand-text);
font-family: var(--brand-font-body); }
main { max-width: 960px; margin: 2rem auto; padding: 0 1rem; }
.grid { display: grid; gap: 1.5rem; grid-template-columns: repeat(auto-fill,minmax(280px,1fr)); }
.card { border: 1px solid var(--brand-muted); border-radius: 8px; overflow: hidden; }
.card img { width: 100%; display: block; }
.card .pad { padding: 1rem; }
.card h2 { font-family: var(--brand-font-heading); font-size: 1.15rem; margin: 0 0 .5rem; }
.card a { color: var(--brand-text); text-decoration: none; }
</style>
</head>
<body>
{{> site-header}}
<main>
<div class="grid">
{{#each articles}}
<article class="card">
{{#if coverImage}}<a href="{{url}}"><img src="{{coverImage}}" alt=""></a>{{/if}}
<div class="pad">
<h2><a href="{{url}}">{{title}}</a></h2>
{{#if excerpt}}<p>{{excerpt}}</p>{{/if}}
</div>
</article>
{{/each}}
</div>
</main>
{{> site-footer}}
</body>
</html>
3. Asset page
Bind this as the Asset page layout.
<!doctype html>
<html lang="{{site.cultureCode}}">
<head>
<meta charset="utf-8">
<title>{{asset.title}} — {{channel.name}}</title>
{{{theme.cssBlock}}}
<style>
body { margin: 0; background: var(--brand-surface); color: var(--brand-text);
font-family: var(--brand-font-body); text-align: center; }
main { max-width: 900px; margin: 2rem auto; padding: 0 1rem; }
img, video { max-width: 100%; height: auto; border-radius: 8px; }
</style>
</head>
<body>
{{> site-header}}
<main>
<h1>{{asset.title}}</h1>
{{#if asset.isImage}}<img src="{{asset.url}}" alt="{{asset.title}}">{{/if}}
{{#if asset.isVideo}}<video src="{{asset.url}}" controls></video>{{/if}}
{{#if asset.description}}<p>{{asset.description}}</p>{{/if}}
</main>
{{> site-footer}}
</body>
</html>
4. Shared header & footer partials
All three recipes above reference {{> site-header}} and {{> site-footer}}. Create two partials so the chrome is written once. (The partial Id is derived from the name — "Site header" becomes site-header.)
Partial: Site header
<header style="padding:1rem;border-bottom:1px solid var(--brand-muted)">
<a href="/{{site.cultureCode}}/c/{{channel.slug}}"
style="color:var(--brand-text);text-decoration:none;font-weight:600">
{{#if channel.logo}}<img src="{{channel.logo}}" alt="" style="height:28px;vertical-align:middle"> {{/if}}
{{channel.name}}
</a>
</header>
Partial: Site footer
<footer style="padding:2rem 1rem;text-align:center;color:var(--brand-muted);font-size:.9rem">
{{#if theme.footer.copyright}}{{theme.footer.copyright}}{{else}}© {{site.currentYear}} {{channel.name}}{{/if}}
</footer>
5. One universal layout for every surface
Because missing tokens render empty, a single layout can cover all three surfaces by branching on what data is present. This is essentially the skeleton a new layout starts from — bind the same layout to Channel home, Asset page, and the default article layout, and it does the right thing on each.
<!doctype html>
<html lang="{{site.cultureCode}}">
<head>
<meta charset="utf-8">
<title>{{channel.name}}</title>
{{{theme.cssBlock}}}
</head>
<body>
{{> site-header}}
<main style="max-width:820px;margin:2rem auto;padding:0 1rem">
{{#if article}}
<article>
<h1>{{article.title}}</h1>
{{{article.body}}}
</article>
{{/if}}
{{#if articles}}
{{#each articles}}
<article style="padding:1rem 0;border-bottom:1px solid var(--brand-muted)">
<h2><a href="{{url}}">{{title}}</a></h2>
{{#if excerpt}}<p>{{excerpt}}</p>{{/if}}
</article>
{{/each}}
{{/if}}
{{#if asset}}
<h1>{{asset.title}}</h1>
{{#if asset.isImage}}<img src="{{asset.url}}" alt="{{asset.title}}" style="max-width:100%">{{/if}}
{{#if asset.isVideo}}<video src="{{asset.url}}" controls style="max-width:100%"></video>{{/if}}
{{/if}}
</main>
{{> site-footer}}
</body>
</html>
- Create the two partials (Site header, Site footer) first — recipes 1–3 reference them.
- Create a layout, paste recipe 5, Preview. The sandboxed preview ships sample article + list + asset data, so all three branches render at once.
- Bind it as Channel home and as the default article layout. Visit the home and an article — each shows only its relevant branch with real data.
- Swap in recipes 1–3 as separate layouts when you want each surface tuned individually instead of one shared template.
See also
- Custom layouts — modes, binding, rollback.
- Layout tokens — the full token reference.