448 lines
8.6 KiB
Markdown
448 lines
8.6 KiB
Markdown
|
|
# Metadata Reference
|
||
|
|
|
||
|
|
Metadata files (`metadata.ini`) configure individual pages and directories. They control titles, URLs, templates, navigation, and more.
|
||
|
|
|
||
|
|
## Basic Structure
|
||
|
|
|
||
|
|
```ini
|
||
|
|
title = "Page Title"
|
||
|
|
summary = "Short description"
|
||
|
|
date = "2024-12-15"
|
||
|
|
search_description = "SEO-friendly description"
|
||
|
|
```
|
||
|
|
|
||
|
|
Place `metadata.ini` in any content directory:
|
||
|
|
|
||
|
|
```
|
||
|
|
content/blog/my-post/
|
||
|
|
├── index.md
|
||
|
|
└── metadata.ini
|
||
|
|
```
|
||
|
|
|
||
|
|
## Core Fields
|
||
|
|
|
||
|
|
### `title`
|
||
|
|
|
||
|
|
The page or item title.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
title = "My Blog Post"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** Extracted from first `# Heading` in Markdown, or folder name
|
||
|
|
**Used in:** Page `<title>`, list items, navigation menu
|
||
|
|
**Type:** String
|
||
|
|
|
||
|
|
### `summary`
|
||
|
|
|
||
|
|
Short description shown in list views.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
summary = "A brief introduction to this topic"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** None (empty)
|
||
|
|
**Used in:** List item previews, RSS feeds, social media cards
|
||
|
|
**Type:** String
|
||
|
|
**Recommended length:** 150-200 characters
|
||
|
|
|
||
|
|
### `date`
|
||
|
|
|
||
|
|
Publication or modification date.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
date = "2024-12-15"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** Extracted from folder name (`YYYY-MM-DD-title`)
|
||
|
|
**Format:** `YYYY-MM-DD` (ISO 8601)
|
||
|
|
**Used in:** List sorting, date displays, `<time>` elements
|
||
|
|
**Type:** String (date)
|
||
|
|
|
||
|
|
### `search_description`
|
||
|
|
|
||
|
|
SEO meta description for search engines.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
search_description = "Learn how to build fast, maintainable websites with FolderWeb"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** Uses `summary` if not set
|
||
|
|
**Used in:** `<meta name="description">` tag
|
||
|
|
**Type:** String
|
||
|
|
**Recommended length:** 150-160 characters
|
||
|
|
|
||
|
|
### `slug`
|
||
|
|
|
||
|
|
Custom URL slug (overrides folder name).
|
||
|
|
|
||
|
|
```ini
|
||
|
|
slug = "custom-url"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** Folder name (with date prefix removed)
|
||
|
|
**Used in:** URL generation
|
||
|
|
**Type:** String (alphanumeric, hyphens, underscores)
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```
|
||
|
|
Folder: content/blog/2024-12-15-very-long-title/
|
||
|
|
Slug: short-title
|
||
|
|
URL: /blog/short-title/
|
||
|
|
```
|
||
|
|
|
||
|
|
### `menu`
|
||
|
|
|
||
|
|
Show this page in the navigation menu.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
menu = 1
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** `0` (not in menu)
|
||
|
|
**Values:** `1` (show) or `0` (hide)
|
||
|
|
**Type:** Integer
|
||
|
|
|
||
|
|
### `menu_order`
|
||
|
|
|
||
|
|
Position in navigation menu (lower numbers first).
|
||
|
|
|
||
|
|
```ini
|
||
|
|
menu = 1
|
||
|
|
menu_order = 10
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** `999` (last)
|
||
|
|
**Used in:** Navigation sorting
|
||
|
|
**Type:** Integer
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```ini
|
||
|
|
# Home
|
||
|
|
menu = 1
|
||
|
|
menu_order = 1
|
||
|
|
|
||
|
|
# About
|
||
|
|
menu = 1
|
||
|
|
menu_order = 10
|
||
|
|
|
||
|
|
# Blog
|
||
|
|
menu = 1
|
||
|
|
menu_order = 20
|
||
|
|
|
||
|
|
# Contact
|
||
|
|
menu = 1
|
||
|
|
menu_order = 30
|
||
|
|
```
|
||
|
|
|
||
|
|
## Settings Section
|
||
|
|
|
||
|
|
Advanced settings go in a `[settings]` section:
|
||
|
|
|
||
|
|
```ini
|
||
|
|
title = "My Page"
|
||
|
|
|
||
|
|
[settings]
|
||
|
|
page_template = "list-grid"
|
||
|
|
show_date = true
|
||
|
|
hide_list = false
|
||
|
|
```
|
||
|
|
|
||
|
|
### `page_template`
|
||
|
|
|
||
|
|
Which template to use for list views.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
[settings]
|
||
|
|
page_template = "list-grid"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** `list` (uses `list.php`)
|
||
|
|
**Available templates:**
|
||
|
|
- `list` — Simple vertical list
|
||
|
|
- `list-grid` — Card grid layout
|
||
|
|
- `list-compact` — Minimal compact list
|
||
|
|
- Custom templates you create
|
||
|
|
|
||
|
|
**Used in:** List view rendering
|
||
|
|
**Type:** String (template name without `.php`)
|
||
|
|
|
||
|
|
### `show_date`
|
||
|
|
|
||
|
|
Display the date on the page.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
[settings]
|
||
|
|
show_date = true
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** `true`
|
||
|
|
**Values:** `true` or `false`
|
||
|
|
**Type:** Boolean
|
||
|
|
|
||
|
|
### `hide_list`
|
||
|
|
|
||
|
|
Don't show list view even if directory has subdirectories.
|
||
|
|
|
||
|
|
```ini
|
||
|
|
[settings]
|
||
|
|
hide_list = true
|
||
|
|
```
|
||
|
|
|
||
|
|
**Default:** `false`
|
||
|
|
**Values:** `true` or `false`
|
||
|
|
**Type:** Boolean
|
||
|
|
**Use case:** Section landing pages that should show content instead of list
|
||
|
|
|
||
|
|
## Language-Specific Overrides
|
||
|
|
|
||
|
|
Add language-specific sections to override fields:
|
||
|
|
|
||
|
|
```ini
|
||
|
|
title = "About Us"
|
||
|
|
summary = "Learn about our company"
|
||
|
|
slug = "about"
|
||
|
|
|
||
|
|
[no]
|
||
|
|
title = "Om oss"
|
||
|
|
summary = "Les om bedriften vår"
|
||
|
|
slug = "om"
|
||
|
|
|
||
|
|
[de]
|
||
|
|
title = "Über uns"
|
||
|
|
summary = "Erfahren Sie mehr über unser Unternehmen"
|
||
|
|
slug = "uber-uns"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Supported fields in language sections:**
|
||
|
|
- `title`
|
||
|
|
- `summary`
|
||
|
|
- `search_description`
|
||
|
|
- `slug`
|
||
|
|
|
||
|
|
**Language codes:** Must match your configured languages (`config.ini`).
|
||
|
|
|
||
|
|
**URLs with language-specific slugs:**
|
||
|
|
- English: `/about/`
|
||
|
|
- Norwegian: `/no/om/`
|
||
|
|
- German: `/de/uber-uns/`
|
||
|
|
|
||
|
|
## Custom Fields
|
||
|
|
|
||
|
|
Add any custom fields you need:
|
||
|
|
|
||
|
|
```ini
|
||
|
|
title = "Project X"
|
||
|
|
author = "Jane Doe"
|
||
|
|
client = "ACME Corp"
|
||
|
|
project_url = "https://example.com"
|
||
|
|
featured = true
|
||
|
|
tags = "web,design,portfolio"
|
||
|
|
```
|
||
|
|
|
||
|
|
Access custom fields in templates:
|
||
|
|
|
||
|
|
```php
|
||
|
|
<?php if (isset($metadata['author'])): ?>
|
||
|
|
<p>By <?= htmlspecialchars($metadata['author']) ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<?php if (isset($metadata['project_url'])): ?>
|
||
|
|
<a href="<?= htmlspecialchars($metadata['project_url']) ?>">
|
||
|
|
View Project
|
||
|
|
</a>
|
||
|
|
<?php endif; ?>
|
||
|
|
```
|
||
|
|
|
||
|
|
Or in plugins:
|
||
|
|
|
||
|
|
```php
|
||
|
|
Hooks::add(Hook::TEMPLATE_VARS, function(array $vars, Context $ctx) {
|
||
|
|
$metadata = $ctx->get('metadata', []);
|
||
|
|
|
||
|
|
if (isset($metadata['tags'])) {
|
||
|
|
$vars['tags'] = explode(',', $metadata['tags']);
|
||
|
|
}
|
||
|
|
|
||
|
|
return $vars;
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
## Complete Example
|
||
|
|
|
||
|
|
**content/blog/2024-12-15-building-fast-sites/metadata.ini:**
|
||
|
|
|
||
|
|
```ini
|
||
|
|
# Core fields
|
||
|
|
title = "Building Fast Websites"
|
||
|
|
summary = "Learn how to optimize your site for speed and performance"
|
||
|
|
date = "2024-12-15"
|
||
|
|
search_description = "A comprehensive guide to building fast, performant websites in 2024"
|
||
|
|
|
||
|
|
# Navigation
|
||
|
|
menu = 0 # Don't show in main menu
|
||
|
|
menu_order = 999
|
||
|
|
|
||
|
|
# Custom slug
|
||
|
|
slug = "fast-sites"
|
||
|
|
|
||
|
|
# Settings
|
||
|
|
[settings]
|
||
|
|
show_date = true
|
||
|
|
|
||
|
|
# Custom fields
|
||
|
|
author = "Jane Doe"
|
||
|
|
category = "Web Performance"
|
||
|
|
tags = "performance,optimization,web"
|
||
|
|
estimated_reading_time = 8
|
||
|
|
|
||
|
|
# Norwegian translation
|
||
|
|
[no]
|
||
|
|
title = "Bygge raske nettsider"
|
||
|
|
summary = "Lær hvordan du optimaliserer nettstedet ditt for hastighet og ytelse"
|
||
|
|
search_description = "En omfattende guide til å bygge raske, effektive nettsteder i 2024"
|
||
|
|
slug = "raske-sider"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Metadata Priority
|
||
|
|
|
||
|
|
When determining values, FolderWeb follows this priority:
|
||
|
|
|
||
|
|
1. **Language-specific metadata** (e.g., `[no]` section)
|
||
|
|
2. **Root metadata** (e.g., `title = "..."`)
|
||
|
|
3. **Auto-extracted values** (e.g., first heading, folder date)
|
||
|
|
4. **Defaults** (e.g., folder name)
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
|
||
|
|
```
|
||
|
|
Folder: content/blog/2024-12-15-my-post/
|
||
|
|
```
|
||
|
|
|
||
|
|
**Title resolution:**
|
||
|
|
1. Check `metadata.ini` for `[en] title = "..."`
|
||
|
|
2. Check `metadata.ini` for `title = "..."`
|
||
|
|
3. Extract from first `# Heading` in Markdown
|
||
|
|
4. Use folder name: "my-post"
|
||
|
|
|
||
|
|
## Metadata in List Items
|
||
|
|
|
||
|
|
When rendering list views, each item receives these metadata fields:
|
||
|
|
|
||
|
|
```php
|
||
|
|
$item = [
|
||
|
|
'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', // Language-specific
|
||
|
|
'cover_image' => '/blog/my-post/cover.jpg', // If exists
|
||
|
|
// All custom metadata fields...
|
||
|
|
'author' => 'Jane Doe',
|
||
|
|
'tags' => 'web,design',
|
||
|
|
];
|
||
|
|
```
|
||
|
|
|
||
|
|
Access in list templates:
|
||
|
|
|
||
|
|
```php
|
||
|
|
<?php foreach ($items as $item): ?>
|
||
|
|
<article>
|
||
|
|
<h2><?= htmlspecialchars($item['title']) ?></h2>
|
||
|
|
|
||
|
|
<?php if (isset($item['author'])): ?>
|
||
|
|
<p>By <?= htmlspecialchars($item['author']) ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
|
||
|
|
<?php if (isset($item['summary'])): ?>
|
||
|
|
<p><?= htmlspecialchars($item['summary']) ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
</article>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Best Practices
|
||
|
|
|
||
|
|
### 1. Use Consistent Field Names
|
||
|
|
|
||
|
|
```ini
|
||
|
|
# Good: consistent naming
|
||
|
|
author = "Jane Doe"
|
||
|
|
published_date = "2024-12-15"
|
||
|
|
featured = true
|
||
|
|
|
||
|
|
# Bad: inconsistent naming
|
||
|
|
Author = "Jane Doe"
|
||
|
|
PublishDate = "2024-12-15"
|
||
|
|
is_featured = true
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Keep Summaries Concise
|
||
|
|
|
||
|
|
```ini
|
||
|
|
# Good
|
||
|
|
summary = "Learn to optimize website performance in 5 steps"
|
||
|
|
|
||
|
|
# Too long
|
||
|
|
summary = "This comprehensive article will teach you everything you need to know about optimizing website performance, including lazy loading, code splitting, image optimization, and much more in detailed steps with examples"
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Use Semantic Custom Fields
|
||
|
|
|
||
|
|
```ini
|
||
|
|
# Good: clear purpose
|
||
|
|
author = "Jane Doe"
|
||
|
|
category = "Tutorial"
|
||
|
|
difficulty = "Beginner"
|
||
|
|
|
||
|
|
# Bad: unclear purpose
|
||
|
|
field1 = "Jane Doe"
|
||
|
|
field2 = "Tutorial"
|
||
|
|
field3 = "Beginner"
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Add Comments
|
||
|
|
|
||
|
|
```ini
|
||
|
|
# SEO and social media
|
||
|
|
title = "Building Fast Websites"
|
||
|
|
search_description = "A guide to web performance optimization"
|
||
|
|
|
||
|
|
# Author and categorization
|
||
|
|
author = "Jane Doe"
|
||
|
|
category = "Performance"
|
||
|
|
|
||
|
|
# Custom display options
|
||
|
|
featured = true # Show in featured section
|
||
|
|
priority = 10 # Higher = more prominent
|
||
|
|
```
|
||
|
|
|
||
|
|
## Debugging Metadata
|
||
|
|
|
||
|
|
To see parsed metadata, create a debug template:
|
||
|
|
|
||
|
|
**custom/templates/page.php:**
|
||
|
|
|
||
|
|
```php
|
||
|
|
<pre><?php print_r($metadata); ?></pre>
|
||
|
|
<hr>
|
||
|
|
<?= $content ?>
|
||
|
|
```
|
||
|
|
|
||
|
|
Or in list templates:
|
||
|
|
|
||
|
|
```php
|
||
|
|
<pre><?php print_r($items); ?></pre>
|
||
|
|
<hr>
|
||
|
|
<?= $pageContent ?>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Remember to revert** before deploying to production.
|
||
|
|
|
||
|
|
## What's Next?
|
||
|
|
|
||
|
|
- **[Template Variables](#)** — See how metadata is used in templates
|
||
|
|
- **[Internationalization](#)** — Use language-specific metadata
|
||
|
|
- **[Creating Plugins](#)** — Process metadata in custom plugins
|