# 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 `
`, 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, `` 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:** ` ` 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
By = htmlspecialchars($metadata['author']) ?>
View Project
```
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
= htmlspecialchars($item['title']) ?>
By = htmlspecialchars($item['author']) ?>
= htmlspecialchars($item['summary']) ?>
```
## 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
= $content ?>
```
Or in list templates:
```php
= $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