Templates
Build per-collection page templates that decide how pages, events, posts, and other records render
A template controls how a specific content type renders. A page template controls the page layout. An event template controls how the event shows its date and venue. A post template controls how the post shows its author and body. Templates live in templates/ as either base templates like page.liquid or named alternates like page.landing.liquid.
Each collection, such as a page, event, or post, has its own field reference describing its data shape. See Template references.
Start with the required theme structure and a working layouts/default.liquid.
Steps
1. Create a template file
Templates use the .liquid extension and follow a strict naming convention:
templates/[collection].liquid
templates/[collection].[name].liquidThe collection is the segment before the first dot. The name is the second segment. If the filename has only one segment, the name defaults to default.
| Filename | Collection | Name |
|---|---|---|
templates/page.liquid | page | default runtime template |
templates/page.landing.liquid | page | landing alternate |
templates/event.featured.liquid | event | featured alternate |
templates/blog.liquid | blog | default |
templates/post.archive.liquid | post | archive |
templates/person.liquid | person | default |
The filename, not the schema, sets the collection and the variant name. When you upload the theme, Basker reads each template's collection and name from the filename. Basker records them in the theme. Editors choose a variant, such as landing, featured, or archive, when they assign a template to a record. Give files clear variant names, because that name is what editors see.
2. Write the template markup
Templates are HTML mixed with Liquid output tags and control flow. Basker exposes the current document as a variable that matches the collection name. For a page template, use page:
<article class="page">
<header class="page__header">
<h1>{{ page.title }}</h1>
{% if page.description %}
<p class="page__description">{{ page.description }}</p>
{% endif %}
</header>
{% if page.image %}
<figure class="page__hero">
<img
src="{{ page.image | image_url: width: 1200 }}"
alt="{{ page.image.alt }}"
width="{{ page.image.width }}"
height="{{ page.image.height }}"
>
</figure>
{% endif %}
<div class="page__body">
{% stageblocks page %}
</div>
</article>Use {% render 'snippet-name' %} to include partials from snippets/.
{% render 'breadcrumbs', page: page %}
{% render 'social-sharing', title: page.title, url: request.url %}The {% include %} tag is deprecated. Use {% render %} instead.
3. Add a schema definition
Every template should include a {% schema %} tag with a JSON object. The schema defines two things. Settings are fields that editors enter for each page. Blocks are the block types allowed on this template.
Place the schema at the end of the file:
{% schema %}
{
"settings": [
{
"type": "checkbox",
"name": "show_breadcrumbs",
"label": "Show breadcrumbs",
"defaultValue": true
},
{
"type": "select",
"name": "header_style",
"label": "Header style",
"options": [
{ "label": "Standard", "value": "standard" },
{ "label": "Hero", "value": "hero" },
{ "label": "Minimal", "value": "minimal" }
],
"defaultValue": "standard"
}
],
"blocks": [
"text-section",
"image-gallery",
"call-to-action",
"featured-events"
]
}
{% endschema %}The settings array defines fields that appear in the editor. Each field requires type, name, and label. The required and defaultValue properties are optional.
The blocks array lists allowed block types as strings. Each string matches the name property in the block's schema. You can also write each block as an object:
{
"blocks": [
"text-section",
{ "name": "image-gallery" },
{ "type": "call-to-action" }
]
}4. Access template settings in markup
Template settings are available on the document at page.theme.settings:
{% assign show_breadcrumbs = page.theme.settings.show_breadcrumbs %}
{% if show_breadcrumbs %}
{% render 'breadcrumbs', page: page %}
{% endif %}
{% assign header_style = page.theme.settings.header_style %}
<header class="page__header page__header--{{ header_style }}">
<h1>{{ page.title }}</h1>
</header>Complete example
A full event.featured.liquid template for an arts venue:
{% assign show_series = event.series != blank %}
<article class="event event--featured">
<header class="event__header">
{% if event.image %}
<div class="event__hero">
<img
src="{{ event.image | image_url: width: 1600, height: 900, fit: 'cover' }}"
alt="{{ event.image.alt | default: event.title }}"
loading="eager"
>
</div>
{% endif %}
<div class="event__header-content">
{% if show_series %}
<a href="/series/{{ event.series.slug }}" class="event__series-link">
{{ event.series.title }}
</a>
{% endif %}
<h1 class="event__title">{{ event.title }}</h1>
{% if event.subtitle %}
<p class="event__subtitle">{{ event.subtitle }}</p>
{% endif %}
{% if event.venue %}
<p class="event__venue">
<a href="/venues/{{ event.venue.slug }}">{{ event.venue.title }}</a>
</p>
{% endif %}
</div>
</header>
<div class="event__body">
{% if event.richDescription_html %}
<div class="event__description rich-text">
{{ event.richDescription_html }}
</div>
{% endif %}
{% stageblocks event %}
</div>
{% render 'event-sidebar', event: event %}
</article>
{% schema %}
{
"settings": [
{
"type": "checkbox",
"name": "show_related_events",
"label": "Show related events",
"defaultValue": true
},
{
"type": "number",
"name": "related_events_count",
"label": "Number of related events to display",
"defaultValue": 4
}
],
"blocks": [
"text-section",
"image-gallery",
"video-embed",
"pull-quote",
"performer-list",
"booking-widget"
]
}
{% endschema %}This template renders when an editor assigns the featured template to an event in the admin.
Troubleshooting
"Template filename is not in the expected format": The file must be a base template such as page.liquid or a named alternate such as page.landing.liquid. Make sure the filename has a collection segment and the .liquid extension.
"Invalid template schema JSON": JSON syntax error inside {% schema %}. Validate it with a JSON linter. Common: trailing commas, unquoted keys, single quotes.
"Template references missing block": A block name in the blocks array does not match any file in blocks/. Verify that the block's name in its schema matches the string.
Rich text fields render as true instead of HTML: Basker splits each rich text field into two properties. Use field_name_html for the HTML. The plain field_name is a boolean.
Related
- Layouts: configure the layout that wraps templates.
- Template context: variables available in templates.
- Blocks: define blocks referenced in template schemas.
- Rendering blocks: the
stageblockstag. - Block schema reference: field types for settings.
- Template references: per-collection data shape.