folderweb/docs/03-reference/03-template-variables.md
Ruben 76697e4656 Add getting started documentation
Add tutorial on adding content

Add tutorial on styling

Add tutorial on templates

Add configuration reference

Add metadata reference

Add template variables reference

Add internationalization reference

Add plugin system documentation

Add creating templates documentation

Add index page
2025-11-27 23:01:02 +01:00

10 KiB

Template Variables Reference

Templates have access to a set of variables provided by FolderWeb and its plugins. This reference documents all available variables and their types.

Base Template Variables

Available in base.php:

$content

The fully rendered HTML content from the page or list template.

Type: String (HTML)
Example:

<main>
  <?= $content ?>
</main>

$pageTitle

The page title for the <title> tag.

Type: String
Default: "FolderWeb"
Example:

<title><?= htmlspecialchars($pageTitle ?? 'FolderWeb') ?></title>

Source:

  1. Language-specific metadata [lang] title
  2. Root metadata title
  3. First heading in content
  4. Folder name

$metaDescription

SEO description for the <meta name="description"> tag.

Type: String
Optional: May be empty
Example:

<?php if (!empty($metaDescription)): ?>
  <meta name="description" content="<?= htmlspecialchars($metaDescription) ?>">
<?php endif; ?>

Source:

  1. Metadata search_description
  2. Metadata summary
  3. Empty if not set

$socialImageUrl

URL to cover image for social media meta tags.

Type: String (URL)
Optional: May be empty
Example:

<?php if (!empty($socialImageUrl)): ?>
  <meta property="og:image" content="<?= htmlspecialchars($socialImageUrl) ?>">
<?php endif; ?>

Source: First cover.* image found in content directory

$navigation

Array of navigation menu items.

Type: Array of associative arrays
Structure:

[
  ['url' => '/about/', 'title' => 'About'],
  ['url' => '/blog/', 'title' => 'Blog'],
  ['url' => '/contact/', 'title' => 'Contact'],
]

Example:

<?php if (!empty($navigation)): ?>
  <nav>
    <?php foreach ($navigation as $item): ?>
      <a href="<?= htmlspecialchars($item['url']) ?>">
        <?= htmlspecialchars($item['title']) ?>
      </a>
    <?php endforeach; ?>
  </nav>
<?php endif; ?>

Source: Pages with menu = 1 in metadata, sorted by menu_order

$homeLabel

Text for the home link.

Type: String
Default: "Home"
Example:

<a href="/"><?= htmlspecialchars($homeLabel ?? 'Home') ?></a>

Source: Translation string translations['home'] or fallback "Home"

$currentLang

Current language code.

Type: String
Default: From config.ini languages.default
Example:

<html lang="<?= htmlspecialchars($currentLang ?? 'en') ?>">

Values: ISO 639-1 language codes (en, no, de, etc.)

$langPrefix

URL prefix for the current language.

Type: String
Default: Empty string for default language
Example:

<a href="<?= htmlspecialchars($langPrefix ?? '') ?>/">Home</a>

Values:

  • "" (empty) for default language
  • "/no" for Norwegian
  • "/de" for German
  • etc.

$languageUrls

URLs to switch between available languages.

Type: Associative array
Structure:

[
  'en' => '/page/',
  'no' => '/no/side/',
  'de' => '/de/seite/',
]

Example:

<?php if (!empty($languageUrls) && count($languageUrls) > 1): ?>
  <nav class="language-switcher">
    <?php foreach ($languageUrls as $lang => $url): ?>
      <a href="<?= htmlspecialchars($url) ?>" 
         <?= ($lang === $currentLang) ? 'aria-current="true"' : '' ?>>
        <?= htmlspecialchars(strtoupper($lang)) ?>
      </a>
    <?php endforeach; ?>
  </nav>
<?php endif; ?>

$translations

Translated UI strings for the current language.

Type: Associative array
Structure:

[
  'home' => 'Home',
  'footer_handcoded' => 'Generated in',
  'footer_page_time' => 'ms',
  'months' => 'January,February,March,...',
]

Example:

<p><?= htmlspecialchars($translations['home'] ?? 'Home') ?></p>

Source: Language files in custom/languages/[lang].ini or app/default/languages/[lang].ini

$pageCssUrl

URL to page-specific CSS file.

Type: String (URL)
Optional: Only set if styles.css exists in content directory
Example:

<?php if (!empty($pageCssUrl)): ?>
  <link rel="stylesheet" href="<?= htmlspecialchars($pageCssUrl) ?>?v=<?= htmlspecialchars($pageCssHash ?? '') ?>">
<?php endif; ?>

$pageCssHash

MD5 hash of page-specific CSS for cache busting.

Type: String (MD5 hash)
Optional: Only set if $pageCssUrl exists
Example: See $pageCssUrl above

Page Template Variables

Available in page.php:

$content

The fully rendered HTML content from the page.

Type: String (HTML)
Example:

<article>
  <?= $content ?>
</article>

$metadata

All metadata for the current page.

Type: Associative array
Structure:

[
  'title' => 'Page Title',
  'summary' => 'Short description',
  'date' => '2024-12-15',
  'formatted_date' => '15. desember 2024',
  'show_date' => true,
  'author' => 'Jane Doe',  // Custom fields
  'tags' => 'web,design',
  // ... all other metadata fields
]

Example:

<?php if (isset($metadata['title'])): ?>
  <h1><?= htmlspecialchars($metadata['title']) ?></h1>
<?php endif; ?>

<?php if (isset($metadata['date']) && ($metadata['show_date'] ?? true)): ?>
  <time datetime="<?= $metadata['date'] ?>">
    <?= $metadata['formatted_date'] ?? $metadata['date'] ?>
  </time>
<?php endif; ?>

List Template Variables

Available in list.php, list-grid.php, list-compact.php, etc.:

$pageContent

Optional intro content from the directory's own files.

Type: String (HTML)
Optional: May be empty
Example:

<?php if ($pageContent): ?>
  <div class="intro">
    <?= $pageContent ?>
  </div>
<?php endif; ?>

Source: Content files in the list directory itself (not subdirectories)

$items

Array of items to display in the list.

Type: Array of associative arrays
Structure:

[
  [
    'url' => '/blog/my-post/',
    'path' => '/content/blog/2024-12-15-my-post',
    'title' => 'My Post',
    'summary' => 'Short description',
    'date' => '2024-12-15',
    'formatted_date' => '15. desember 2024',
    'cover_image' => '/blog/my-post/cover.jpg',
    // All custom metadata fields...
    'author' => 'Jane Doe',
    'category' => 'Tutorial',
  ],
  // ... more items
]

Example:

<?php foreach ($items as $item): ?>
  <article>
    <?php if (isset($item['cover_image'])): ?>
      <img src="<?= $item['cover_image'] ?>" 
           alt="<?= htmlspecialchars($item['title']) ?>">
    <?php endif; ?>
    
    <h2>
      <a href="<?= $item['url'] ?>">
        <?= htmlspecialchars($item['title']) ?>
      </a>
    </h2>
    
    <?php if (isset($item['date'])): ?>
      <time datetime="<?= $item['date'] ?>">
        <?= $item['formatted_date'] ?? $item['date'] ?>
      </time>
    <?php endif; ?>
    
    <?php if (isset($item['summary'])): ?>
      <p><?= htmlspecialchars($item['summary']) ?></p>
    <?php endif; ?>
  </article>
<?php endforeach; ?>

$metadata

Metadata for the list directory itself.

Type: Associative array
Structure: Same as page metadata
Example:

<?php if (isset($metadata['title'])): ?>
  <h1><?= htmlspecialchars($metadata['title']) ?></h1>
<?php endif; ?>

Item Properties

Each item in $items has these properties:

Property Type Description Optional
url String Full URL to the item No
path String Filesystem path to item No
title String Item title No
summary String Short description Yes
date String ISO date (YYYY-MM-DD) Yes
formatted_date String Localized date string Yes
cover_image String URL to cover image Yes
Custom fields Mixed Any metadata fields Yes

Adding Custom Variables

Use the Hook::TEMPLATE_VARS hook to add custom variables:

Hooks::add(Hook::TEMPLATE_VARS, function(array $vars, Context $ctx) {
    // Add a custom variable
    $vars['siteName'] = 'My Website';
    
    // Add computed values
    $vars['currentYear'] = date('Y');
    
    // Add from context
    $vars['userName'] = $ctx->get('user_name', 'Guest');
    
    return $vars;
});

Then use in templates:

<p>&copy; <?= $currentYear ?> <?= htmlspecialchars($siteName) ?></p>

Variable Availability by Template

Variable base.php page.php list.php
$content
$pageTitle
$metaDescription
$socialImageUrl
$navigation
$homeLabel
$currentLang
$langPrefix
$languageUrls
$translations
$pageCssUrl
$pageCssHash
$metadata
$pageContent
$items

Note: All variables are technically available everywhere via plugin hooks, but this table shows the default availability.

Escaping Output

Always escape user content to prevent XSS attacks:

<!-- Good -->
<h1><?= htmlspecialchars($metadata['title']) ?></h1>
<p><?= htmlspecialchars($item['summary']) ?></p>

<!-- Bad -->
<h1><?= $metadata['title'] ?></h1>
<p><?= $item['summary'] ?></p>

Exception: Already-sanitized HTML like $content (rendered from Markdown):

<!-- Good (content is already HTML) -->
<div class="content">
  <?= $content ?>
</div>

Checking Variable Existence

Always check if optional variables exist:

<!-- Good -->
<?php if (isset($metadata['author'])): ?>
  <p>By <?= htmlspecialchars($metadata['author']) ?></p>
<?php endif; ?>

<!-- Bad (may cause warnings) -->
<p>By <?= htmlspecialchars($metadata['author']) ?></p>

Use null coalescing for defaults:

<p><?= htmlspecialchars($metadata['author'] ?? 'Anonymous') ?></p>

Debugging Variables

To see all available variables in a template:

<pre><?php var_dump(get_defined_vars()); ?></pre>

Or specific variables:

<pre><?php print_r($metadata); ?></pre>
<pre><?php print_r($items); ?></pre>

Remember to remove debug code before deploying to production.

What's Next?