Every component this blog supports - a single post that exercises the whole MDX toolkit, from callouts and code to terminals, tabs, and tables.

This post is the living style guide for the blog. Every block, primitive, and pattern lives here so the page becomes a single, scrollable proof that the system actually works.
Prose primitives
Paragraphs read the way you'd expect - generous leading, balanced measure,
honey-yellow accents reserved for the moments that earn them. Bold weight
is restrained to real emphasis. Inline code looks like const x = 42,
links like the Zod docs carry the accent. Use
highlight sparingly when an idea genuinely needs to be picked
out of the line. Keyboard shortcuts render via ⌘K.
Strikethrough comes from GFM: old idea → new idea. Footnotes work
too1 - the back-link returns the reader to where they left off.
Lists
Bulleted lists are clean:
- Type-safety from the build, not the runtime
- Performance that maps to perception
- Accessibility designed in, not retro-fitted
Ordered lists track the steps:
- Read the patterns and the anti-patterns
- Compare against current best practice
- Place the piece that fits - nothing more
Task lists work too (GFM):
- Schema-validated frontmatter
- Shiki syntax highlighting
- Cross-post canonical handling
- Multi-author support (not planned)
- Comments (deliberately skipped)
Callouts
Six tones, picked to match how the writing actually feels.
Asides and quotes
The two editorial blocks have distinct jobs. <Aside> is the author's
margin note. <Quote> is somebody else speaking.
We can build big things out of simple parts. Or we can build small things out of complicated parts. The first approach scales.
Code blocks
The fenced block is the workhorse. Shiki renders every fence at build time in the brand theme, with copy-to-clipboard built in. No language is wrong - unknown ones fall back to TypeScript.
import { z } from "zod";
export const blogPostFrontmatter = z.object({
title: z.string().min(3).max(120),
slug: z.string().regex(/^[a-z0-9-]+$/, "kebab-case"),
publishedAt: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
tags: z.array(z.string()).min(1).max(6),
externalCanonical: z.string().url().optional(),
});
export type BlogPostFrontmatter = z.infer<typeof blogPostFrontmatter>;export function Hello({ name }: { name: string }) {
return <p className="text-accent">Hello, {name}</p>;
}bun add shiki remark-gfm
bun run buildSELECT slug, title, published_at
FROM posts
WHERE published_at <= CURRENT_DATE
AND draft = false
ORDER BY published_at DESC
LIMIT 10;Statistics
Three quiet hairline-divided numbers carry weight when surrounded by space.
1.2s
LCP, p75
Real-user, last 30d
42ms
INP, p75
Interaction-to-next-paint
0.02
CLS, p75
Cumulative layout shift
Terminal sessions
Compose with <Line> children - prompt="$" marks a command, dim mutes
echoed output.
$bun add shiki remark-gfmSaved lockfileinstalled shiki@4.1.0installed remark-gfm@4.0.1$bun run buildNext.js 16.2.6 (Turbopack)Compiled successfully in 3.8s27 routes prerendered.File trees
Nest <Folder> and <File> to any depth.
Tabs
Pipe-delimited labels match panel children in order.
bun add zodpnpm add zodnpm install zodComparison blocks
Side-by-side before/after - naive vs optimised, untyped vs typed. The "after" column gets a subtle accent so the win is visually obvious.
Before - drift waiting
After - schema is the contract
Spec sheet
A labeled key-value list, composed of <Row> children.
Build & deploy
- Framework
- Next.js 16.2 + React 19.2
- Runtime
- Node 20 (Vercel)
- Package mgr
- Bun 1.3
- Styling
- Tailwind v4 (CSS-first config)
- Highlighter
- Shiki - build-time, zero runtime JS
- Validation
- Zod 4 (frontmatter + runtime)
Tables
Standard GFM markdown tables get the brand styling for free:
| Block | Purpose | Status |
|---|---|---|
<Lead> | Editorial stand-first | ✓ |
<Callout> | 6 tones: note / tip / info / warn / etc. | ✓ |
<Aside> | Author margin note | ✓ |
<Quote> | Attributed pull-quote | ✓ |
<Steps> <Step> | Numbered procedural sequence | ✓ |
<Terminal> <Line> | CLI session | ✓ |
<FileTree> <Folder> <File> | Directory tree | ✓ |
<Tabs> | Compare-in-place tabbed content | ✓ |
<Spec> <Row> | Key-value labeled list | ✓ |
<Compare> | Before/after two-column | ✓ |
<Stat> | Big number + label | ✓ |
<BlogImage> | Captioned next/image wrapper | ✓ |
<Video> | YouTube / Loom / Vimeo / file | ✓ |
<Bookmark> | External link preview card | ✓ |
<GitHubRepo> | Static GitHub repo card | ✓ |
<Mark> <Kbd> | Inline highlight + keyboard shortcut | ✓ |
| Tables / footnotes / task lists | Standard GFM | ✓ |
Steps
For procedural content where order is the structure. Numerals auto-increment.
Install the package
Run
bun add shikionce. The lockfile pins the version so every build gets the same highlighter.Create a highlighter singleton
Wrap
createHighlighterinReact.cache()so the same instance is reused across server renders.Render via MDX pre override
The MDX components map gets a custom
prethat pipes fenced code through the highlighter and into your themed<CodeBlock>shell.
Link previews
Two flavours, depending on what the reader needs to know about the link.
zod.dev
Zod - the docs
The reference for the schema-as-validator-as-type pattern.
The site you are reading right now - Next.js 16, Bun, Tailwind v4, GSAP, MDX. Designed and engineered by hand.
Media
Images come with captions and reserved aspect for zero CLS.

Video embeds normalise provider URLs and lazy-load the iframe.
Blockquotes
Standard markdown blockquotes still work - used for short, in-line passages
where <Quote> would be too heavy:
A schema is the contract, not a comment. Write the contract once; let the compiler enforce it everywhere.
Multiple paragraphs in a blockquote stay grouped:
First, build the abstraction.
Then, see if it earns its keep against three concrete callsites. If it doesn't, delete it.
Horizontal rule
Three dashes become a hairline divider:
Footnotes
Drop a [^id] next to the claim that needs a citation. The numbered footer
section is auto-built by remark-gfm2.
Closing
Every block above is a real component, not a mockup. If a future post needs something this list doesn't cover, the answer is to add one more entry here
- and the new block joins the system for good.
Footnotes
-
This is the first footnote - a simple paragraph reference. ↩
-
Footnotes can include formatting,
inline code, and even links - for instance the Zod docs. Multi-paragraph footnotes also work, though they're rarely worth the indentation. ↩