# Page reference — frontmatter and mdcms tags

All keys you can use inside a markdown page in `pages/` or `posts/`.

A page has two parts:

```markdown
---
# Frontmatter (YAML, optional except for title)
title: My Page
---

Markdown body goes here.

```mdcms
toc
```

Regular markdown, plus mdcms code blocks for callouts, table of contents, post lists.
```

---

## Frontmatter

The YAML block delimited by `---` at the top of the file. Read by `mdcms build` to populate `nav.yml` and `search.json`, and by `index.html` at runtime to set the page title, dates, and meta tags.

```yaml
---
title: Page Title              # REQUIRED. Browser tab title, nav label, h1 fallback.
                               # Without this, the page is skipped from nav.yml.

sort: 100                      # Position in the nav within its section. Lower = higher.
                               # Default: 100. Tiebreaker is filename.

section-id: guides             # Assigns this page to a section. Must match (or auto-create)
                               # a code: in nav.yml. Omit to leave unsectioned.

draft: true                    # Excludes the page from nav.yml AND search.json.
                               # Default: false.

author: Jane Doe               # Shown in the meta line under the page title (pages with author or created).

created: 2026-05-18 14:30      # Publish date. Format: YYYY-MM-DD or YYYY-MM-DD HH:MM.
                               # Required for posts to appear in posts-* tag listings.
                               # Used as the sort key in chronological/reverse-chronological lists.

modified: 2026-05-19 09:15     # Last-modified date. Shown next to created date if set.

description: Short summary     # Used for the <meta name="description"> tag.
                               # Falls back to config.yml sitedescription if omitted.

keywords: foo, bar, baz        # Comma-separated. Indexed in search.json.

language: en                   # BCP 47 code. Sets the <html lang=""> attribute when this page is loaded.
                               # Doesn't filter pages — that's what categories are for.
---
```

**Category variants** are not a frontmatter field — they are encoded in the filename. `about.nb.md` is the Norwegian variant of `about.md`, provided `nb` is declared in `config.yml` under `categories:`.

---

## mdcms code blocks

Fenced blocks with the `mdcms` language tag are intercepted by the renderer and replaced with dynamic HTML. The tag name goes either on the fence line or on the first line of the block:

````markdown
```mdcms callout-info
title: Heads up
This is the body.
```
````

…is equivalent to:

````markdown
```mdcms
callout-info
title: Heads up
This is the body.
```
````

Inside the block, lines matching `key: value` are parsed as options. The first non-matching line begins the body.

---

### Callout tags — `callout-info`, `callout-warning`, `callout-success`, `callout-error`

A bordered, tinted box for notes, warnings, success messages, errors. Colour and icon come from `theme.yml` (`callouts:` block); fall back to built-in defaults.

````markdown
```mdcms callout-info
title: Note                    # Optional. Bold title row with icon. Omit for a body-only callout.
icon: lightbulb                # Optional. Override the default icon. Use an SVG name from assets/icons/.
message: aitranslation         # Optional. Resolves title + body from config.yml callouts: block.
                               # Takes precedence over inline title/body.

Body text supports **full markdown** — bold, *italics*, `code`,
[links](https://example.com), lists, etc.

- item one
- item two
```
````

**Behaviour:**
- Type comes from the tag name suffix (`info`/`warning`/`success`/`error`).
- `message: <key>` looks up the named block in `config.yml`. When matched, the message's title and body override any inline values. The message's `type:` also overrides the tag type.
- For multi-language messages, the renderer picks the entry for the active category, then the default category, then the first key.

---

### Table of contents — `toc`

Renders a section-grouped, sorted list of all visible non-draft pages in the active category. The page containing the tag is excluded.

````markdown
```mdcms
toc
```
````

No options. Output is grouped by nav section in section sort order; pages within each section follow their own `sort:`.

---

### Post listings — `posts-created-*`

Generate a chronologically sorted list of posts (files in `posts/`). Requires each post to have a `created:` value in frontmatter.

**Reliable variants** (others are broken — do not use):

```
posts-created-chronological-byyearmonth
posts-created-reversechronological
```

The grammar:

```
posts-created-<order>[-<modifier>]
  order:    chronological | reversechronological
  modifier: byyear | byyearmonth | lastyear | lastmonth   (optional)
```

- `byyear` / `byyearmonth` — group output by year, or by year-and-month.
- `lastyear` / `lastmonth` — filter to posts from the last 365/30 days.
- No modifier — flat list of all posts.

````markdown
```mdcms
posts-created-reversechronological
limit: 10                      # Max number of posts shown. Default: all.
                               # When paginate: yes, this is the page size (batch size).

paginate: yes                  # Pagination mode:
                               # yes   — show a "load more" button after batchSize posts.
                               # none  — show only the first <limit> posts, no pagination.
                               # no    — show all posts at once (default).
```
````

**Category filtering:** When `categories-use: yes`, the listing automatically filters to the active category.

---

## Markdown features

Standard CommonMark plus GFM (GitHub-flavoured) extensions:

- Tables
- Strikethrough (`~~text~~`)
- Task lists (`- [ ]` / `- [x]`)
- Fenced code blocks with syntax language hints (`` ```python ``)
- Autolinks

**Raw HTML** passes through to the DOM. You can embed HTML directly:

```markdown
<meta http-equiv="refresh" content="0; url=docs/">
```

**Scripts injected via `<script>` tags in markdown do not execute** — the renderer uses `innerHTML`, which browsers block from running script tags. Use `<meta http-equiv="refresh">` for redirects.

**Links to other pages** can use either:

```markdown
[Docs](pages/docs.md)          # Internal link — rewritten to a client-side route.
[External](https://example.com)  # External — opens in new tab automatically.
```

---

## Full example

````markdown
---
title: Quick Start
sort: 100
section-id: getting-started
author: Jane Doe
created: 2026-05-18 14:30
description: How to install and run MD-CMS in five minutes.
keywords: install, setup, quickstart
---

# Quick start

Welcome. This page walks you through installing MD-CMS.

```mdcms callout-info
title: Before you begin
Make sure you have Python 3.9 or newer.
```

## Table of contents

```mdcms
toc
```

## Recent posts

```mdcms
posts-created-reversechronological
limit: 5
paginate: yes
```

## Translation notice

```mdcms callout-warning
message: aitranslation
```
````
