folderweb/docs/how-to/working-with-metadata.md
2025-11-02 13:46:47 +01:00

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:

  1. First H1 heading in content (# Title in Markdown)
  2. 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 true to 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 images
  • list-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:

  • title for titles
  • date for dates
  • summary for summaries
  • author for 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"