Globals
The variables every public template can read (site, sites, locale, locales, page, request, now, today, settings, singletons, nav, csrf, assets, devMode) with every key each one holds.
Globals are the variables every public page template receives, whatever the page is: entry pages, index pages, the search page, error pages, block and rich text templates, components and partials. The callable globals (path(), query(), t() and the rest) are on Functions; what each kind of page adds is on The page context.
<html lang="{{ locale.code }}" dir="{{ locale.direction }}">
<title>{{ page.title }} | {{ site.name }}</title>
<p>{{ settings.contact.phone }}</p>
<footer>© {{ now|date:"y" }} {{ site.organisation }}</footer> site
The site the request is for.
| Key | Value |
|---|---|
site.key | The site’s key, its folder name under config/sites/ |
site.name | The site’s name in the request locale |
site.shortName | short_name in the request locale, empty when not set |
site.organisation | organisation from site.yaml |
site.baseUrl | The site’s absolute base URL, on its configured domain |
site.domains | The site’s domains list |
site.country | country, an ISO 3166 code |
site.timezone | timezone, an IANA zone name |
site.defaultCurrency | default_currency, an ISO 4217 code. site.currency is the same value |
site.embedOnly | Whether the site runs in embed-only mode |
site.robots | noindex, follow in embed-only mode (the engine also sends it as an X-Robots-Tag header), else empty |
sites
On a project with more than one site, every site, each key, name (in the request locale) and baseUrl. Not set on a single-site project. Use siteUrl() to link to a page on another site.
{% if sites %}<nav aria-label="{{ t('nav.sites') }}">{% for s in sites %}<a href="{{ s.baseUrl|url }}"{% if s.key == site.key %} aria-current="true"{% endif %}>{{ s.name }}</a>{% endfor %}</nav>{% endif %} locale and locales
locale is the request locale:
| Key | Value |
|---|---|
locale.code | The locale code, such as en-GB |
locale.label | Its name in its own language, such as English or 日本語 |
locale.isDefault | Whether it is the site’s default locale |
locale.direction | ltr or rtl |
locale.language | The language subtag, such as en |
locale.currency | The locale’s currency code |
locale.firstDayOfWeek | 0 for Sunday to 6 for Saturday |
locale.calendar | The calendar the formatting filters use, such as gregory |
locale.numbering | The numbering system, such as latn |
locales is the site’s enabled locales, each with the same keys. For a language switcher that lists only the locales the current page is published in, use localeSwitcher() or page.alternates; locales lists them all.
page
The page being rendered: always uri, canonical, title, type and isPreview, and more on some pages (alternates, index, noindex, description, landing). The keys of each kind of page are on The page context.
request
What a template may know about the request. It is deliberately small: no headers, no cookies, no IP address, so a page stays cacheable and private.
| Key | Value |
|---|---|
request.path | The request path, with the locale prefix |
request.query | The query string, as a map from name to value: request.query.q |
request.isSecure | Whether the request came over HTTPS (directly, or with X-Forwarded-Proto: https) |
Reading a query parameter outside the canonical set makes the page uncacheable, and engine-dmo check warns at the read (uncacheable-query). The canonical set is page, sort, q, type, tag, lat, lon, km, and every field a route of the site lists in facets:.
now, today, tomorrow, yesterday
| Variable | Value |
|---|---|
now | The time of the request, in the site’s time zone |
today | Midnight at the start of the request’s date, in the site’s time zone |
tomorrow, yesterday | Midnight of the day after and the day before |
They are never in the server’s zone or in UTC, so a site in summer time does not see today begin at one in the morning. Format them with the date filters: {{ today|date:"full" }}. Compare them with dates directly: {% if entry.endsAt < now %}.
settings
The site’s settings: block from site.yaml, nested maps and lists as written. It is the place for values a template needs that are not content, such as a contact email or a social profile URL.
settings:
contact:
email: hello@example.test
social:
instagram: https://www.instagram.com/example <a href="mailto:{{ settings.contact.email }}">{{ settings.contact.email }}</a>
<a href="{{ settings.social.instagram|url }}">Instagram</a> Secrets never belong here: configuration files may not hold secrets, which come from environment variables.
singletons
The site’s singleton documents by type key. singletons.<type> is that type’s one document on the site, published in the request locale, shaped as entry is, or empty when nothing is published. It is read only when a template reaches it, so listing singletons costs nothing on a page that does not use them.
{% with footer = singletons.siteFooter %}
{% if footer %}{{ footer.text|ptext }}{% endif %}
{% endwith %} engine-dmo check reports a key that is not a singleton type on the site (unknown-singleton). Singletons are declared in the schema; see Content types.
nav
The site’s navigation by slot. Each slot is declared under nav: in site.yaml and filled in the admin:
nav:
main: { id: nav_q69bmrm00d, label: { en-GB: Header }, depth: 1 }
footer: { id: nav_fw01bn2kgg, label: { en-GB: Footer columns }, depth: 2 } nav.main is a list of items, resolved for the site and the request locale, with targets that are not available left out. Each item is:
| Key | Value |
|---|---|
label | The label in the request locale |
url | The address: a document’s live path, an asset’s URL, a site path, an external URL or a type’s index page; empty for a heading |
kind | What the item points at |
isExternal | Whether it leaves the site |
isCurrent | Whether it links to the page being rendered |
isActive | Whether it or one of its descendants is current |
depth | Its level, from 1 |
children | Its child items |
Render a tree with the nav tag (see Tags):
<nav aria-label="{{ t('nav.main') }}"><ul>
{% nav item in nav.main %}
<li><a href="{{ item.url|url }}"{% if item.isCurrent %} aria-current="page"{% endif %}>{{ item.label }}</a>
{% ifchildren %}<ul>{% children %}</ul>{% endifchildren %}</li>
{% endnav %}
</ul></nav> csrf
The token a form posting back to the engine must carry. It is minted when a template prints it, which sets the binding cookie, so a page that never prints it stays free of cookies. csrfToken() returns the same token and csrfInput() the hidden input that carries it.
<form method="post" action="{{ path('/enquiry') }}">
{{ csrfInput() }}
...
</form> assets
Files and bundles from public/:
| Call | Prints |
|---|---|
assets.url('css/site.css') | The file’s path with a version from its modification time (/css/site.css?v=tnuoz7), so a changed file is fetched again |
assets.css('main') | A <link rel="stylesheet"> for the bundle main |
assets.js('main') | A <script type="module"> for the bundle main |
assets.js('legacy', false) | A classic <script defer> |
Files resolve along the site’s public chain: public/<site key>/, then public/_shared/, then public/. Without a build integration, bundle main is css/main.css and js/main.js. With the Vite extension, a bundle resolves to the built, content-hashed files, and to the Vite dev server under serve --dev. See The frontend build.
devMode
true when the engine runs with engine-dmo serve --dev, otherwise false. Use it for development-only markup; never to hide content.
The page context
Exactly what each kind of page template receives (a document's entry and its common fields, an index page's items, pagination and facets, the search page's results, error pages, block and rich text templates) and how to print the real context of any URL.
Querying content
How a template fetches published documents with query() (where, tag, near, orderBy, limit, offset, exclude, organisation, onePer, with, and the terminal methods), nearby(), children(), ancestors(), smartList() and search(), with every rule, limit and error.