4.6 KiB
4.6 KiB
Templates Reference
For LLM agents working on this site's templates. Read when modifying any template file.
Template Hierarchy
Content renders inside-out: content file -> page/list template -> base.php
content file (md/html/php) -> rendered as $content
-> page.php or list-*.php (wraps content)
-> base.php (HTML document shell)
File Locations
All in custom/templates/. These override app/default/templates/.
| Template | Purpose | Used When |
|---|---|---|
base.php |
HTML document wrapper (head, nav, footer) | Always |
page.php |
Single page/article | Directory has no subdirectories (or hide_list=true) |
list.php |
Default list layout | Directory has subdirectories (default) |
list-card-grid.php |
Card grid layout | page_template = list-card-grid in metadata |
list-faq.php |
FAQ accordion layout | page_template = list-faq in metadata |
list-grid.php |
Brochure grid layout | page_template = list-grid in metadata |
Template Selection
List template is chosen by page_template field in the directory's metadata.ini:
page_template = list-faq
If not set, defaults to list.php.
Variables Available in All Templates
These are extracted via extract() so they're direct PHP variables:
| Variable | Type | Description |
|---|---|---|
$content |
string | Pre-rendered HTML content (in base.php) |
$pageTitle |
?string | Page title from metadata |
$metaDescription |
?string | Meta description |
$socialImageUrl |
?string | Social media image URL |
$navigation |
array | Menu items [['title'=>..., 'url'=>...], ...] |
$homeLabel |
string | Home link text |
$currentLang |
string | Current language code (no or en) |
$langPrefix |
string | URL language prefix (empty for default, /en for English) |
$languageUrls |
array | ['no'=>'/path/', 'en'=>'/en/path/'] |
$translations |
array | Translation strings from language .ini files |
$availableLangs |
array | ['no', 'en'] |
$pageCssUrl |
?string | Page-specific CSS URL |
$pageCssHash |
?string | CSS cache-bust hash |
$pageJsUrl |
?string | Page-specific JS URL |
$pageJsHash |
?string | JS cache-bust hash |
$feedUrl |
?string | Atom feed URL (only on list pages with feed=true) |
Additional Variables in page.php
| Variable | Type | Description |
|---|---|---|
$content |
string | Rendered page content HTML |
$metadata |
array | Full metadata array from metadata.ini |
Additional Variables in list-*.php Templates
| Variable | Type | Description |
|---|---|---|
$pageContent |
?string | Rendered intro content from list directory's own content files |
$items |
array | List items (see schema below) |
$metadata |
array | List directory's metadata |
List Item Schema
Each item in $items:
[
'title' => string, // Item title
'url' => string, // Relative URL with lang prefix
'date' => string, // Formatted date (localized)
'rawDate' => string, // ISO date (YYYY-MM-DD)
'summary' => ?string, // Summary text
'cover' => ?string, // Cover image URL
'pdf' => ?string, // PDF file URL
'redirect' => ?string, // External redirect URL
'dirPath' => string, // Filesystem path to item directory
]
base.php Key Sections
- Head: Meta tags, social OG tags, Twitter cards, stylesheets, feed link, favicon
- Header: Logo, navigation menu, language switcher
- Main:
$content(wrapped content from inner template) - Footer: Social links, page generation time, language links, GoatCounter analytics
Critical: Feed Link in Head
<?php if (!empty($feedUrl)): ?>
<link rel="alternate" type="application/atom+xml" title="<?= htmlspecialchars($pageTitle ?? 'Feed') ?>" href="<?= htmlspecialchars($feedUrl) ?>">
<?php endif; ?>
This MUST remain in base.php. It enables feed discovery for any section with feed = true in metadata.
Critical: GoatCounter Analytics
<img style="display:none" src="https://stopplidelsen.goatcounter.com/count?p=<?= htmlspecialchars($_SERVER['REQUEST_URI']) ?>">
This is the analytics tracker. Do not remove or modify the URL.
Conventions
- Escape all user-generated content:
<?= htmlspecialchars($var) ?> - Pre-rendered HTML (from markdown) is safe:
<?= $content ?> - Use
$translations['key']for i18n strings - Use
$langPrefixbefore all internal URLs - Use CSS
<style>blocks at the bottom of list templates for template-specific styles - Use CSS nesting inside scoped selectors (e.g.,
main > section { ... }) - Use
clamp()for responsive sizing, avoid@mediaqueries