Basker Docs

Template context

Every variable, global function, and collection drop available in Liquid templates rendered by Basker

CategoryExamplesAccess pattern
Globalstenant, navigation, settingsReference by name, no parentheses: {{ tenant.name }}
Collection dropsall_events, all_pages, all_venuesProperty access by slug or ID: {{ all_events.moonclock }}
Document contextpage, event, postDirect 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.

PropertyTypeDescription
idstringTenant ID
namestringDisplay name
slugstringURL-safe identifier
<p>&copy; {{ 'now' | date: '%Y' }} {{ tenant.name }}</p>

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 nodeTypeDescription
titlestringPage title
slugstringPage slug
relativePathstringFull URL path (e.g. /whats-on/events)
urlstringPage URL
descriptionstringPage description
imageobjectAssociated image
childrenarrayChild page nodes
has_childrenbooleanWhether child pages exist
parentobjectParent page node
siblingsarraySibling 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).

PropertyTypeDescription
titlestringAnnouncement title
messagebooleanWhether a message exists
message_htmlstringRendered HTML of the message
targetingModestringOne 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.

PropertyTypeDescription
idstringForm ID
slugstringForm slug
titlestringForm title
submitButtonLabelstringLabel for the submit button
confirmationTypestringmessage or redirect
confirmationMessage_htmlstringRendered confirmation message
fieldsarrayThe form's fields, in order

Each item in fields has:

PropertyTypeDescription
blockTypestringField type: text, textarea, email, number, select, checkbox, country, state, or message
namestringField name to submit the value under
labelstringField label
requiredbooleanWhether the field is required
defaultValuemixedStarting value, when set
widthnumberSuggested width as a percentage, when set
optionsarrayFor select fields: { label, value } items
message_htmlstringFor 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:

PropertyDescription
apps.google.containerIDGoogle Tag Manager container ID
apps.google.measurementIDGoogle Analytics measurement ID
apps.tessitura.tnew.domainTNEW 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.

PropertyTypeDescription
urlstringFull request URL including protocol and host
pathstringURL path (e.g. /events/moonclock)
methodstringHTTP method (e.g. GET)
queryobjectParsed URL query parameters
{% assign req = request %}
<link rel="canonical" href="{{ req.url }}">

site

Returns: Object. Site root URL.

PropertyTypeDescription
urlstringAbsolute 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.

PropertyTypeDescription
available_languagesarrayLanguage codes the site offers
current_languagestringThe active language code
default_languagestringThe 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.

PropertyTypeDescription
root_urlstringThe 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:

  1. Lookup by slug or ID: {{ all_events.moonclock }} returns a single document.
  2. 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.

DropCollectionLookup fields
all_eventseventsslug
all_venuesvenuesslug
all_blogsblogsslug
all_categoriescategoriesslug
all_organizationsorganizationsslug
all_pagespagesslug, relativePath
all_peoplepeopleslug
all_postspostsslug
all_seasonsseasonsslug
all_seriesseriesslug
all_tagstagsslug
all_worksworksslug

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:

ParameterTypeDefaultDescription
all_events_limitnumber50Documents per page (max 50)
all_events_pagenumber1Page 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.

RouteVariable
Pagepage
Eventevent
Event instance (performance)instance, plus event for its parent event
Postpost
Blogblog
Seasonseason
Seriesseries
Personperson
Venuevenue
Organizationorganization
Workwork
Smart collectioncollection

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:

PropertyTypeDescription
field_namebooleanAlways true when the field exists, even if it is empty
field_name_htmlstringRendered 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.

PropertyTypeDescription
idstringBlock instance ID
blockTypestringThe block type name (theme block name for custom blocks)
themeBlockstringOriginal theme block identifier
All field namesmixedFlattened 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

On this page