welcome to the rabbit holes

How articles work on this site — and a tour of the MDX palette you can use.

This site publishes longform via MDX. Each article is a single .mdx file under content/articles/<category>/<slug>.mdx. Push to main, Cloudflare Pages rebuilds, the post is live in roughly two minutes. There is no admin UI; the editor is your text editor and the publisher is git.

The rest of this post is a working reference for what you can do inside an article.

Frontmatter

Every article begins with a YAML block:

---
title: "welcome to the rabbit holes"
description: "One-line lede shown under the title and in the index card."
date: 2026-05-11          # required, ISO; drives sort + RSS pubDate
category: "site"          # must equal the parent directory name
tags: ["meta", "writing"] # optional
cover: /articles/site/welcome/cover.png   # optional; resolved from public/
draft: false              # default false; drafts hidden from index + RSS in prod
---

The build fails loudly if anything is missing or wrong: missing title, a category that disagrees with the directory, a cover pointing at a file that doesn't exist under public/.

Headings get anchors

rehype-slug and rehype-autolink-headings wrap every H2 and H3 in an anchor link. The article shell renders a table of contents at the top when there are at least two H2s.

So do sub-headings

Used sparingly. Prose reads better with shallow hierarchy.

The component palette

Five custom MDX components ship out of the box.

Callout

Toggle

Hide a long demo behind a click

<details>/<summary> under the hood, so it works without JavaScript. Useful for transcripts, raw JSON, anything that earns its keep but shouldn't crowd the reading flow.

  • one
  • two
  • three

Figure

Captioned image. Render with next/image so the layout reserves the slot before the bytes arrive.

<Figure
  src="/articles/site/welcome/diagram.png"
  alt="System sketch"
  caption="The system, sketched."
  width={1200}
  height={800}
/>

Audio

Embed an <audio> tag with caption and an optional collapsible transcript.

<Audio
  src="/articles/site/welcome/clip.mp3"
  caption="Call demo (0:42)"
  transcript="Hello. Yes I'm calling about the form…"
/>

Highlight

Inline yellow, orange, or red emphasis on a few words. Use for the specific phrases a reader should not miss.

Code

Fenced code blocks tokenize with Shiki at build time, theme github-light. Zero JavaScript ships to the client for syntax highlighting.

export const greet = (name: string) => `hello, ${name}`;

Tables

GitHub-flavored Markdown tables work directly:

concerntool
pipelinevelite
codeshiki
RSSfeed
imagesnext/image (unoptimized, static export)

Assets

Article-specific binaries live alongside the MDX in public/:

public/articles/site/welcome/
  cover.png
  diagram.png
  clip.mp3

Reference them with absolute paths starting /articles/.... Static export copies public/ verbatim so the URLs work without any build machinery.

Publishing

# write
$EDITOR content/articles/<cat>/<slug>.mdx

# preview locally
bun dev
# → http://localhost:3000/articles/<cat>/<slug>

# verify the build is green before pushing
bun run build

# commit and push
git add content/articles/<cat>/<slug>.mdx public/articles/<cat>/<slug>
git commit -m "post(<cat>): <title>"
git push origin main

Drafts: set draft: true to keep an in-progress post on main without showing it on /articles or in the RSS feed. The article URL still resolves, so you can share a direct link for review.