All posts
🧪

Test-driving Markdoc with custom callouts

Adding a second authoring format alongside MDX: typed Markdoc tags for callouts, highlights, and embeds.

I added Markdoc as a second content format on this blog. Markdown gets you 90% of the way; Markdoc gets you the last 10% without inviting JSX into your prose.

Why Markdoc next to MDX

MDX lets me drop React components into a markdown file, which is great when I genuinely need a component. But for the kinds of things I reach for most — callouts, highlights, embeds — MDX gives me too much rope. Markdoc fixes the vocabulary up-front in markdoc.config.mjs:

What's wired

Three tags so far:

  1. {% callout %} — tinted box with an icon, four types (note, tip, warn, inspiration).
  2. {% hl %}highlight{% /hl %} — inline marker effect using the neo-brutalist palette .
  3. {% youtube %} — a privacy-preserving youtube-nocookie embed without dragging in YouTube's player JS until the iframe loads.

Code blocks still work

// src/components/markdoc/Callout.astro
const tones = {
  note: { bg: 'bg-neo-sky', icon: Info },
  warn: { bg: 'bg-neo-accent', icon: AlertTriangle },
  tip: { bg: 'bg-neo-mint', icon: Lightbulb },
  inspiration: { bg: 'bg-neo-muted', icon: Sparkles },
};

Shiki still highlights them because the fence node is rendered through a thin Astro wrapper that delegates to the built-in <Code> component.

More posts Say hi