Page Metadata Documentation

Last modified: 10/20/2025

Page Metadata Documentation

This document defines all metadata fields used in GeoHazardWatch page frontmatter (YAML header), designed for full Schema.org WebPage compliance to ensure optimal SEO and semantic web integration.

Schema.org WebPage Alignment

GeoHazardWatch metadata fields directly map to Schema.org WebPage properties for maximum semantic web compatibility and search engine optimization.

Required Fields (Schema.org Core Properties)

name (mapped to title)

headline (mapped to title)

identifier (mapped to uuid)

dateModified (mapped to lastModified)

url (auto-generated)

Extended Required Fields (ngdpbase-Specific)

pageType

category (storage-based classification)

system-category are assigned by Admin

keywords (mapped to user-keywords)

User Keywords defines keywords that are set by users

System Keywords

System Keywords are assigned by the system.
Currently the only value is "general"

Optional Fields (Schema.org Enhanced Properties)

about (mapped to categories)

dateCreated

author (auto-generated)

isPartOf (auto-generated)

mainContentOfPage (auto-generated)

documentationType

isProtected

inLanguage (auto-generated)

license (auto-generated)

publisher (auto-generated)

Complete Schema.org WebPage Example

---
# Required Schema.org WebPage Properties
title: "API Documentation"              # → name, headline
pageType: "documentation"               # → additionalType (ngdpbase-specific)
category: "Developer"                   # → about (DefinedTerm) - storage-based
uuid: "api-docs-v1-uuid"               # → identifier
lastModified: "2025-09-10T10:00:00.000Z"  # → dateModified

# Optional Schema.org Enhanced Properties  
user-keywords: [api, reference, integration]  # → keywords
categories: [Developer, API]               # → about (multiple DefinedTerms) - detailed classification
documentationType: "api"                   # → audience enhancement
dateCreated: "2025-09-01T10:00:00.000Z"  # → dateCreated
isProtected: true                          # → access control (not Schema.org)

# Auto-generated Schema.org Properties (not in frontmatter):
# url: "https://example.com/view/API Documentation"
# author: { "@type": "Organization", "name": "ngdpbase Platform" }
# publisher: { "@type": "Organization", "name": "ngdpbase Platform" }  
# isPartOf: { "@type": "WebSite", "name": "ngdpbase Platform", "url": "/" }
# breadcrumb: { "@type": "BreadcrumbList", ... } (from categories array)
# mainContentOfPage: { "@type": "WebPageElement", "cssSelector": ".wiki-content" }
# inLanguage: "en-US"
# license: "https://example.com/terms"
---

Schema.org JSON-LD Output Example

The above metadata generates this Schema.org JSON-LD:

{
  "@context": "https://schema.org",
  "@type": "WebPage",
  "name": "API Documentation",
  "headline": "API Documentation", 
  "url": "https://example.com/view/API%20Documentation",
  "identifier": "api-docs-v1-uuid",
  "dateModified": "2025-09-10T10:00:00.000Z",
  "dateCreated": "2025-09-01T10:00:00.000Z",
  "inLanguage": "en-US",
  "keywords": "api, reference, integration",
  "about": [
    {
      "@type": "DefinedTerm",
      "name": "Developer",
      "inDefinedTermSet": {
        "@type": "DefinedTermSet", 
        "name": "ngdpbase Categories"
      }
    },
    {
      "@type": "DefinedTerm",
      "name": "API",
      "inDefinedTermSet": {
        "@type": "DefinedTermSet", 
        "name": "ngdpbase Categories"
      }
    }
  ],
  "breadcrumb": {
    "@type": "BreadcrumbList",
    "itemListElement": [
      {
        "@type": "ListItem",
        "position": 1,
        "name": "Developer",
        "item": "https://example.com/category/Developer"
      },
      {
        "@type": "ListItem", 
        "position": 2,
        "name": "API",
        "item": "https://example.com/category/API"
      }
    ]
  },
  "mainContentOfPage": {
    "@type": "WebPageElement",
    "cssSelector": ".wiki-content"
  },
  "isPartOf": {
    "@type": "WebSite",
    "name": "ngdpbase Platform",
    "url": "https://example.com/"
  },
  "author": {
    "@type": "Organization", 
    "name": "ngdpbase Platform"
  },
  "publisher": {
    "@type": "Organization",
    "name": "ngdpbase Platform"
  },
  "hasDigitalDocumentPermission": [
    {
      "@type": "DigitalDocumentPermission",
      "permissionType": "ReadPermission",
      "grantee": {
        "@type": "Audience",
        "audienceType": "public"
      }
    },
    {
      "@type": "DigitalDocumentPermission", 
      "permissionType": "WritePermission",
      "grantee": {
        "@type": "Audience",
        "audienceType": "developer"
      }
    },
    {
      "@type": "DigitalDocumentPermission",
      "permissionType": "CreatePermission", 
      "grantee": {
        "@type": "Audience",
        "audienceType": "developer"
      }
    },
    {
      "@type": "DigitalDocumentPermission",
      "permissionType": "DeletePermission",
      "grantee": {
        "@type": "Person",
        "name": "admin"
      }
    },
    {
      "@type": "DigitalDocumentPermission",
      "permissionType": "UploadPermission",
      "grantee": {
        "@type": "Audience",
        "audienceType": "contributor"
      }
    },
    {
      "@type": "DigitalDocumentPermission",
      "permissionType": "CommentPermission",
      "grantee": {
        "@type": "Audience",
        "audienceType": "authenticated"
      }
    }
  ]
}

Schema.org WebPage Field Mapping Summary

ngdpbase FieldSchema.org PropertyRequiredTypeMax ValuesAuto-Generated
titlename, headline✅ YesText1No
uuididentifier✅ YesPropertyValue/Text1Yes
lastModifieddateModified✅ YesDateTime1Yes
pageTypeadditionalType✅ YesText1No
categoryabout (DefinedTerm)✅ YesDefinedTerm1No
user-keywordskeywords❌ NoText3No
categoriesabout (multiple)❌ NoDefinedTerm3No
dateCreateddateCreated❌ NoDateTime1Optional
documentationTypeaudience (enhanced)❌ NoText1No
isProtectedhasDigitalDocumentPermission❌ NoDigitalDocumentPermissionMultipleYes
(auto)url✅ YesURL1Yes
(auto)author✅ YesOrganization1Yes
(auto)publisher✅ YesOrganization1Yes
(auto)isPartOf✅ YesWebSite1Yes
(auto)breadcrumb❌ NoBreadcrumbList1Yes
(auto)mainContentOfPage❌ NoWebPageElement1Yes
(auto)inLanguage✅ YesLanguage1Yes
(auto)license❌ NoURL/CreativeWork1Yes

Schema.org WebPage Benefits

SEO Optimization

Semantic Web Integration

Technical Advantages

Usage Guidelines

For Content Creators

User Keywords Storage Architecture

Problem Statement

User keywords need to be:

  1. Extendable by users during normal operation
  2. Preserved during app upgrades
  3. Merged with new base keywords from app updates
  4. Validated to prevent duplicates and maintain consistency

Hybrid Storage Solution

Primary Storage Locations

Storage LocationPurposeUpgrade BehaviorContent Type
/required-pages/User Keywords.md**Base Keywords**ReplacedApp-provided defaults
/users/user-keywords.json**User Extensions**PreservedUser-added keywords
Runtime Merge**Combined List**AutomaticBase + User extensions

Base Keywords (/required-pages/User Keywords.md)

---
title: User Keywords  
pageType: system
isProtected: true
---
# User Keywords

## Base System Keywords
- documentation
- test
- system
- template
- security
- api
- reference
- integration

User Extensions (/users/user-keywords.json)

{
  "userDefinedKeywords": [
    "geology",
    "medicine", 
    "psychology",
    "project-planning",
    "personal"
  ],
  "lastModified": "2025-09-10T10:00:00.000Z",
  "addedBy": {
    "admin": ["geology", "medicine"],
    "user1": ["psychology"],
    "user2": ["project-planning", "personal"]
  }
}

Runtime Merging Process

  1. Load Base: Read keywords from /required-pages/User Keywords.md
  2. Load Extensions: Read user keywords from /users/user-keywords.json
  3. Merge & Deduplicate: Combine arrays, remove duplicates (case-insensitive)
  4. Sort & Present: Alphabetical order for consistency
  5. Validate Selection: Ensure max 3 keywords per page

Upgrade Safety Workflow

During App Upgrade

# 1. Backup user extensions (automatic)
cp /users/user-keywords.json /users/user-keywords.backup.json

# 2. Replace base keywords (app-managed)
# /required-pages/User Keywords.md gets new app defaults

# 3. Merge user extensions (automatic) 
# System reads both files and merges at runtime

# 4. Validate & clean (post-upgrade)
# Remove any invalid keywords, update JSON format if needed

User Interface Behavior

Implementation Requirements

KeywordManager Component

class KeywordManager {
  async getAvailableKeywords() {
    const baseKeywords = await this.loadBaseKeywords();
    const userKeywords = await this.loadUserKeywords(); 
    return this.mergeAndDeduplicate(baseKeywords, userKeywords);
  }
  
  async addUserKeyword(keyword, userId) {
    // Add to /users/user-keywords.json
    // Validate against existing keywords
    // Track who added it for audit
  }
  
  async removeUserKeyword(keyword, userId) {
    // Remove from /users/user-keywords.json only
    // Cannot remove base keywords
  }
}

Validation Rules

Migration Strategy

Phase 1: Consolidate Existing Files

  1. Audit Current Keywords: Extract all unique keywords from existing pages
  2. Classify Keywords:
    • Common/system keywords → Base keywords
    • User-specific keywords → User extensions
  3. Create Base File: New /required-pages/User Keywords.md with system defaults
  4. Create Extensions File: New /users/user-keywords.json with user additions

Phase 2: Update References

  1. Update Documentation: All references point to new hybrid system
  2. Update Page Validation: Use merged keyword list for validation
  3. Update Edit Interface: Show merged list, track additions properly

Phase 3: Test Upgrade Process

  1. Simulate Upgrade: Replace base keywords, verify user extensions preserved
  2. Test Merging: Ensure no duplicates, proper sorting
  3. Validate Pages: All existing user-keywords still valid after merge

Benefits

Upgrade Safety: User keywords never lost during app updates
Extensibility: Users can add keywords without editing system files
Consistency: Base keywords ensure common vocabulary across installations
Audit Trail: Track who added which keywords for management
Performance: Merging happens at edit time, not page load time
Backup: User extensions automatically preserved and trackable

For Developers

Schema.org WebPage Validation

Required Schema.org Properties (Auto-Generated)

@context: "https://schema.org"
@type: "WebPage"
name: From title field
url: Auto-generated from base URL + page title
dateModified: From lastModified field

Enhanced Schema.org Properties (Context-Dependent)

🔄 headline: From title field
🔄 identifier: From uuid field
🔄 keywords: From user-keywords array
🔄 about: From category and categories fields as DefinedTerms
🔄 breadcrumb: Auto-generated from hierarchical categories
🔄 author: Auto-generated Organization object
🔄 publisher: Auto-generated Organization object
🔄 isPartOf: Auto-generated WebSite object
🔄 mainContentOfPage: Auto-generated WebPageElement
🔄 inLanguage: Auto-generated "en-US"

Validation Tools

File System Organization

Storage Strategy by Category

CategoryStorage LocationUpgrade BehaviorManagementPurpose
General/pages/Always PreservedUserUser-generated content
System/required-pages/May be ReplacedAppRequired system pages
Documentation/required-pages/Updated with AppAppUser documentation
Developer/docs/VersionedDeveloperTechnical documentation

Storage Examples by Category

/pages/ (General Category)

/required-pages/ (System Category)

/required-pages/ (Documentation Category)

/docs/ (Developer Category)

Content Classification Strategy

Primary: Storage-based categories determine file location and upgrade behavior
Secondary: User-keywords provide detailed content classification and filtering

This approach separates operational concerns (where files live) from content concerns (what they contain).

Schema.org WebPage Entity Strategy

ngdpbase uses Schema.org WebPage as the primary entity type for full compliance with web standards and optimal SEO performance.

Why Schema.org WebPage?

Schema.org WebPage is the most appropriate entity type for page content because:

Schema.org Type Selection by Page Category

Page CategorySchema.org TypePrimary ReasoningAdditional Properties
**All Pages****WebPage**Universal web standardbreadcrumb, mainContentOfPage
System/***WebPage**Navigation-heavy reference pagessignificantLink array
Documentation**WebPage** + TechArticleTechnical content with web navigationabout with DefinedTerm
Project**WebPage** + CreativeWorkPlanning docs with collaborationauthor, contributor
Meeting Notes**WebPage** + ArticleTime-based collaborative contentdateCreated, dateModified
General**WebPage**Standard page structureCore WebPage properties

Note: GeoHazardWatch defaults to WebPage for all content, with additional types layered on through additionalType or about properties when appropriate.

Schema.org WebPage Property Coverage

Core Properties (Always Present)

Enhanced Properties (Context-Dependent)

Organizational Properties (Auto-Generated)

Validation and Testing

All GeoHazardWatch pages generate Schema.org WebPage JSON-LD that validates against:

See system-category for category configuration, System Keywords and User Keywords for keyword management, and User Documentation for related guides.