Frontmatter
Every .md page can carry a YAML block at the top, delimited by --- on the first line and a matching --- after the keys. ShellDocs.Core's FrontmatterParser reads it via YamlDotNet, and the framework consumes a small handful of well-known keys.
Shape
---
title: My Page
description: Short summary shown as page subtitle and meta description.
order: 3
category: Guides
---
# My Page
Body starts here.
Both delimiters are literal --- on their own line. The block is optional : a page with no frontmatter still renders (title falls back to the slug).
Fields ShellDocs reads
| Prop | Type | Default | Description |
|---|---|---|---|
description |
string |
— | Sidebar tooltip, page subtitle under H1, meta description. Indexed by search : matches on description weight higher than body matches. |
order |
int |
0 |
Sort order within a folder when meta.json doesn't list the page explicitly. Lower first; ties fall back to alphabetical. |
category |
string? |
— | Optional grouping label. Currently surfaced as `NavigationNode.Category` : reserved for future sidebar grouping. |
Free-form keys
Any additional keys are parsed into the frontmatter dictionary and available via RenderedDocument.Frontmatter.GetValue<T>("key"). Useful for:
- Author / date / revision (surface in your own layout)
- Feature flags (
draft: true,experimental: true) - Cross-tool metadata (custom fields your CI pipeline reads)
ShellDocs itself ignores keys it doesn't recognize : nothing breaks if you add your own.
Type coercion
GetValue<T> returns the value cast to T, using Convert.ChangeType when the raw parse doesn't match. So order: 3 in YAML lands as a long from YamlDotNet, then coerces to int at read time. Pattern:
int order = doc.Frontmatter.GetValue<int>("order");
string? draft = doc.Frontmatter.GetValue<string>("draft");
If the key is missing or coercion fails, GetValue<T> returns default(T).
Multiline strings
Standard YAML block-scalars work : | preserves newlines, > folds them into spaces.
---
title: Migration
description: >
Multi-line description that folds line breaks into single spaces
so you don't have to fight rewrapping.
---
Escaping quotes and colons
Values with colons or leading punctuation need quoting : YAML parses them as flow-scalars otherwise.
---
title: "Callouts : tips, warnings, and danger boxes"
description: "The `Callout` primitive."
---
Prefer double-quotes so backticks stay literal.
When frontmatter is missing or broken
- No
---block at all : the page still renders. Title falls back to the slug. - Opening
---with no closing---: parser treats it as no frontmatter and passes the whole file through as body. - Malformed YAML : parser catches the
YamlExceptionand returns an empty frontmatter dict, still handing the body through untouched. The page renders with slug-derived title.
Broken YAML doesn't throw : the page just renders with defaults. If a page's sidebar entry suddenly reverts to a slug-cased title, check the frontmatter for a stray unescaped colon.