Template Files
A Chinaski theme is a directory of Template Toolkit files that the static builder renders into every page, post, blog index, feed, and error page. This page covers the template set and search rules; block templates and template variables each get more depth on linked pages, and the complete variable reference lives in the admin’s built-in Theme Authoring doc (Admin → Docs).
The site templates directory
Site templates live in builder/site_templates/ (or a theme directory override; see below). One file per page-shaped output, plus optionals:
| File | Rendered as |
|---|---|
page.tt | every published page (default) |
post.tt | every published post |
blog_index.tt | the paginated blog listings (+ per-category/author archives via the shared renderer) |
landing.tt | pages that select the landing template |
404.tt | the per-language 404 page |
offline.tt | PWA offline fallback page |
_head.tt | <head> partial (meta tags, canonical, JSON-LD) |
_header.tt / _footer.tt | site header/footer partials |
_cookie_notice.tt | optional consent banner |
_sidebar.tt, _meta_tags.tt, _password_gate.tt | other shared partials |
<anything>.tt | any page that selects that template by name |
Conventions: files starting with _ are partials; they never render as standalone pages. Zero-viable requirements: pages can type a custom template name (landing.tt etc.) and the builder picks it from this directory (or from your active theme if it lives there first).
A starter’s skeleton is minimal:
<!DOCTYPE html>
<html lang="[% lang | html %]" dir="[% dir %]">
<head>
[% INCLUDE '_head.tt' %]
</head>
<body>
[% INCLUDE '_header.tt' %]
<main>[% title | html %][% body %]</main>
[% INCLUDE '_footer.tt' %]
</body>
</html>The one deliberate non-escaping: [% body %] emits stored HTML on purpose; page authors are the trust boundary; don’t extend raw output to other fields.
Searching and fallback (themes tweak the default)
When a non-default theme is active, its directory is searched first and builder/site_templates/ second, so a theme only needs to ship what it customizes; missing files fall back to the built-ins automatically rather than failing a build.
Forking _head.tt rather than rewriting it is recommended: it already emits the full meta set (canonical, OG/Twitter, hreflang, JSON-LD, noindex, and analytics with consent gating) and the builder hand-computes those values for the template’s stash.
What each build renders
For each configured language the builder renders: published pages, published posts, the paginated blog index, per-category archives, the post feed (RSS), the sitemap, robots.txt, and the 404 page. Output is written file-by-file (with a wall-clock ceiling of 30 minutes and a 2 GiB write budget that abort safely past the cap), and any stale files from a previous run are removed.
A template render failure doesn’t stop the build: the failure is recorded in the build log and the loop continues. The dashboard names the first few failing templates; the first place to look at debugging is the builds screen.
The escape hatch: per-page templates
Every page’s editor has a template dropdown populated automatically from non-partial .tt files in the standard directory plus the active theme’s directory, and it always keeps the page’s currently-set template in the list even if that file belongs to an inactive theme, so a routine re-save can’t silently swap templates.
Snippets (injections with an audit trail)
A snippet is a hand-controlled chunk of HTML inserted verbatim at the bottom of <head> or before </body>: analytics, precedes, verification tags. They can be global (injected site-wide) or attached to individual pages/posts (also by tick-box in those editors). Since snippet content is injected verbatim, anyone with snippet-edit rights can install arbitrary JavaScript on every page. Treat it as server access.
Testing your theme
- Edit
.ttfiles in the theme directory (orsite_templates/for core tweaks). - Click Build on the dashboard (or run the builder by hand).
- Errors include the failing template name and a reason; the full log is in the Builds screen.
The build system catches template errors even in validation; failures record the file and error, not just a blanket “done”.
Security rules
- Escape everything user-controlled with
| html; the intentional exceptions arebody(raw rich-text by design) andjson_ld(pre-serialized,</script>already neutralized). | urito encode URL components; never concatenate raw values into hrefs or attributes.- Minimal inline scripts only: every inline script widens the break-glass surface.
- Block field values arrive from admin forms unescaped; escape them.
- Snippet access equals server access: whoever can edit snippets can run content on every page.