folderweb/docs/reference/metadata.md
Ruben 441c8bca68 Add hide_list metadata option to directories
Add support for hide_list metadata option that allows directories to be
displayed as pages instead of lists when they contain subfolders
2025-11-25 20:30:11 +01:00

625 lines
11 KiB
Markdown

# Metadata Reference
Complete reference for all metadata fields and their usage in `metadata.ini` files.
## File Format
Metadata files use INI format:
```ini
; Comments start with semicolon
key = "value"
array[] = "value1"
array[] = "value2"
[section]
key = "section value"
```
## Standard Fields
### title
**Type**: String
**Used in**: All content types
**Purpose**: Override automatic title extraction
```ini
title = "Custom Page Title"
```
If not provided, FolderWeb extracts title from:
1. First H1 heading (`# Title` in Markdown)
2. Folder name (as fallback)
**Multi-language**:
```ini
title = "English Title"
[no]
title = "Norsk Tittel"
[fr]
title = "Titre Français"
```
### date
**Type**: Date string (YYYY-MM-DD)
**Used in**: Blog posts, articles
**Purpose**: Override automatic date extraction
```ini
date = "2025-11-02"
```
If not provided, FolderWeb extracts date from folder names like `2025-11-02-post-title`.
Dates are automatically formatted in Norwegian style: "2. november 2025"
### summary
**Type**: String
**Used in**: List views
**Purpose**: Brief description for cards and listings
```ini
summary = "A concise description that appears in blog listings."
```
**Multi-language**:
```ini
summary = "English summary"
[no]
summary = "Norsk sammendrag"
```
### menu
**Type**: Boolean
**Used in**: Top-level directories
**Purpose**: Include in site navigation
```ini
menu = true
```
Accepted values: `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off`
### menu_order
**Type**: Integer
**Used in**: Navigation items
**Purpose**: Control navigation order (lower numbers first)
```ini
menu = true
menu_order = 1
```
### page_template
**Type**: String
**Used in**: Directories with subdirectories
**Purpose**: Choose list template
```ini
page_template = "list-grid"
```
Available values:
- `list` - Simple list (default)
- `list-grid` - Grid with cover images
- `list-card-grid` - Card-style grid
- `list-faq` - Expandable FAQ format
- Any custom template name (without `.php` extension)
### slug
**Type**: String
**Used in**: Language sections
**Purpose**: Translate URL segments
```ini
[no]
slug = "om-oss"
[fr]
slug = "a-propos"
```
The actual folder is `about/`, but URLs become:
- `/about/` (English)
- `/no/om-oss/` (Norwegian)
- `/fr/a-propos/` (French)
### hide_list
**Type**: Boolean
**Used in**: Directories with subdirectories
**Purpose**: Hide list of subfolders and show only page content
```ini
hide_list = true
```
When enabled, directories with subfolders display as regular pages instead of showing a list view. Useful when you need subfolders for organization but want to present a single page to visitors.
Accepted values: `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off`
### redirect
**Type**: URL string
**Used in**: List items (with `list-card-grid` template)
**Purpose**: Link to external site instead of internal page
```ini
redirect = "https://example.com"
```
Creates an external link card in card grid layouts.
## Custom Fields
You can add any custom fields for use in your templates:
### Common Custom Fields
```ini
; Author information
author = "Jane Doe"
author_email = "jane@example.com"
author_url = "https://janedoe.com"
; Content metadata
reading_time = "5 min"
difficulty = "intermediate"
featured = true
; Categorization
tags[] = "PHP"
tags[] = "Tutorial"
tags[] = "Web Development"
categories[] = "Programming"
categories[] = "Backend"
; SEO
meta_description = "Complete guide to FolderWeb metadata"
meta_keywords = "metadata, ini, folderweb"
; Social sharing
og_image = "/blog/post/social-card.jpg"
twitter_card = "summary_large_image"
; Version tracking
version = "1.2.0"
last_updated = "2025-11-02"
; Display options
hide_date = true
hide_author = false
hide_list = true
show_toc = true
; External references
github_url = "https://github.com/user/repo"
demo_url = "https://demo.example.com"
download_url = "/files/document.pdf"
```
## Array Fields
Use `[]` syntax for array values:
```ini
tags[] = "PHP"
tags[] = "Web Development"
tags[] = "Tutorial"
authors[] = "Jane Doe"
authors[] = "John Smith"
related_posts[] = "/blog/post-1/"
related_posts[] = "/blog/post-2/"
```
Access in templates:
```php
<?php foreach ($metadata['tags'] as $tag): ?>
<span><?= htmlspecialchars($tag) ?></span>
<?php endforeach; ?>
```
## Boolean Values
Accepted boolean formats:
```ini
; True values
featured = true
featured = 1
featured = yes
featured = on
; False values
draft = false
draft = 0
draft = no
draft = off
```
## Language Sections
Use `[lang]` sections for multi-language overrides:
```ini
; Base values (default language)
title = "About Us"
summary = "Learn about our company"
slug = "about"
; Norwegian overrides
[no]
title = "Om Oss"
summary = "Lær om vårt selskap"
slug = "om-oss"
; French overrides
[fr]
title = "À Propos"
summary = "Découvrez notre entreprise"
slug = "a-propos"
; Fields not overridden inherit base values
```
Language-specific fields override base fields for that language.
## Comments
Use `;` or `#` for comments:
```ini
; This is a comment
title = "My Page"
# This is also a comment
date = "2025-11-02"
; Comments can be on same line as values
menu = true ; Include in navigation
```
## Special Characters
### Quotes
Use quotes for values with special characters:
```ini
; Optional for simple values
title = Simple Title
title = "Simple Title"
; Required for values with spaces at start/end
title = " Padded Title "
; Required for values with special characters
summary = "Use \"quotes\" for nested quotes"
summary = 'Single quotes work too'
```
### Escape Sequences
Standard INI escape sequences:
```ini
; Newline
text = "First line\nSecond line"
; Tab
text = "Indented\ttext"
; Quote
text = "He said \"Hello\""
```
## Metadata Location
### Directory Metadata
Place `metadata.ini` in the directory it describes:
```
content/blog/metadata.ini # Blog configuration
content/about/metadata.ini # About page metadata
```
### Item Metadata
Place `metadata.ini` in each subdirectory:
```
content/blog/2025-11-01-post/metadata.ini # Post metadata
content/blog/2025-11-02-post/metadata.ini # Post metadata
```
## Metadata Scope
Metadata applies only to its directory. **No inheritance** from parent directories.
## Complete Examples
### Blog Configuration
**content/blog/metadata.ini**:
```ini
; Display settings
title = "Blog"
page_template = "list-grid"
; Navigation
menu = true
menu_order = 1
; Multi-language
[no]
title = "Blogg"
slug = "blogg"
[fr]
title = "Blog"
slug = "blog"
```
### Blog Post
**content/blog/2025-11-02-web-performance/metadata.ini**:
```ini
; Basic information
title = "Optimizing Web Performance"
date = "2025-11-02"
summary = "Learn techniques to make your website faster."
; Author information
author = "Jane Developer"
author_url = "https://jane.dev"
; Content metadata
reading_time = "8 min"
difficulty = "intermediate"
featured = true
; Categorization
tags[] = "Performance"
tags[] = "Web Development"
tags[] = "Optimization"
categories[] = "Technical"
categories[] = "Tutorial"
; SEO
meta_description = "Complete guide to web performance optimization"
; Multi-language versions
[no]
title = "Optimalisering av Nettsideytelse"
summary = "Lær teknikker for å gjøre nettsiden din raskere."
[fr]
title = "Optimisation des Performances Web"
summary = "Apprenez à accélérer votre site web."
```
### Documentation Page
**content/docs/metadata.ini**:
```ini
title = "Documentation"
menu = true
menu_order = 2
page_template = "list"
; Custom fields
show_toc = true
github_url = "https://github.com/user/repo"
[no]
title = "Dokumentasjon"
slug = "dokumentasjon"
```
### Portfolio Project
**content/portfolio/project-name/metadata.ini**:
```ini
title = "Project Name"
date = "2025-11-02"
summary = "Brief project description"
; External links
redirect = "https://project-demo.com"
github_url = "https://github.com/user/project"
; Project details
client = "Company Name"
role = "Lead Developer"
technologies[] = "PHP"
technologies[] = "HTML"
technologies[] = "CSS"
[no]
title = "Prosjektnavn"
summary = "Kort prosjektbeskrivelse"
```
### FAQ Section
**content/faq/metadata.ini**:
```ini
title = "Frequently Asked Questions"
menu = true
menu_order = 4
page_template = "list-faq"
[no]
title = "Ofte Stilte Spørsmål"
slug = "oss"
[fr]
title = "Questions Fréquemment Posées"
slug = "faq"
```
## Accessing Metadata in Templates
### In Page Templates
Variable: `$pageMetadata`
```php
<?php
$title = $pageMetadata['title'] ?? 'Untitled';
$author = $pageMetadata['author'] ?? null;
$tags = $pageMetadata['tags'] ?? [];
?>
<article>
<h1><?= htmlspecialchars($title) ?></h1>
<?php if ($author): ?>
<p class="author">By <?= htmlspecialchars($author) ?></p>
<?php endif; ?>
<?= $content ?>
<?php if (!empty($tags)): ?>
<div class="tags">
<?php foreach ($tags as $tag): ?>
<span class="tag"><?= htmlspecialchars($tag) ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
</article>
```
### In List Templates
Variable: `$metadata` (directory metadata), `$items` (item metadata)
```php
<!-- Directory metadata -->
<h1><?= htmlspecialchars($metadata['title'] ?? 'Untitled') ?></h1>
<!-- Items with their 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; ?>
</article>
<?php endforeach; ?>
```
## Validation
### Check Syntax
Test INI file parsing:
```bash
php -r "print_r(parse_ini_file('content/blog/metadata.ini', true));"
```
### Common Errors
**Unquoted special characters**:
```ini
; Wrong
title = Title with: special characters
; Correct
title = "Title with: special characters"
```
**Missing array brackets**:
```ini
; Wrong (only last value kept)
tags = "PHP"
tags = "Tutorial"
; Correct (array created)
tags[] = "PHP"
tags[] = "Tutorial"
```
**Invalid section names**:
```ini
; Wrong
[language.no]
; Correct
[no]
```
## Best Practices
### Always Escape Output
```php
<?= htmlspecialchars($metadata['title']) ?>
```
### Provide Defaults
```php
$author = $metadata['author'] ?? 'Anonymous';
$tags = $metadata['tags'] ?? [];
```
### Check Before Using
```php
<?php if (isset($metadata['author'])): ?>
<p>By <?= htmlspecialchars($metadata['author']) ?></p>
<?php endif; ?>
```
### Use Consistent Field Names
Stick to standard names across your site:
- `author` not `writer` or `by`
- `tags` not `keywords` or `topics`
- `summary` not `description` or `excerpt`
### Document Custom Fields
Add comments explaining non-obvious fields:
```ini
; Featured articles appear at top of homepage
featured = true
; External demo link (overrides internal page)
demo_url = "https://demo.example.com"
```
## Related
- [Multi-Language Guide](../how-to/multi-language.md)
- [Working with Metadata](../how-to/working-with-metadata.md)
- [Template Variables Reference](templates.md)
- [Configuration Reference](configuration.md)