Templates
Your markup stays yours, in plain Twig files
Total CMS renders with Twig, and the whole CMS is reachable from a template through a single global variable. You write the HTML; the CMS hands you the content.
Total CMS renders with Twig 3. Templates are files you own, in your own repository, with clean syntax, automatic output escaping, and compiled caching so the parsing happens once rather than on every request. There is no PHP to write, which is rather the point — a designer can work in a Total CMS template without first learning the framework underneath it.
One global variable, cms, is how a template reaches the CMS. It is organised into namespaces, each with its own reference page:
cms.collection.*— objects, searching, URLs, navigationcms.data.*— typed access to a single fieldcms.media.*andcms.render.*— image paths, galleries, downloads, streaming, pagination markupcms.feed.*,cms.seo.*,cms.auth.*,cms.schema.*,cms.builder.*,cms.locale.*,cms.view.*,cms.qrcode.*andcms.barcode.*
Alongside those, Total CMS adds filters and tags to the ones Twig already ships. Text goes through markdown, truncate, nl2br or title; dates through date or dateRelative; colours through oklch, rgb, hsl and hex. The cmsgrid tag renders a collection into a grid, list or compact layout, and the cache tag stores the rendered HTML of anything expensive. When something is missing and you want to know about it, cms.log() writes from the template into the admin's log analyzer.
Two helpers belong in every layout: cms.assetsHead() in the head and cms.assetsBody() just before the closing body tag. They emit the stylesheets and scripts that Total CMS's own output depends on — grid layout, galleries, pagination, icons, HTMX — plus anything an extension registered. Leave them out and nothing errors; the grid renders as an unstyled stack and the lightbox never opens, which is a good deal harder to debug than an error would be.
What this looks like on a real page: a blog index is a for-loop over cms.collection.objects('blog'), each post's Markdown body run through the markdown filter, and the whole listing wrapped in a cache tag tagged with the collection so it rebuilds itself the moment an editor publishes.
What you get
One cms global
Collections, media, feeds, SEO, auth, schemas and Site Builder all hang off the same variable, split into namespaces. There is one thing to learn, not twenty.
Escaped by default
Twig escapes output automatically, so a field full of angle brackets cannot quietly become markup on your page.
Compiled and cached
Total CMS caches compiled templates, so the parsing cost is paid once. The admin's Cache Manager clears it after a large change.
Grids without the CSS
The cmsgrid tag lays a collection out as a grid, a list, or a compact row, with helper classes your own stylesheet can override.
Core assets in two calls
cms.assetsHead() and cms.assetsBody() emit everything the CMS output needs, in the right order, cache-busted, including extension assets.
In practice
One snippet
{% set posts = cms.collection.objects('blog') %}
{% for post in posts %}
<article>
<h2>{{ post.title }}</h2>
<time>{{ post.date | date('F j, Y') }}</time>
<div class="content">{{ post.content | markdown }}</div>
</article>
{% endfor %}
Read a collection, loop it, and run a Markdown field through the markdown filter — the same three moves work for every collection on the site.
FAQ
Common questions
Do I need to know PHP?
No. Twig is its own template language, designed to be readable and writable without PHP knowledge. Everything the CMS exposes is reachable through the cms variable.
What do the asset helpers actually emit?
The core stylesheets and scripts the CMS's own output depends on — grid CSS, gallery CSS and JS, pagination CSS, content and icon styles, and HTMX — plus any assets registered by extensions. Without them Load More never fetches and galleries never lay out.
Where do templates live?
Templates are managed in the admin at /admin/templates. A template id can contain forward slashes to organise into folders, and the .twig extension is added for you.
Can I debug a template?
Turn on debug mode and dump() is available inside templates. cms.log() writes a message, level and context into twig.log, which the admin log analyzer reads.
Related features
- Template Designer Define a template inline in a development page and it syncs to your local templates folder and to production on every page load, authorised by a per-template token.
- Load More & fragment caching One Twig call paginates a collection or Data View over HTMX, with the first page rendered server-side. The cache tag stores fragments and invalidates them by collection.
- Site Builder Pages live in the builder-pages collection with a route and a template. The router matches URLs at request time, so a page is live the moment you save it.
Want the details? Read the Twig templating documentation →
Or keep browsing: every Total CMS feature →
Start Your Free 45-Day Trial