9.2 KiB
How to Work with Metadata
This guide shows you how to use metadata.ini files to control page behavior, appearance, and content.
What is Metadata?
Metadata provides structured information about your content directories without cluttering your content files. It's stored in metadata.ini files using the INI format.
Basic Metadata File
Create metadata.ini in any content directory:
title = "My Page Title"
date = "2025-11-02"
summary = "A brief description of this page."
Common Metadata Fields
Title
Controls the displayed title (overrides automatic title extraction):
title = "Custom Page Title"
If not provided, FolderWeb extracts the title from:
- First H1 heading in content (
# Titlein Markdown) - Folder name (as fallback)
Date
Set an explicit date (overrides folder name date extraction):
date = "2025-11-02"
Format: YYYY-MM-DD
FolderWeb automatically formats this in Norwegian style: "2. november 2025"
Summary
Add a summary for list views:
summary = "This appears in blog listings and card grids."
Summaries are displayed in:
- List views
- Grid layouts
- Card grids
Navigation Control
Adding to Menu
menu = true
menu_order = 1
- menu: Set to
trueto include in site navigation - menu_order: Controls order (lower numbers appear first)
Example - Setting up main navigation:
content/blog/metadata.ini:
menu = true
menu_order = 1
title = "Blog"
content/about/metadata.ini:
menu = true
menu_order = 2
title = "About"
content/contact/metadata.ini:
menu = true
menu_order = 3
title = "Contact"
Result: Navigation shows "Blog", "About", "Contact" in that order.
Template Control
Choosing List Template
For directories with subdirectories, control which list template is used:
page_template = "list-grid"
Available templates:
list- Simple list (default)list-grid- Grid with cover imageslist-card-grid- Card-style grid (supports PDFs, external links)list-faq- Expandable FAQ format
Example - Blog with grid layout:
content/blog/metadata.ini:
title = "Blog"
page_template = "list-grid"
External Redirects
Make a directory item link externally (used with list-card-grid):
redirect = "https://example.com"
Example - Portfolio with external links:
content/portfolio/project-live-site/metadata.ini:
title = "Visit Live Site"
summary = "Check out the deployed project."
redirect = "https://myproject.com"
When using the list-card-grid template, this creates a card that links to the external URL instead of an internal page.
Multi-Language Metadata
Use sections for language-specific overrides:
; Default language values
title = "About Us"
summary = "Learn more about our company."
[no]
title = "Om Oss"
summary = "Lær mer om vårt selskap."
slug = "om-oss"
[fr]
title = "À Propos"
summary = "Découvrez notre entreprise."
slug = "a-propos"
Language sections override base values for that language.
Translated Slugs
The slug field in language sections changes the URL:
[no]
slug = "om-oss"
Now the Norwegian version is accessible at /no/om-oss/ instead of /no/about/.
Custom Metadata Fields
You can add any custom fields you need:
title = "Article Title"
author = "Jane Doe"
reading_time = "5 min"
difficulty = "intermediate"
featured = true
Access these in custom templates:
<?php if (isset($metadata['author'])): ?>
<p class="author">By <?= htmlspecialchars($metadata['author']) ?></p>
<?php endif; ?>
<?php if (isset($metadata['reading_time'])): ?>
<span class="reading-time"><?= htmlspecialchars($metadata['reading_time']) ?></span>
<?php endif; ?>
Arrays in Metadata
INI format supports arrays using repeated keys:
tags[] = "PHP"
tags[] = "Web Development"
tags[] = "Tutorial"
categories[] = "Programming"
categories[] = "Backend"
Access in templates:
<?php if (!empty($metadata['tags'])): ?>
<div class="tags">
<?php foreach ($metadata['tags'] as $tag): ?>
<span class="tag"><?= htmlspecialchars($tag) ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
Boolean Values
Use true, false, 1, 0, yes, no, on, off:
menu = true
featured = yes
draft = false
Comments
Add comments with ; or #:
; This is a comment
title = "My Page"
# This is also a comment
date = "2025-11-02"
Metadata Inheritance
Metadata does not inherit from parent directories. Each directory needs its own metadata.ini.
Metadata for List Items
When a directory is displayed in a list view, FolderWeb loads its metadata:
content/blog/2025-11-01-first-post/metadata.ini:
title = "My First Blog Post"
date = "2025-11-01"
summary = "An introduction to blogging with FolderWeb."
This metadata appears in the blog listing at /blog/.
Complete Example: Blog Setup
Blog Directory Metadata
content/blog/metadata.ini:
title = "Blog"
menu = true
menu_order = 1
page_template = "list-grid"
[no]
title = "Blogg"
slug = "blogg"
Individual Post Metadata
content/blog/2025-11-02-web-performance/metadata.ini:
title = "Optimizing Web Performance"
date = "2025-11-02"
summary = "Learn techniques to make your website faster."
author = "Jane Developer"
reading_time = "8 min"
tags[] = "Performance"
tags[] = "Web Development"
tags[] = "Optimization"
categories[] = "Technical"
categories[] = "Tutorial"
[no]
title = "Optimalisering av Nettsideytelse"
summary = "Lær teknikker for å gjøre nettsiden din raskere."
Accessing Metadata in Templates
In Page Templates
<?php
// Page-specific metadata
$metadata = $pageMetadata;
// Access fields
$author = $metadata['author'] ?? 'Unknown';
$tags = $metadata['tags'] ?? [];
?>
<article>
<header>
<h1><?= htmlspecialchars($metadata['title'] ?? '') ?></h1>
<p class="author">By <?= htmlspecialchars($author) ?></p>
</header>
<?= $content ?>
<?php if (!empty($tags)): ?>
<footer class="tags">
<?php foreach ($tags as $tag): ?>
<span><?= htmlspecialchars($tag) ?></span>
<?php endforeach; ?>
</footer>
<?php endif; ?>
</article>
In List Templates
Each item in $items includes its metadata:
<?php foreach ($items as $item): ?>
<article>
<h2>
<a href="<?= $item['url'] ?>">
<?= htmlspecialchars($item['title']) ?>
</a>
</h2>
<?php if ($item['date']): ?>
<time><?= $item['date'] ?></time>
<?php endif; ?>
<?php if ($item['summary']): ?>
<p><?= htmlspecialchars($item['summary']) ?></p>
<?php endif; ?>
<?php if ($item['cover']): ?>
<img src="<?= $item['cover'] ?>" alt="">
<?php endif; ?>
<?php if ($item['pdf']): ?>
<a href="<?= $item['pdf'] ?>" download>Download PDF</a>
<?php endif; ?>
<?php if ($item['redirect']): ?>
<a href="<?= $item['redirect'] ?>" target="_blank" rel="noopener">
Visit External Link
</a>
<?php endif; ?>
</article>
<?php endforeach; ?>
Debugging Metadata
Check if Metadata is Loaded
In your template, dump the metadata:
<pre><?php var_dump($metadata); ?></pre>
Or for list items:
<pre><?php var_dump($items); ?></pre>
Verify INI Syntax
Use PHP to test your INI file:
php -r "print_r(parse_ini_file('content/blog/metadata.ini', true));"
This shows parsed values and helps identify syntax errors.
Best Practices
Use Consistent Field Names
Stick to standard fields for common data:
titlefor titlesdatefor datessummaryfor summariesauthorfor authors
Escape Output
Always escape metadata in templates:
<?= htmlspecialchars($metadata['title']) ?>
Provide Defaults
Use null coalescing for missing fields:
$author = $metadata['author'] ?? 'Anonymous';
$date = $metadata['date'] ?? 'Unknown date';
Keep It Simple
Only add metadata fields you actually use. Don't over-engineer.
Use Comments
Document non-obvious metadata:
; Featured articles appear at the top of the homepage
featured = true
; Legacy field kept for backwards compatibility
old_url = "/blog/old-slug/"
Common Patterns
Blog Post
title = "Post Title"
date = "2025-11-02"
summary = "Brief description"
author = "Author Name"
tags[] = "tag1"
tags[] = "tag2"
Documentation Page
title = "API Reference"
menu = true
menu_order = 3
page_template = "list"
Portfolio Item
title = "Project Name"
date = "2025-11-02"
summary = "Project description"
redirect = "https://live-demo.com"
FAQ Section
title = "Frequently Asked Questions"
menu = true
menu_order = 4
page_template = "list-faq"