folderweb/docs/how-to/custom-templates.md

289 lines
7.1 KiB
Markdown
Raw Normal View History

2025-11-02 13:46:47 +01:00
# How to Create Custom Templates
This guide shows you how to override default templates with your own custom designs.
## Overview
FolderWeb uses a template fallback system:
1. Check `/custom/templates/` for custom version
2. Fall back to `/app/default/templates/` if not found
**Important**: Never modify files in `/app/default/` — always create custom versions in `/custom/`.
## Available Templates
- **base.php** - HTML wrapper (header, navigation, footer)
- **page.php** - Single page/article wrapper
- **list.php** - Simple list view (default)
- **list-grid.php** - Grid layout with images
- **list-card-grid.php** - Card grid (supports PDFs, external links)
- **list-faq.php** - Expandable FAQ/Q&A format
## Customizing the Base Template
The base template controls your entire site layout.
### Step 1: Copy the Default
```bash
mkdir -p custom/templates
cp app/default/templates/base.php custom/templates/base.php
```
### Step 2: Edit Your Copy
The base template has access to these variables:
```php
$content // The rendered page content (HTML)
$currentLang // Current language code (e.g., "en", "no")
$navigation // Array of navigation items
$homeLabel // Site title
$translations // Translation strings
$pageTitle // Current page title
$dirName // Parent directory name (for CSS classes)
$pageName // Current page name (for CSS classes)
```
### Example: Add a Custom Header
```php
<header class="site-header">
<div class="contain">
<a href="<?= $ctx->langPrefix ?>/" class="logo">
<img src="/custom/assets/logo.svg" alt="<?= $homeLabel ?>">
</a>
<nav>
<ul>
<?php foreach ($navigation as $item): ?>
<li>
<a href="<?= $item['url'] ?>"><?= htmlspecialchars($item['title']) ?></a>
</li>
<?php endforeach; ?>
</ul>
</nav>
</div>
</header>
```
## Customizing the Page Template
The page template wraps individual articles and pages.
### Step 1: Copy the Default
```bash
cp app/default/templates/page.php custom/templates/page.php
```
### Step 2: Customize
Available variables:
```php
$content // Main content HTML
$pageMetadata // Array of metadata (tags, categories, etc.)
$translations // Translation strings
```
### Example: Add Author Information
```php
<article>
<?php if (isset($pageMetadata['author'])): ?>
<div class="author-info">
<p>Written by <?= htmlspecialchars($pageMetadata['author']) ?></p>
</div>
<?php endif; ?>
<?= $content ?>
<?php if (isset($pageMetadata['tags'])): ?>
<div class="tags">
<strong><?= $translations['tags'] ?>:</strong>
<?php foreach ($pageMetadata['tags'] as $tag): ?>
<span class="tag"><?= htmlspecialchars($tag) ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
</article>
```
## Creating a Custom List Template
List templates control how directories with subdirectories are displayed.
### Step 1: Create Your Template
```bash
touch custom/templates/list-custom.php
```
### Step 2: Use List Template Variables
All list templates receive:
```php
$items // Array of subdirectories
$metadata // Directory metadata
$pageContent // Optional intro content
$translations // Translation strings
```
Each item in `$items` has:
```php
[
'title' => 'Post Title',
'date' => '2. november 2025',
'url' => '/blog/2025-11-02-post/',
'cover' => '/blog/2025-11-02-post/cover.jpg',
'summary' => 'Brief description',
'pdf' => '/blog/2025-11-02-post/document.pdf',
'redirect' => 'https://external-site.com'
]
```
### Example: Timeline Template
```php
<?php if (!empty($pageContent)): ?>
<div class="page-intro">
<?= $pageContent ?>
</div>
<?php endif; ?>
<div class="timeline">
<?php foreach ($items as $item): ?>
<article class="timeline-item">
<time><?= $item['date'] ?></time>
<h2>
<a href="<?= $item['url'] ?>"><?= htmlspecialchars($item['title']) ?></a>
</h2>
<?php if ($item['summary']): ?>
<p><?= htmlspecialchars($item['summary']) ?></p>
<?php endif; ?>
</article>
<?php endforeach; ?>
</div>
```
### Step 3: Apply Your Template
Create a `metadata.ini` in the directory:
```ini
page_template = "list-custom"
```
## Template Best Practices
### Always Escape Output
Prevent XSS attacks by escaping user-generated content:
```php
<?= htmlspecialchars($item['title']) ?>
```
### Use Short Echo Tags
FolderWeb uses modern PHP, so short tags are always available:
```php
<?= $variable ?> // Good
<?php echo $variable; ?> // Also works, but verbose
```
### Check Before Using
Always check if variables exist:
```php
<?php if (isset($item['cover']) && $item['cover']): ?>
<img src="<?= $item['cover'] ?>" alt="">
<?php endif; ?>
```
### Leverage CSS Classes
The base template adds dynamic classes to `<body>`:
```php
<body class="section-<?= $dirName ?> page-<?= $pageName ?>">
```
Use these for page-specific styling without JavaScript.
## Advanced: Accessing the Context Object
Templates can access the full context object `$ctx`:
```php
<?php
// Available properties:
$ctx->contentDir // Path to content directory
$ctx->currentLang // Current language
$ctx->defaultLang // Default language
$ctx->availableLangs // Array of available languages
$ctx->langPrefix // URL prefix (e.g., "/en" or "")
$ctx->requestPath // Current request path
$ctx->hasTrailingSlash // Boolean
$ctx->navigation // Navigation array (computed property)
$ctx->homeLabel // Site title (computed property)
$ctx->translations // Translation array (computed property)
?>
```
## Example: Breadcrumb Navigation
Add breadcrumbs to your page template:
```php
<nav class="breadcrumbs" aria-label="Breadcrumb">
<ol>
<li><a href="<?= $ctx->langPrefix ?>/">Home</a></li>
<?php
$parts = array_filter(explode('/', trim($ctx->requestPath, '/')));
$path = '';
foreach ($parts as $i => $part):
$path .= '/' . $part;
$isLast = ($i === count($parts) - 1);
?>
<li<?= $isLast ? ' aria-current="page"' : '' ?>>
<?php if ($isLast): ?>
<?= htmlspecialchars($part) ?>
<?php else: ?>
<a href="<?= $ctx->langPrefix . $path ?>/">
<?= htmlspecialchars($part) ?>
</a>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ol>
</nav>
```
## Testing Your Templates
1. Clear your browser cache
2. Reload the page
3. Check browser console for errors
4. Validate HTML with W3C validator
## Reverting Changes
To revert to default templates, simply delete your custom version:
```bash
rm custom/templates/base.php
```
FolderWeb will automatically fall back to the default.
## Related
- [Customizing Styles](custom-styles.md)
- [Template Reference](../reference/templates.md)
- [Metadata Reference](../reference/metadata.md)