288 lines
7.1 KiB
Markdown
288 lines
7.1 KiB
Markdown
# 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)
|