Understanding YAML Frontmatter in GeoHazardWatch pages.
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.
.md file--- markersgray-matter libraryFrontmatter 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:
┌─────────────────────────────────┐
│ --- │ ← 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... │
└─────────────────────────────────┘
Frontmatter must:
--- on its own line--- on its own line---
# 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
---
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:
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:
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:
| Category | Storage | Description | Access Level |
|---|---|---|---|
system | required-pages/ | System configuration pages | Admin only |
documentation | required-pages/ | Official documentation | Editor+ |
developer | required-pages/ | Developer docs | Developer+ |
general | pages/ | General content | All users |
user | pages/ | User-generated content | All users |
test | pages/ | Test/experimental pages | Editor+ |
Impact:
See also: Page Storage Guide
These fields enhance page functionality but are not strictly required:
user-keywords (Recommended)Purpose: Searchable tags for content discovery
Format: YAML array of strings
Example:
user-keywords:
- documentation
- examples
- markdown
- formatting
Best Practices:
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:
/view/markdown-footnotes-guideauthor (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
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
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
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:
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:
| Category | View | Edit | Delete |
|---|---|---|---|
| system | All | Admin | Admin |
| documentation | All | Editor+ | Admin |
| general | All | Contributor+ | Editor+ |
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
---
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:
required-pages/443c95f1-0b21-494a-b712-08ce0dc933e1.md/view/markdown-footnotes-guide---
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:
pages/7a8b9c0d-1e2f-3g4h-5i6j-7k8l9m0n1o2p.md/view/my-project-notes---
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:
required-pages/110fc9ee-90ca-4e6d-b6fa-334ce3074205.md/view/leftmenu---
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.
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 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
---
Wrong:
---
title: My Page
uuid: 123e4567-e89b-12d3
# Forgot closing ---
# Page Content
Error: Entire page treated as frontmatter
Fix: Always include closing ---
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
---
Wrong:
uuid: 4A266851-F3CD-4BA6-BBBE-5A408F3ADF72
Problem: File lookup may fail
Fix: Always use lowercase
uuid: 4a266851-f3cd-4ba6-bbbe-5a408f3adf72
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
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.
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
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
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
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();
---
# 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 | Date | Changes |
|---|---|---|
| 1.0.0 | 2025-10-20 | Initial documentation |
Questions or Issues?
Last Updated: 2025-10-20
Maintained By: ngdpbase Documentation Team
Status: Current ✅