Templates
Templates are reusable Twig files stored in your tcms-data/templates/ directory. They can be used with {% include %}, the {% cmsgrid %} tag, or rendered directly via the API.
Managing Templates
Section titled “Managing Templates”Templates are managed through the admin dashboard at /admin/templates. From there you can create, edit, duplicate, and delete templates.
Template IDs
Section titled “Template IDs”Each template has a unique ID that can include forward slashes to organize into folders:
header— root-level templategrids/blog— template in thegridsfolderpages/products/tile— nested folders are supported
The .twig extension is added automatically — you only need to provide the ID.
Using Templates
Section titled “Using Templates”Include a template in any Twig file:
{% include 'header.twig' %}{% include 'grids/blog.twig' %}Use with {% cmsgrid %} for collection layouts:
{% cmsgrid cms.collection.objects('blog') from 'blog' with 'blog grid' %} {% include 'grids/blog.twig' %}{% endcmsgrid %}Render directly via the API:
GET /templates/grids/blogWhite Label Templates
Section titled “White Label Templates”Special templates customize the admin interface. See White Label for details.
| Template | Purpose |
|---|---|
whitelabel/login-above.twig | Content above the login form |
whitelabel/login-below.twig | Content below the login form |
whitelabel/download-auth-above.twig | Content above download auth form |
whitelabel/download-auth-below.twig | Content below download auth form |
whitelabel/admin-home.twig | Custom admin home page content |
Template Designer
Section titled “Template Designer”The Template Designer enables remote template updates from development tools like Stacks. When building layouts in a visual GUI, the Template Designer automatically syncs the template content to both your local dev server and your production server — no manual copy-paste required.
How It Works
Section titled “How It Works”- Create a template in the admin dashboard and enable the Template Designer toggle
- Copy the Designer Token shown in the template form
- Use the
{% templatedesigner %}tag in your development Twig template - Every page load on your dev server syncs the template content locally and pushes it to production
Enabling Designer on a Template
Section titled “Enabling Designer on a Template”Edit any template in the admin dashboard. You’ll see two fields:
- Template Designer — Toggle to enable remote updates for this template
- Designer Token — Auto-generated token for authentication (visible when Designer is enabled)
The Designer Token is read-only and generated automatically. Share it with your development tool to authorize updates.
The {% templatedesigner %} Tag
Section titled “The {% templatedesigner %} Tag”This tag captures raw template content before Twig compiles it, preserving expressions like {{ object.title }} as source code rather than evaluating them.
Syntax
Section titled “Syntax”{% templatedesigner for 'TEMPLATE_PATH' on 'PRODUCTION_URL' token 'TOKEN' %} ...template content...{% endtemplatedesigner %}Parameters
Section titled “Parameters”| Parameter | Required | Description |
|---|---|---|
for 'path' | Yes | Template ID (without .twig extension) |
on 'url' | Yes | Production API base URL |
token 'token' | No | Designer token for remote sync (required for production sync) |
Example
Section titled “Example”{% templatedesigner for 'products/tile' on 'https://example.com/tcms/' token 'abc123def456' %} <article class="product-tile"> <h3>{{ object.title }}</h3> <p>{{ object.summary }}</p> {% if object.image %} {{ cms.render.image(object, {w: 400}, {collection: 'products', property: 'image'}) }} {% endif %} <span class="price">{{ object.price | price }}</span> </article>{% endtemplatedesigner %}Sync Behavior
Section titled “Sync Behavior”The sync behavior depends on which server renders the page:
On your development server
Section titled “On your development server”When the page is rendered on a dev server (where the API URL differs from the on parameter):
- Local sync — The template content is saved to the local
tcms-data/templates/directory - Remote sync — A PUT request is sent to the production server’s Designer API to update the template there
- Badge — A status badge appears in the bottom-right corner showing sync results
The badge displays:
- The template path being synced
- Local sync status (success or error)
- Remote sync status (success, error, or skipped if no token provided)
- A Copy Template button to copy the raw template source to your clipboard
On your production server
Section titled “On your production server”When the API URL matches the on parameter, the tag is a no-op — no sync occurs, no badge is displayed, and there is zero performance overhead.
Designer API
Section titled “Designer API”The Designer API provides a public endpoint for remote template updates. This endpoint is authenticated with the Designer Token, not the normal session/API key auth.
Update Template
Section titled “Update Template”PUT /designer/templates/{path}X-Designer-Token: your-token-hereContent-Type: text/plain
<article>{{ object.title }}</article>The request body is the raw template content (plain text, not JSON). Only the template content is updated — the Designer Token and other metadata remain unchanged.
Returns 200 with:
{ "success": true, "template": "products/tile"}The token can also be passed as a query parameter:
/designer/templates/path?token=your-token
Multiple Designer Blocks
Section titled “Multiple Designer Blocks”A single page can contain multiple {% templatedesigner %} blocks. Each one syncs independently and gets its own entry in the status badge:
{% templatedesigner for 'products/card' on 'https://example.com/' token 'token1' %} <div class="card">{{ object.title }}</div>{% endtemplatedesigner %}
<div class="divider"></div>
{% templatedesigner for 'products/detail' on 'https://example.com/' token 'token2' %} <section class="detail"> <h1>{{ object.title }}</h1> <div>{{ object.content | markdown }}</div> </section>{% endtemplatedesigner %}Local-Only Mode
Section titled “Local-Only Mode”If you omit the token parameter, the template is only saved locally — no remote sync is attempted:
{% templatedesigner for 'dev/prototype' on 'https://example.com/' %} <div class="prototype">{{ object.title }}</div>{% endtemplatedesigner %}This is useful when prototyping templates that aren’t ready for production yet.
Security
Section titled “Security”- Designer API endpoints are public (no session or API key required) but gated by the Designer Token
- Each template has its own unique token — compromising one token does not affect other templates
- Tokens are auto-generated UUIDs and cannot be edited manually
- The Designer toggle must be explicitly enabled per template
- The API only allows updating template content — metadata (token, enabled status) cannot be changed via the Designer API