GeoHazardWatch

Page Actions


Frontmatter

Understanding YAML Frontmatter in GeoHazardWatch pages.

Table of Contents

  1. Overview
  2. What is Frontmatter?
  3. Structure and Syntax
  4. Required Fields
  5. Optional Fields
  6. How Frontmatter is Used
  7. Examples
  8. Best Practices
  9. Common Mistakes
  10. Technical Implementation
  11. Related Documentation

Overview

Frontmatter is a block of YAML metadata at the beginning of every page that contains essential information about the page such as its title, category, keywords, and more. It's fundamental to how GeoHazardWatch organizes, stores, and processes page content.

Key Points

  • Format: YAML (YAML Ain't Markup Language)
  • Location: Top of every .md file
  • Delimiters: Enclosed between --- markers
  • Purpose: Store page metadata separately from content
  • Processing: Parsed by the gray-matter library

What is Frontmatter?

Frontmatter is a metadata block that appears at the very beginning of a markdown file, before any actual content. It provides structured information about the page that the platform uses for:

  • Page identification via UUID
  • Storage location determination via system-category
  • Search and discovery via title and keywords
  • Organization and categorization
  • Access control and permissions
  • Version tracking and attribution

Visual Structure

┌─────────────────────────────────┐
│ ---                             │ ← Opening delimiter
│ title: Page Title               │
│ uuid: 123e4567-e89b-12d3        │ ← YAML metadata
│ system-category: documentation  │
│ user-keywords:                  │
│   - keyword1                    │
│   - keyword2                    │
│ ---                             │ ← Closing delimiter
│                                 │
│ # Page Content Starts Here      │ ← Markdown content
│                                 │
│ Your page content...            │
└─────────────────────────────────┘


Structure and Syntax

Basic Format

Frontmatter must:

  1. Start at the very beginning of the file (line 1)
  2. Begin with --- on its own line
  3. Contain valid YAML key-value pairs
  4. End with --- on its own line
  5. Be followed by markdown content

YAML Syntax Rules

---
# String values
title: Simple String
author: John Doe

# String with special characters (use quotes)
title: "String: with colons"
slug: "my-page-slug"

# Array/List values
user-keywords:
  - keyword1
  - keyword2
  - keyword3

# Or inline array format
user-keywords: [keyword1, keyword2, keyword3]

# Date/timestamp (ISO 8601 format, quoted)
lastModified: '2025-10-20T10:47:21.921Z'

# UUID (lowercase, hyphenated)
uuid: 443c95f1-0b21-494a-b712-08ce0dc933e1

# Boolean values
published: true
draft: false
---


Required Fields

Every page must include these frontmatter fields:

title (Required)

Purpose: Human-readable name of the page

Format: String

Display: Used in navigation, search results, page headers, and links

Example:

title: Markdown Footnotes Guide

Rules:

  • Must be unique on the platform
  • Use clear, descriptive titles
  • Avoid special characters that may cause URL encoding issues
  • Recommended: 3-10 words

uuid (Required)

Purpose: Unique identifier for the page

Format: UUID v4 (lowercase, hyphenated)

Used for: Filename, internal references, version tracking

Example:

uuid: 443c95f1-0b21-494a-b712-08ce0dc933e1

Rules:

  • Must be globally unique
  • Lowercase letters only
  • Hyphenated format (8-4-4-4-12)
  • Auto-generated on page creation
  • Never change after creation

Generation:

# On Unix/Mac
uuidgen | tr '[:upper:]' '[:lower:]'

# Output example
4a266851-f3cd-4ba6-bbbe-5a408f3adf72


system-category (Required)

Purpose: Determines storage location and access control

Format: String (must match a configured category)

Default: general if not specified

Example:

system-category: documentation

Available Categories:

CategoryStorageDescriptionAccess Level
systemrequired-pages/System configuration pagesAdmin only
documentationrequired-pages/Official documentationEditor+
developerrequired-pages/Developer docsDeveloper+
generalpages/General contentAll users
userpages/User-generated contentAll users
testpages/Test/experimental pagesEditor+

Impact:

  • Controls which directory the page is stored in
  • Affects backup priority and frequency
  • Determines edit and delete permissions
  • Influences cache behavior

See also: Page Storage Guide


Optional Fields

These fields enhance page functionality but are not strictly required:

Purpose: Searchable tags for content discovery

Format: YAML array of strings

Example:

user-keywords:
  - documentation
  - examples
  - markdown
  - formatting

Best Practices:

  • Use 3-5 relevant keywords
  • Choose specific, searchable terms
  • Include synonyms users might search for
  • Avoid generic terms like "page" or "wiki"
  • Use lowercase for consistency

slug (Optional)

Purpose: URL-friendly version of the title

Format: Lowercase string with hyphens

Auto-generated: From title if not provided

Example:

title: Markdown Footnotes Guide
slug: markdown-footnotes-guide

Rules:

  • Lowercase letters, numbers, hyphens only
  • No spaces or special characters
  • Should reflect the page title
  • Used in URL: /view/markdown-footnotes-guide

author (Optional)

Purpose: Track page creator or maintainer

Format: String (username or full name)

Example:

author: ngdpbase Team
author: john.doe
author: Jane Smith

Display: Shown in page metadata sidebar


lastModified (Automatic)

Purpose: Track when page was last edited

Format: ISO 8601 timestamp (quoted string)

Managed by: System automatically updates on save

Example:

lastModified: '2025-10-20T10:47:21.921Z'

Note: You typically don't need to manually set this field


How Frontmatter is Used

1. Storage Location Routing

When you save a page:

Page Save
    ↓
Read frontmatter.system-category
    ↓
Lookup category in config
    ↓
Check storageLocation property
    ↓
Route to correct directory
    ↓
Save as {uuid}.md

Example:

system-category: documentation  # → storageLocation: "required"

Result: Page saved to required-pages/4a266851-f3cd-4ba6-bbbe-5a408f3adf72.md


2. Page Identification

ngdpbase uses a three-level identification system:

1. UUID (Primary)
   └─→ Filename: {uuid}.md
   └─→ Internal references
   └─→ Never changes

2. Title (Human-readable)
   └─→ Display name
   └─→ Search results
   └─→ Can change without breaking links

3. Slug (URL-friendly)
   └─→ Web URL: /view/{slug}
   └─→ Generated from title
   └─→ Can be customized


3. Search and Discovery

Frontmatter fields power the search system:

title: Markdown Footnotes Guide     # Primary search field
user-keywords:                       # Secondary search terms
  - footnotes
  - markdown
  - references
  - citations
system-category: documentation       # Category filter

Search Behavior:

  • Title matches rank highest
  • Keywords provide additional matching
  • Category allows filtered searches
  • Author enables "find by creator"

4. Access Control

The system-category field integrates with the access control system:

system-category: system
    ↓
Lookup access policy
    ↓
Check user role
    ↓
Grant/Deny permissions

Example Access Matrix:

CategoryViewEditDelete
systemAllAdminAdmin
documentationAllEditor+Admin
generalAllContributor+Editor+


5. Cache Management

Different categories have different cache strategies:

// System pages (high priority)
system-category: system
  → cacheTTL: 3600 seconds
  → preload: true
  → priority: high

// User pages (standard)
system-category: general
  → cacheTTL: 300 seconds
  → preload: false
  → priority: normal


Examples

Example 1: Documentation Page

---
title: Markdown Footnotes Guide
uuid: 443c95f1-0b21-494a-b712-08ce0dc933e1
system-category: documentation
user-keywords:
  - documentation
  - markdown
  - footnotes
  - examples
slug: markdown-footnotes-guide
author: ngdpbase Team
lastModified: '2025-10-16T19:56:00.000Z'
---

# Markdown Footnotes Guide

This guide explains how to use footnotes in ngdpbase...

Result:

  • Stored in: required-pages/443c95f1-0b21-494a-b712-08ce0dc933e1.md
  • URL: /view/markdown-footnotes-guide
  • Searchable by: Title, keywords
  • Editable by: Editor+ roles
  • Cache: High priority, 1 hour TTL

Example 2: User Content Page

---
title: My Project Notes
uuid: 7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p
system-category: user
user-keywords:
  - project
  - notes
  - development
  - planning
slug: my-project-notes
author: jane.smith
lastModified: '2025-10-20T10:30:00.000Z'
---

# My Project Notes

These are my notes for the Q4 project...

Result:

  • Stored in: pages/7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p.md
  • URL: /view/my-project-notes
  • Editable by: Owner + Editor+
  • Cache: Standard priority, 5 minutes TTL

Example 3: System Page

---
title: LeftMenu
uuid: 110fc9ee-90ca-4e6d-b6fa-334ce3074205
system-category: system
user-keywords: []
slug: leftmenu
author: ngdpbase Team
lastModified: '2025-10-20T08:15:00.000Z'
---

[{TableOfContents}]

* [User Documentation]
* [Recent Changes]
* [SystemInfo]

Result:

  • Stored in: required-pages/110fc9ee-90ca-4e6d-b6fa-334ce3074205.md
  • URL: /view/leftmenu
  • Editable by: Admin only
  • Protected: Cannot be accidentally deleted
  • Cache: Preloaded at startup

Example 4: Minimal Valid Frontmatter

---
title: Simple Page
uuid: 1a2b3c4d-5e6f-7890-1234-567890abcdef
system-category: general
user-keywords: []
---

# Simple Page

Just the required fields. The system will auto-generate other values.


Best Practices

✅ DO

Use descriptive, unique titles

title: API Authentication Guide  # Good
title: Guide                     # Bad - too generic

Include relevant keywords

user-keywords:
  - api
  - authentication
  - oauth
  - security

Choose the appropriate category

# Official documentation
system-category: documentation

# Personal notes
system-category: user

Use proper YAML syntax

# Correct
title: "Title: With Colon"
lastModified: '2025-10-20T10:00:00.000Z'

# Incorrect
title: Title: With Colon  # Will cause parsing error

Keep keywords specific and relevant

user-keywords:
  - javascript  # Good
  - node.js     # Good
  - programming # Too broad
  - stuff       # Too vague


❌ DON'T

Don't use uppercase in UUIDs

uuid: 4A266851-F3CD-4BA6-BBBE-5A408F3ADF72  # Wrong
uuid: 4a266851-f3cd-4ba6-bbbe-5a408f3adf72  # Correct

Don't manually change lastModified

lastModified: '2025-10-20T10:00:00.000Z'  # Let system handle this

Don't use non-existent categories

system-category: my-custom-category  # Will default to 'general'

Don't forget the closing ---

---
title: My Page
uuid: 123e4567-e89b-12d3
system-category: general
# Missing closing --- will break parsing!

Don't put content before frontmatter

# My Page  ← Wrong! Content before frontmatter

---
title: My Page
---


Common Mistakes

Mistake 1: Missing Closing Delimiter

Wrong:

---
title: My Page
uuid: 123e4567-e89b-12d3
# Forgot closing ---

# Page Content

Error: Entire page treated as frontmatter

Fix: Always include closing ---


Mistake 2: Invalid YAML Syntax

Wrong:

---
title: Error: This won't parse
user-keywords: keyword1, keyword2  # Wrong array format
---

Error: YAML parsing failure

Fix:

---
title: "Error: This will parse"
user-keywords:
  - keyword1
  - keyword2
---


Mistake 3: Uppercase UUID

Wrong:

uuid: 4A266851-F3CD-4BA6-BBBE-5A408F3ADF72

Problem: File lookup may fail

Fix: Always use lowercase

uuid: 4a266851-f3cd-4ba6-bbbe-5a408f3adf72


Mistake 4: Wrong Category Name

Wrong:

system-category: Documentation  # Capital D
system-category: docs           # Abbreviated

Problem: Will default to 'general', page goes to wrong directory

Fix: Use exact category name from config

system-category: documentation


Mistake 5: Content Before Frontmatter

Wrong:

This is my page about widgets.

---
title: Widgets
uuid: 123e4567-e89b-12d3
---

Problem: Frontmatter must be at line 1

Fix: Always start with frontmatter

---
title: Widgets
uuid: 123e4567-e89b-12d3
---

This is my page about widgets.


Technical Implementation

Parsing Library

ngdpbase uses gray-matter for frontmatter parsing:

const matter = require('gray-matter');

// Parse a markdown file
const fileContent = fs.readFileSync('page.md', 'utf-8');
const parsed = matter(fileContent);

// Access frontmatter
console.log(parsed.data.title);           // "My Page"
console.log(parsed.data.uuid);            // "123e4567..."
console.log(parsed.data['system-category']); // "documentation"

// Access content
console.log(parsed.content);  // Markdown content without frontmatter

See: /Volumes/hd3/GitHub/ngdpbase/src/providers/FileSystemProvider.js:4


Processing Flow

1. Page Load Request
   ↓
2. Read file: {uuid}.md
   ↓
3. Parse with gray-matter
   ↓
4. Extract frontmatter (parsed.data)
   ↓
5. Extract content (parsed.content)
   ↓
6. Validate required fields
   ↓
7. Add to cache
   ↓
8. Return page object


Validation

The ValidationManager checks frontmatter:

// Required fields check
const requiredFields = ['title', 'uuid', 'system-category'];

// Format validation
if (!/^[a-f0-9-]{36}$/.test(uuid)) {
  throw new Error('Invalid UUID format');
}

// Category validation
const validCategories = config.get('ngdpbase.system-category');
if (!validCategories[systemCategory]) {
  console.warn(`Unknown category: ${systemCategory}, using default`);
}

See: /Volumes/hd3/GitHub/ngdpbase/src/managers/ValidationManager.js


Automatic Field Generation

When fields are missing:

// Auto-generate UUID if missing
if (!frontmatter.uuid) {
  frontmatter.uuid = uuidv4().toLowerCase();
}

// Auto-generate slug if missing
if (!frontmatter.slug) {
  frontmatter.slug = slugify(frontmatter.title);
}

// Set default category if missing
if (!frontmatter['system-category']) {
  frontmatter['system-category'] = 'general';
}

// Update lastModified on save
frontmatter.lastModified = new Date().toISOString();



Quick Reference Card

---
# Required Fields
title: Page Title                            # Display name
uuid: 4a266851-f3cd-4ba6-bbbe-5a408f3adf72  # Unique ID (lowercase)
system-category: documentation               # Storage location

# Recommended Fields
user-keywords:                               # Search tags
  - keyword1
  - keyword2

# Optional Fields
slug: page-title                             # URL-friendly name
author: Username                             # Creator

# Automatic Fields
lastModified: '2025-10-20T10:00:00.000Z'    # System-managed
---

# Page Content Starts Here


Version History

VersionDateChanges
1.0.02025-10-20Initial documentation


Questions or Issues?


Last Updated: 2025-10-20
Maintained By: ngdpbase Documentation Team
Status: Current ✅

No footnotes on this page.

No comments yet.