Markdown pages

How SharpDocs turns *.md files into routed pages.


Every *.md file under DocsRoot is loaded once at startup and becomes a page.

Slug rules

The slug is the file path relative to the project root, with the extension stripped, any locale suffix stripped, and \ normalized to /:

File Slug
index.md index
overview/how-it-works.md overview/how-it-works
overview/index.md overview
how-to\add-a-page.md (Windows) how-to/add-a-page
index.vi.md (with locale vi) index (vi override)
install.foo.md (no locale foo) install.foo (literal)

The trailing /index collapse lets you use a folder-as-section pattern: overview/index.md becomes /overview instead of /overview/index.

Locale-aware filenames

A trailing dotted segment that matches a declared locale (in sharpdocs.json) marks the file as a per-locale override for that slug. The locale suffix is stripped before slug computation, so install.vi.md and install.md both produce slug get-started/install — the .vi.md form is just an override that wins for that one locale.

If the suffix doesn't match a declared locale, it's treated as part of the filename — install.foo.md (with locales: ["en", "vi"]) is a base file at slug install.foo. See Localization for the full overlay model.

Frontmatter

Pages can start with a YAML frontmatter block:

---
title: My page
description: What this page covers.
---

Body content...

Only string-valued keys are surfaced. Currently SharpDocs reads:

  • title — falls back to the filename if omitted
  • description — optional, used in meta tags

Other keys (including non-string values) are silently ignored. Malformed YAML is ignored, not fatal.

Markdown features

Parsed with Markdig using UseAdvancedExtensions() and UseAutoIdentifiers(). That gives you:

  • GitHub-flavored tables, task lists, fenced code with language tags
  • Automatic heading IDs (for in-page anchors and the on-page TOC)
  • Footnotes, definition lists, abbreviations
  • Smart punctuation and emoji shortcodes

Headings at level 2 and 3 are indexed for the search scorer and the on-page "On this page" navigation.

htmx navigation

When the browser issues a nav request with the HX-Request header, DocsController returns the _Article partial instead of the full layout — the sidebar and shell stay put while the article body swaps. This is transparent; you don't need to do anything in your markdown.