Template context
Every variable, global function, and collection drop available in Liquid templates rendered by Basker
| Category | Examples | Access pattern |
|---|---|---|
| Globals | tenant, navigation, settings | Reference by name, no parentheses: {{ tenant.name }} |
| Collection drops | all_events, all_pages, all_venues | Property access by slug or ID: {{ all_events.moonclock }} |
| Document context | page, event, post | Direct property access on the current document variable |
Globals
Available in any template or layout, scoped to the current tenant and request. Reference them by name without parentheses: {{ tenant.name }}, not {{ tenant().name }}. Adding parentheses is a syntax error and stops the page rendering.
Globals are also available inside a {% render %} partial. Document variables such as page and event are not globals. A partial sees them only when you pass them in:
{% render 'event-card', event: event %}tenant
Returns: Object. The current tenant.
| Property | Type | Description |
|---|---|---|
id | string | Tenant ID |
name | string | Display name |
slug | string | URL-safe identifier |
<p>© {{ 'now' | date: '%Y' }} {{ tenant.name }}</p>navigation
Returns: Object. The navigation tree built from published pages where showInNavigation is enabled. Not iterable directly: use navigation.pages for the root pages, or navigation.<slug> for the children of a specific page.
| Property per node | Type | Description |
|---|---|---|
title | string | Page title |
slug | string | Page slug |
relativePath | string | Full URL path (e.g. /whats-on/events) |
url | string | Page URL |
description | string | Page description |
image | object | Associated image |
children | array | Child page nodes |
has_children | boolean | Whether child pages exist |
parent | object | Parent page node |
siblings | array | Sibling page nodes at the same level |
<ul>
{% for item in navigation.pages %}
<li><a href="{{ item.relativePath }}">{{ item.title }}</a></li>
{% endfor %}
</ul>Navigation nodes have no current-page or active flag. To mark the current item, compare its path with the current request path:
{% for item in navigation.pages %}
<a href="{{ item.relativePath }}"{% if item.relativePath == request.path %} aria-current="page"{% endif %}>{{ item.title }}</a>
{% endfor %}announcements
Returns: Array of announcements targeted to the current page. Filtered automatically by their targeting mode (all pages, specific collection, specific pages, URL pattern).
| Property | Type | Description |
|---|---|---|
title | string | Announcement title |
message | boolean | Whether a message exists |
message_html | string | Rendered HTML of the message |
targetingMode | string | One of all, collection, pages, simple |
{% assign alerts = announcements %}
{% for alert in alerts %}
<div class="announcement" role="alert">
{{ alert.message_html }}
</div>
{% endfor %}all_forms
Returns: Object indexed by form ID and slug. All forms for the current tenant.
| Property | Type | Description |
|---|---|---|
id | string | Form ID |
slug | string | Form slug |
title | string | Form title |
submitButtonLabel | string | Label for the submit button |
confirmationType | string | message or redirect |
confirmationMessage_html | string | Rendered confirmation message |
fields | array | The form's fields, in order |
Each item in fields has:
| Property | Type | Description |
|---|---|---|
blockType | string | Field type: text, textarea, email, number, select, checkbox, country, state, or message |
name | string | Field name to submit the value under |
label | string | Field label |
required | boolean | Whether the field is required |
defaultValue | mixed | Starting value, when set |
width | number | Suggested width as a percentage, when set |
options | array | For select fields: { label, value } items |
message_html | string | For message fields: the rendered message |
A form linked from a block relationship has the same properties.
{% assign forms = all_forms %}
{% assign contact_form = forms['contact-us'] %}
{% if contact_form %}
<p>{{ contact_form.title }}</p>
{% endif %}apps
Returns: Object. App configuration data for the current tenant, keyed by app handle. Basker includes only fields marked visible to the live site.
{% assign app_config = apps %}
{% if app_config.google.measurementID %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ app_config.google.measurementID }}"></script>
{% endif %}Values include:
| Property | Description |
|---|---|
apps.google.containerID | Google Tag Manager container ID |
apps.google.measurementID | Google Analytics measurement ID |
apps.tessitura.tnew.domain | TNEW domain, returned exactly as entered in the admin. It is nil when no domain is set. |
A value is nil when the app is not installed or the field is empty.
Basker does not add the Google Tag Manager container or the GA4 script to Liquid theme pages. If the site uses them, output them in your layout from apps.google.containerID and apps.google.measurementID. Include the Tag Manager <noscript> fallback after <body>. Do not hardcode a container ID.
settings
Returns: Object. Theme settings defined in config/settings_schema.json and configured in the admin. The object follows the shape of the schema. A field inside a group sits under the group's name: settings.<group>.<name>. A field placed directly in the schema array is settings.<name>. See Theme settings.
{% assign theme = settings %}
{% if theme.global.logo %}
<img src="{{ theme.global.logo | image_url: width: 200 }}" alt="{{ tenant.name }}">
{% else %}
<span class="site-title">{{ tenant.name }}</span>
{% endif %}attribute_definition
Returns: Object nested by namespace and key. Custom attribute definitions configured for the tenant.
{% assign attrs = attribute_definition %}
{% assign genre_attr = attrs.genre.name %}body_classes
Returns: String. CSS class names derived from the current template path. For templates/event.featured.liquid, returns "page page-featured".
<body class="{{ body_classes }}">content_for_header
Returns: String (HTML). System-injected content for the <head>: preconnect hints, generator meta tag, and preview-mode scripts when active.
<head>
{{ content_for_header }}
</head>forms_endpoint
Returns: String (URL). The base URL for the forms submission service. Basker uses it internally in {% form %}. Custom form implementations can also use it.
<form method="POST" action="{{ forms_endpoint }}/forms/{{ contact_form.id }}/submit">
...
</form>request
Returns: Object. Information about the current HTTP request.
| Property | Type | Description |
|---|---|---|
url | string | Full request URL including protocol and host |
path | string | URL path (e.g. /events/moonclock) |
method | string | HTTP method (e.g. GET) |
query | object | Parsed URL query parameters |
{% assign req = request %}
<link rel="canonical" href="{{ req.url }}">site
Returns: Object. Site root URL.
| Property | Type | Description |
|---|---|---|
url | string | Absolute root URL (e.g. https://remarkable-theatre.example) |
locale
Returns: String. The current locale code (e.g. en, cy, fr).
<html lang="{{ locale }}">locale_prefix
Returns: String. The URL path prefix for the current language: /cy on a non-default language, and an empty string on the default language. Prepend it to hand-built internal links so they stay in the active language.
<a href="{{ locale_prefix }}/contact">Contact</a>Links taken from a record's url or relativePath property, or from navigation, already include this prefix. Only manually assembled paths need it.
localization
Returns: Object. The language configuration for the current site.
| Property | Type | Description |
|---|---|---|
available_languages | array | Language codes the site offers |
current_language | string | The active language code |
default_language | string | The site's default language code |
{% assign l10n = localization %}
{% assign current_path = request.path %}
{% if locale_prefix != blank %}
{% assign current_path = current_path | remove_first: locale_prefix %}
{% endif %}
{% if current_path == blank %}
{% assign current_path = "/" %}
{% endif %}
{% for lang in l10n.available_languages %}
{% if lang == l10n.default_language %}
{% assign href = current_path %}
{% else %}
{% assign href = "/" | append: lang | append: current_path %}
{% endif %}
<a href="{{ href }}"{% if lang == l10n.current_language %} aria-current="true"{% endif %}>
{{ lang | upcase }}
</a>
{% endfor %}See Localization for a complete language switcher and translation setup.
routes
Returns: Object. Common site paths, prefixed for the active language.
| Property | Type | Description |
|---|---|---|
root_url | string | The site root: /cy/ on a non-default language, / on the default |
<a href="{{ routes.root_url }}">Home</a>is_preview
Returns: Boolean. Whether the current request is in preview mode.
{% if is_preview %}
<div class="preview-badge">Preview Mode</div>
{% endif %}Collection drops
Collection drops provide access to all documents of a given collection. Each supports two access patterns:
- Lookup by slug or ID:
{{ all_events.moonclock }}returns a single document. - List iteration: iterate the drop directly, with optional page and limit query parameters (
all_events_limit,all_events_page).
Basker lazy-loads and caches lookups per request. Basker enforces a maximum of 20 unique lookups per drop per request.
| Drop | Collection | Lookup fields |
|---|---|---|
all_events | events | slug |
all_venues | venues | slug |
all_blogs | blogs | slug |
all_categories | categories | slug |
all_organizations | organizations | slug |
all_pages | pages | slug, relativePath |
all_people | people | slug |
all_posts | posts | slug |
all_seasons | seasons | slug |
all_series | series | slug |
all_tags | tags | slug |
all_works | works | slug |
Lookup example:
{% assign venue = all_venues.main-hall %}
{% if venue %}
<p>{{ venue.title }} - {{ venue.website }}</p>
{% endif %}Pagination query parameters control list output via URL query:
| Parameter | Type | Default | Description |
|---|---|---|---|
all_events_limit | number | 50 | Documents per page (max 50) |
all_events_page | number | 1 | Page number |
Replace all_events with the relevant drop name (all_venues_limit, all_posts_page, etc.).
{% for event in all_events %}
<a href="{{ event.url }}">{{ event.title }}</a>
{% endfor %}Document context
Each route sets one variable for the record it renders. The other document variables are empty on that route. For example, page is empty on an event page.
| Route | Variable |
|---|---|
| Page | page |
| Event | event |
| Event instance (performance) | instance, plus event for its parent event |
| Post | post |
| Blog | blog |
| Season | season |
| Series | series |
| Person | person |
| Venue | venue |
| Organization | organization |
| Work | work |
| Smart collection | collection |
A layout or block that renders on more than one kind of route should not rely on one document variable. For the current path, use request.path, which is set on every route.
Data flattening behavior
Basker automatically flattens document data before it reaches Liquid templates. Understand these transformations to access data correctly.
Relationships
Relationship fields are available as the related document, or as an array of documents for a relationship that accepts multiple values.
{
"venue": {
"id": "000000000000000000000003",
"title": "Remarkable Theatre Main Hall",
"slug": "main-hall"
}
}Access:
{{ event.venue.title }}Rich text fields
Basker splits rich text fields into two properties:
| Property | Type | Description |
|---|---|---|
field_name | boolean | Always true when the field exists, even if it is empty |
field_name_html | string | Rendered HTML string |
{% if event.richDescription_html != blank %}
<div class="rich-text">
{{ event.richDescription_html }}
</div>
{% endif %}For more on rendering rich text in themes, see Field types reference.
Blocks
Basker flattens block data within documents to include id, blockType, and all field data at the top level.
| Property | Type | Description |
|---|---|---|
id | string | Block instance ID |
blockType | string | The block type name (theme block name for custom blocks) |
themeBlock | string | Original theme block identifier |
| All field names | mixed | Flattened field values from the block schema |
Theme settings on documents
When a document has per-document theme settings, they are available as:
{{ page.theme.settings.field_name }}A record with no saved template settings has no theme property. In Liquid, page.theme.settings.field_name is then nil, so give it a fallback with default.
Index
Tenant and site: tenant, site, locale, locale_prefix, localization, routes
Navigation and pages: navigation, all_pages
Content collections: all_events, all_venues, all_blogs, all_posts, all_people, all_organizations, all_seasons, all_series, all_works, all_categories, all_tags
Forms and announcements: all_forms, announcements, forms_endpoint
Theme and layout: settings, body_classes, content_for_header, apps, attribute_definition
Request context: request, is_preview
Related
- Writing templates: using context variables in templates.
- Writing layouts: using global functions in layouts.
- Rendering blocks: block rendering context.