# Templates Templates control how content is presented. FolderWeb uses plain PHP templates — HTML with embedded PHP for dynamic output. ## Template Types FolderWeb has three template levels: ### Base Template (`base.php`) The HTML scaffold wrapping every page. Contains ``, navigation, footer, and a `$content` placeholder for the inner template. ### Page Template (`page.php`) Wraps single-page content. Receives the rendered content and metadata. ### List Templates (`list.php`, `list-grid.php`, `list-compact.php`) Displays collections of items from subdirectories. Receives an `$items` array and optional intro content. ## Template Location Templates live in `custom/templates/`: ``` custom/ └── templates/ ├── base.php # HTML scaffold ├── page.php # Single page wrapper ├── list.php # Default list layout ├── list-grid.php # Grid card layout └── list-compact.php # Compact list layout ``` FolderWeb falls back to `app/default/templates/` for any template not present in `custom/`. ## Base Template The base template wraps every page. Here is a minimal example: ```php <?= htmlspecialchars($pageTitle) ?>
``` Key points: - `$content` contains the rendered output from the page or list template - Always escape user-facing values with `htmlspecialchars()` - Check optional variables with `isset()` before using them ## Page Template The page template wraps individual page content: ```php

``` ## List Template List templates display items from subdirectories: ```php
<?= htmlspecialchars($item['title']) ?>

``` ## Choosing a List Template Select which list template to use per directory in `metadata.ini`: ```ini title = "Projects" [settings] page_template = "list-grid" ``` Built-in options: - `list` — vertical list (default) - `list-grid` — card grid - `list-compact` — minimal compact list ## Creating Custom List Templates Create a new file in `custom/templates/`. For example, a timeline layout: **custom/templates/list-timeline.php:** ```php

``` Use it with: ```ini [settings] page_template = "list-timeline" ``` ## Template Variables ### Base template | Variable | Type | Description | |---|---|---| | `$content` | string | Rendered page/list HTML | | `$pageTitle` | string | Page title for `` | | `$metaDescription` | string | SEO description | | `$navigation` | array | Menu items (`title`, `url`, `order`) | | `$homeLabel` | string | Translated "Home" text | | `$currentLang` | string | Current language code | | `$langPrefix` | string | URL language prefix (`""` or `"/no"`) | | `$languageUrls` | array | Links to other language versions | | `$translations` | array | Translated UI strings | | `$cssHash` | string | Cache-busting hash for base CSS | | `$pageCssUrl` | string | Page-specific CSS URL (if exists) | | `$pageJsUrl` | string | Page-specific JS URL (if exists) | | `$pageLoadTime` | float | Page generation time | ### Page template | Variable | Type | Description | |---|---|---| | `$content` | string | Rendered HTML from content files | | `$metadata` | array | Page metadata (title, date, etc.) | ### List template | Variable | Type | Description | |---|---|---| | `$items` | array | Items to display | | `$pageContent` | string | Rendered intro content | | `$metadata` | array | Directory metadata | Each item in `$items`: | Key | Type | Description | |---|---|---| | `url` | string | Full URL to item | | `title` | string | Item title | | `summary` | string | Short description | | `date` | string | ISO date (YYYY-MM-DD) | | `formatted_date` | string | Localized date string | | `cover_image` | string | Cover image URL | See the [Template Variables Reference](../03-reference/03-template-variables.md) for the complete list. ## Best Practices **Escape output.** Always use `htmlspecialchars()` for user-facing values. The `$content` variable is already rendered HTML and does not need escaping. **Check variables.** Use `isset()` before accessing optional values: ```php <?php if (isset($metadata['summary'])): ?> <p><?= htmlspecialchars($metadata['summary']) ?></p> <?php endif; ?> ``` **Keep logic minimal.** Templates should display data, not process it. Complex logic belongs in plugins. **Use semantic HTML.** Prefer `<article>`, `<header>`, `<nav>`, `<time>` over generic `<div>` elements. ## Next Steps - [Template Variables Reference](../03-reference/03-template-variables.md) — Complete variable list - [Internationalization](../03-reference/04-internationalization.md) — Multi-language support - [Configuration Reference](../03-reference/01-configuration.md) — All configuration options