MDX Content

Write content using MDX (Markdown + JSX components).

Write content using MDX (Markdown + JSX components).

Structure

content/
└── notes/      # Blog posts

Frontmatter

content/notes/example.mdx
---
title: "Post Title"
date: "2024-12-21"
summary: "Brief description"
image: "https://unsplash.com/photos/..."
pinned: false
---

Fields:

  • title - Post title (required)
  • date - Publication date (required)
  • summary - Short description (required)
  • image / image_url - Hero image (optional, Unsplash URL or local path)
  • pinned - Pin to top of list (optional)

Parsing Pipeline

Content is parsed in src/lib/content/mdx.ts using:

  1. gray-matter - Frontmatter extraction with YAML engine
  2. reading-time - Estimated read time
  3. Custom slug generation from filename

Custom Components

Available in MDX:

  • Table - Enhanced tables with column definitions
  • YouTubeEmbed - Responsive YouTube embeds

Creating Content

  1. Create .mdx file in content/notes/
  2. Add frontmatter with required fields
  3. Write content with Markdown
  4. Run dev server to preview

Heading hierarchy and formatting

The page template renders the title as H1. Start article sections at ## (H2), use ### (H3) for subsections, and continue to H4–H6 only when the content is nested further. Do not repeat the page title inside the Markdown or skip heading levels. Client case studies in content/clients/*.md follow the same hierarchy.

The shared table of contents reads H2–H6 from the article body and preserves their nesting on desktop and mobile. Keep heading labels descriptive; heading links, reading styles, and the contents list derive from the rendered structure.

Write emphasis as **Label**, with no spaces inside the markers. Separate lists and fenced code blocks from surrounding paragraphs with blank lines. Specify a language immediately after the opening code fence; keep filenames or explanatory labels outside the fence metadata.

Run bun run lint:markdown to check notes, case studies, and documentation. Preview the rendered article as well: linting does not verify the meaning of a heading or the resulting contents hierarchy.

Reading controls

PageActions supplies Markdown copy/export, assistant links, sharing, and adjacent page links on both article templates. use-page-actions-menu owns menu placement, focus, and keyboard navigation. The raw content comes from the existing /api/markdown/... endpoints. Preserve clipboard writes within the user's click handler for Safari compatibility.

Publishing checklist

Choose a descriptive filename because it becomes the public note slug. Keep the publication date quoted in YAML, write a summary that explains the problem or outcome, and use an optional image only when it adds useful context. The parser accepts image_url or image; pinned notes use the pinned boolean.

Before publishing, preview the note from the list and check the article title, metadata, hero image, code blocks, contents hierarchy, and related-reading links. Use the page-action menu to view the Markdown export as well. An assistant reading the export should receive the same explanation and meaningful links as a visitor.