Templates
Templates
header.php
Generates all HTML from <!DOCTYPE html> to the opening of the main content area.
Injected variables
| Variable | Type | Description |
|---|---|---|
$settings | array | All site settings |
$data | array | Site content — see note below |
$pageTitle | string | Current page title |
$metaTitle | string | Calculated SEO <title> |
$metaDescription | string | Calculated SEO meta description |
$metaKeywords | string | Meta keywords (if set on the item) |
$ogImage | string | Open Graph image URL |
$ogTitle | string | Open Graph title |
$ogDescription | string | Open Graph description |
$type | string | Current content type (article, project, page, '') |
$slug | string | Current item slug (empty on list pages) |
$headerScripts | array | Additional scripts to inject — use render_header_scripts() |
On list pages and the homepage, $data['article'] contains the full lightweight index. On single-item pages, it contains only that one item. Use slloadindex('article') when you need the full catalogue from an uncertain context.
Minimal <head>
<!DOCTYPE html>
<html lang="<?php echo htmlspecialchars($settings['site_language'] ?? 'en'); ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $metaTitle; ?></title>
<?php echo render_meta_tags($settings, $metaTitle, $metaDescription); ?>
<link rel="stylesheet" href="<?php echo getBaseUrl(); ?>css/lightbox.css">
<?php echo render_header_scripts($headerScripts); ?>
</head>
render_header_scripts() injects in this order: system CSS, theme style.css, js/main.js, conditional gallery scripts, theme script.js, JS i18n bridge.
footer.php
Injected variables
| Variable | Type | Description |
|---|---|---|
$settings | array | Site settings |
$data | array | Site content |
$currentYear | string | Current year (date('Y')) |
$baseUrl | string | Base URL with trailing slash |
Minimal structure
</main>
</div>
<?php echo render_search_ui(); ?>
</body>
</html>
rendersearchui() must be called before </body>. It generates the search overlay HTML that powers Ctrl+K, regardless of whether the search icon is visible.
home.php
Rendered between header.php and footer.php on the homepage. Injected: $data, $settings.
<?php
$articles = $data['article'] ?? [];
usort($articles, fn($a, $b) => strcmp($b['date'] ?? '', $a['date'] ?? ''));
$recent = array_slice($articles, 0, 5);
?>
<h1><?php echo htmlspecialchars($settings['site_title']); ?></h1>
<?php foreach ($recent as $article): ?>
<?php echo render_article_card($article); ?>
<?php endforeach; ?>
content-articles.php, content-pages.php, content-projects.php
Single-item views. Receive only $item — the full item array.
<article>
<?php render_featured_image($item); ?>
<?php render_content_title($item); ?>
<?php render_content_date($item); ?>
<?php render_content_category($item); ?>
<?php render_content_tags($item); ?>
<div class="prose">
<?php echo render_content_html($item['content'] ?? '', $item); ?>
</div>
</article>
Always use rendercontenthtml($item['content'], $item) — never echo $item['content'] directly.
content-list.php
Injected variables
| Variable | Type | Description |
|---|---|---|
$list_type | string | 'article', 'project', 'page', 'category', 'tag' |
$articles | array | Articles to display (sorted by date desc) |
$projects | array | Projects to display (sorted by date desc) |
$items | array | All items with _content_type key |
$filter_value | string | Current category or tag slug |
$data | array | Full data store |
$settings | array | Site settings |
Page templates (page-templates/)
<?php /* Template Name: Contact */ ?>
<div class="contact-page">
<h1><?php echo htmlspecialchars($item['title']); ?></h1>
<?php echo render_content_html($item['content'] ?? '', $item); ?>
<?php echo render_contact_form_html(); ?>
</div>
Available variable: $item. Call loadSettings() if you need $settings.
