# 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`:
```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 |
| `$pageMetadata` | 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`:

```php
[
    '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

1. **Head**: Meta tags, social OG tags, Twitter cards, stylesheets, feed link, favicon
2. **Header**: Logo, navigation menu, language switcher
3. **Main**: `$content` (wrapped content from inner template)
4. **Footer**: Social links, page generation time, language links, GoatCounter analytics

### Critical: Feed Link in Head

```php
<?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

```html
<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 `$langPrefix` before 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 `@media` queries
