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:
| concern | tool |
|---|---|
| pipeline | velite |
| code | shiki |
| RSS | feed |
| images | next/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.