Disclosure: The contents of this post have been partially or entirely created using AI. Read more about how I use or don’t use AI.

Test Page / Syntax Guide

This page documents the Markdown syntax and special styles available when writing posts and pages for this blog. It doubles as a live test of the renderer — everything shown below is actually rendered by Magnetizer, not typed out as a picture.

Since a post’s title already occupies the top-level heading, headings inside the body should start at ### — anything more prominent (# or ##) triggers a build warning.

Text formatting

Source:

**bold**, *italic*, `inline code`, and ==highlighted== text.

Renders as:

bold, italic, inline code, and highlighted text.

Headings

Source:

### A level-3 heading
#### A level-4 heading

Renders as:

A level-3 heading

A level-4 heading

Links

Regular links, and bare URLs/email addresses wrapped in <> for automatic linking:

[First post](1.html), [External link](https://bbc.co.uk), or just <https://mxgns.uk> and <[email protected]>.

Renders as:

First post, External link, or just https://mxgns.uk and hello@mxgns.uk.

Any link that isn’t relative and doesn’t point at mxgns.uk is treated as external — it automatically opens in a new tab and gets a small icon, no extra markup needed.

Lists

An unordered list:

- Optimisation & curation
- Boating
- Reading

Renders as:

  • Optimisation & curation
  • Boating
  • Reading

An ordered list:

1. First
2. Second
3. Third

Renders as:

  1. First
  2. Second
  3. Third

Tables

Source:

| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Item 1   | Item 2   | Item 3   |
| Item 4   | Item 5   | Item 6   |

Renders as:

Column 1 Column 2 Column 3
Item 1 Item 2 Item 3
Item 4 Item 5 Item 6

Blockquotes

Source:

> A quoted thought, indented and set apart from the rest of the text.

Renders as:

A quoted thought, indented and set apart from the rest of the text.

Code

Inline code uses single backticks: `like this`.

For a proper code block, indent every line with four spaces (or one tab) rather than fencing it with ```. Triple backticks are not treated as a fenced code block by this renderer — they collapse into an inline <code> span instead, which loses the block formatting and line breaks. Indentation is the only reliable way to get a real block.

Source:

    def greeting(name):
        return f"Hello, {name}!"

Renders as:

def greeting(name):
    return f"Hello, {name}!"

Horizontal rule

Source:

---

Renders as:


Smart typography

Straight quotes and apostrophes are automatically converted to their curly (“smart”) equivalents. -- becomes an en dash, --- becomes an em dash, and ... becomes an ellipsis.

Source:

She said "it's fine" -- really... it's --- true.

Renders as:

She said “it’s fine” – really… it’s — true.

Quotes, dashes and ellipses inside inline code or an indented code block are left untouched, e.g. "like this" -- and this....

Images

Photos for a post or page aren’t inserted with Markdown’s ![alt](src) syntax. Instead they’re placed alongside the .md file in content/ as {post-id}-image-{NN}.{ext} (e.g. 12-image-01.jpg, 12-image-02.png), and alt text is supplied in the frontmatter, in file order:

---
date: 2026-05-21
title: A day at the coast
images:
  - Beach hut in the rain
  - A bowl of bananas
---

Any image not referenced inline (see below) is automatically shown as a strip of <figure> elements above the post body.

Inline images

To place a specific image inline within the body text, use {{ image N }} on its own line, with blank lines before and after — N matches the two-digit number in the filename:

Some text before the image.

{{ image N }}

Some text after.

This is replaced with a <figure><img></figure> using that image’s resized file and its frontmatter alt text. Referencing an image number the post doesn’t have, or using the token inline with other text, is a build error. (Note: this reference page has no images of its own, so the example above uses a placeholder letter rather than a real number — a real post would give the actual position of the image in its filename, e.g. the third image.)

Read more marker

Placing the marker below on its own line splits a post’s body. On index/category pages only the content above the marker is shown, followed by a “Read more” link (which folds in a photo count if any images are hidden past the marker); on the individual post page the marker has no effect and the full body is shown.

An introductory paragraph, shown everywhere.

<!-- MORE -->

The rest of the story, only shown on the post's own page.

(Shown here in capitals only because this reference page is itself parsed by Magnetizer, and the real, lowercase marker would split this very page. In your own posts, write it exactly as above, but lowercase.)

Frontmatter fields

Beyond date, title and images, a few other fields turn on extra styling:

---
date: 2026-05-21
category: travel
favourite: true
ai_assisted: true
---
  • category — must match a slug configured in config.yaml; adds a category link to the post’s footer and includes the post on that category’s page.
  • favourite: true — adds a small star after the post’s entry in the archive listing.
  • ai_assisted: true — adds a disclosure banner (see below) to the top of the post’s content, everywhere it’s shown.

AI-assisted disclosure

Setting ai_assisted: true in a post’s frontmatter inserts a banner at the very top of the post body — on the individual post page, and in the excerpt or full body shown on index and category pages:

---
date: 2026-07-17
ai_assisted: true
---

The banner’s wording (and any link inside it) comes from ai_disclosure_html in config.yaml, not from anything written in the post itself — Magnetizer has no opinion on the phrasing, only on where the banner appears:

ai_disclosure_html: 'The contents of this post have been entirely or partially created using AI. It’s a rare exception. <a href="48.html">Read more about how I do or don’t use AI on this blog.</a>'

This page itself has ai_assisted: true set, so an example of the banner can be seen at the very top of the page.

The banner uses the container-brown colour variant together with an ai-disclosure class that lays the icon and text out side by side, with tighter padding than a regular container (matching ::: info). The black AI icon (per the standard AI-content disclosure symbol) is a CSS background image on .ai-disclosure, base64-encoded in style.css — same as every other icon on the site, not a separate file. If ai_disclosure_html isn’t set in config.yaml, a generic fallback sentence is used instead.

Dynamic values

Some values are worth computing at build time rather than typing by hand — a post count or word count would go stale the moment a new post is published. Write the value’s name inside double braces:

Source:

{{ post_count }}

Renders as:

98

Five values are available: post_count, word_count, image_count, today and ai_post_list. Whitespace inside the braces doesn’t matter — {{post_count}}, {{ post_count }} and {{ post_count }} all mean the same thing, and the syntax is inert inside inline code or an indented code block (which is how it’s shown safely above).

Source:

This site has {{ post_count }} posts, totalling {{ word_count }} words and {{ image_count }} images. Today is {{ today }}.

Renders as:

This site has 98 posts, totalling 11,211 words and 90 images. Today is 20/9/26.

{{ ai_post_list }} is different — it renders a whole <ul> of posts (and special pages — this page is itself ai_assisted: true, so it’s in the list below) with ai_assisted: true set, newest first, so it needs to sit alone on its own line with blank lines before and after, rather than inline with other text:

Source:

{{ ai_post_list }}

Renders as:

An unrecognised name is left exactly as written and logs a build warning — handy for catching typos. Numbers of 1,000 or more get a comma thousands-separator (e.g. 12,345). A page using any of these values is automatically rebuilt whenever the underlying numbers change elsewhere on the site (e.g. a new post shifts post_count), not just when the page’s own file changes.

Container blocks

Wrap a section of Markdown in a ::: fence to render it inside a <div class="container">. Content between the fences is itself parsed as Markdown, and an opening ::: without a matching closing ::: is left as plain text. Containers don’t nest.

Source:

::: 
A plain container, useful for setting a block of content apart from the rest of the page.
:::

Renders as:

A plain container, useful for setting a block of content apart from the rest of the page.

Colour variants

Add one of container-pink, container-green, container-yellow, container-blue, container-beige or container-brown after the fence for a tinted version:

::: container-pink
A pink-tinted container.
:::

Renders as:

A pink-tinted container.

The other colours render as:

A green-tinted container.

A yellow-tinted container.

A blue-tinted container.

A beige-tinted container.

A brown-tinted container.

Info box

The info class renders a highlighted callout with an “i” icon, for asides or notes:

::: info
Worth calling out separately from the main text.
:::

Renders as:

Worth calling out separately from the main text.

Circle list

Adding li-circles alongside a plain or colour-variant class turns a bullet list inside the container into a row of circles — handy for a short set of tags or stats. It lays out 1, 2, 4 or 5 items specially (a single item fills the row, 2 or 4 split evenly, 5 splits 3-and-2); any other count wraps as a plain grid of thirds.

::: container-pink li-circles
- Item 1
- Item 2
- Item 3
:::

Renders as:

  • Item 1
  • Item 2
  • Item 3

Download links

There’s no Markdown shorthand for a download link with the little download icon — write the anchor tag directly with a download-link class, since raw HTML passes through untouched:

Get the full-size version <a href="12-image-01-resized.jpg" class="download-link">here</a>.

Renders as:

Get the full-size version here.

2 comments

Magnus

This is the first comment for this post. Comments can include styles like italics, bold etc, as well as links.

They can also include multiple paragraphs!

Magnus

This is the second comment for this post.