Writing Content
Frontmatter, sidecar metadata, GFM, and code blocks.
Authoring model
Use plain markdown (.md) for most pages, and switch to .svx only when a page needs a live Svelte component inline. Everything else about the two file types is identical: frontmatter, sidecars, GFM, code blocks.
Frontmatter
Set page metadata directly in the file with YAML frontmatter; no sidecar file is required:
---
title: Example Page
description: Shown in listings and the meta description tag.
order: 5
tags: [guide]
icon: rocket
---
Your content starts here.Metadata fields
title: Display titledescription: Optional summary for listingsorder: Sorting number for navtags: Optional list for future filteringicon: Name from the curated icon set, shown in the sidebar and next to the page’s<h1>. See Components for the full list of names.
Pages also show a “Last updated on” date, taken from the file’s most recent git commit at build time — not from filesystem timestamps, which reset on every fresh clone. There’s nothing to set: commit the file and the date follows. If your CI does a shallow clone (GitHub Actions and Cloudflare default to one), most files have no reachable history and the date is simply omitted; fetch full history to get it back (fetch-depth: 0 in the GitHub Pages workflow).
Sidecar overrides
A name.meta.json file next to name.md takes priority over frontmatter for any field it sets. That’s useful when you want to tweak nav ordering without touching the prose file, or for content synced in from elsewhere:
{
"order": 1
}Frontmatter still supplies everything the sidecar doesn’t override. _meta.json, a separate folder-level file, sits above both; see Navigation for how that precedence works.
Headings
Use consistent heading levels so TOC generation and anchor links are predictable.
GFM formatting
Tables, task lists, strikethrough, and bare-URL autolinks all work out of the box:
| Feature | Syntax |
|---|---|
| Table | pipe-delimited |
| Task list | - [ ] todo |
| Strikethrough | ~~done~~ |
- Ship GFM support
- Ship more of the roadmap
Code blocks with a filename
Add filename="..." to a fence’s info string to show a filename header above the code, alongside the built-in copy button every code block gets:
```sh filename="deploy.sh"
echo hello
```Diagrams and math
Mermaid diagrams use a ```mermaid fence and render to inline SVG:
```mermaid
graph LR
A[content/*.md] --> B[mdsvex]
B --> C[page]
```Mermaid’s layout engine needs a real browser, so instead of driving a headless Chromium at build time, the diagram renders in the reader’s browser. The mermaid library loads lazily and only on pages that actually contain a diagram; every other page ships none of it, and builds need no browser anywhere — locally, in Docker, or in CI. Diagrams pick the dark or light theme active when the page loads.
LaTeX math uses $inline$ and $$block$$ syntax, rendered via KaTeX to static HTML at build time — no client-side JS ships for it:
Inline: $E = mc^2$.
Block:
$$
t = maxleft(1, leftlceil rac{w}{200} \right\rceil\right)
$$Obsidian syntax
Wikilinks ([[Page]]), image embeds (![[diagram.png]]), > [!tip] callouts, ==highlights==, and %% comments %% all work in .md and .svx files, and publish: false or draft: true in frontmatter keeps a page out of the build. That means content/ can be opened directly as an Obsidian vault; see Obsidian.
Components
.svx files (not .md) can import and use Svelte components inline. See the Components page for the full built-in set (Callout, Tabs, Steps, Cards, Collapse, Bleed, Banner, FileTree, ImageZoom) and how to import them.
Watch out: don’t put inline code containing
<or{in a heading — plain inline code and inline code anywhere else on the page are both fine. See Troubleshooting for why.