Hello, visualizations

A test post for the new blog: interactive charts, diagrams, math, and highlighted code, all from a single MDX file.

MetaData vizMachine learning

This is a test post for the blog. Posts live in content/blog/ as MDX, so they're plain Markdown plus any React component I register. Everything below renders from that one file.

Math

Inline math works like f(x)=14x4−x2+0.35xf(x) = \tfrac{1}{4}x^4 - x^2 + 0.35x, and display math gets its own block:

Attention(Q,K,V)=softmax⁡ ⁣(QK⊤dk)V\text{Attention}(Q, K, V) = \operatorname{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right)V

The gradient descent update used in the playground further down is

xt+1=xt−η ∇f(xt)x_{t+1} = x_t - \eta \, \nabla f(x_t)

Code

Code blocks are highlighted at build time with Shiki, follow the light/dark toggle, and support titles and highlighted lines:

lib/descent.ts
export function descend(grad: (x: number) => number, x0: number, lr: number, steps = 50) {
  const path = [x0]
  for (let i = 0; i < steps; i++) {
    const x = path[path.length - 1]
    path.push(x - lr * grad(x))
  }
  return path
}

Charts

A line chart with hover crosshair, direct end labels, a legend, and a table view (try the Show table button):

p95 latency by context length

Synthetic benchmark, milliseconds, lower is better

  • Baseline
  • Prompt cache
  • Int8 + cache
Hover for exact values.

A single-series area chart, which needs no legend because the title names the series:

Weekly build minutes

Synthetic CI usage over 12 weeks

A sorted bar chart with values at the bar tips and hover details:

Where an agent run spends its time

Synthetic breakdown of a 40s run, seconds

Diagrams

Mermaid diagrams render client-side and re-theme with the toggle:

Rendering diagram…
A minimal retrieval-augmented generation loop.
Rendering diagram…

Interactive components

Any React component can be embedded. Here's a gradient descent playground. With a small learning rate it rolls into whichever valley it starts in. Push the rate up and it starts overshooting, and somewhere past 0.8 it diverges entirely:

Gradient descent playground

Pick a learning rate and starting point, then step through the updates x ← x − η·f′(x).

global minlocal min
Step 0 · x = 2.100 · loss = 2.787

Images

Images are plain Markdown. Put the file in public/blog/<post-slug>/ and link it from the root. The optional quoted title becomes the caption:

![The homepage on desktop](/blog/hello-visualizations/home-desktop.jpg "The homepage in dark mode, at 1440px")
The portfolio homepage on desktop in dark mode, with the silk background behind the hero and experience cards
The homepage in dark mode, at 1440px

They're resized for each screen, served as AVIF or WebP, and lazy-loaded. The size is read from the file at build time, so the page doesn't jump around as images load. A typo in the path fails the build rather than shipping a broken image.

Put images on consecutive lines, with no blank line between them, and they sit side by side:

The homepage on a phone in light mode
Light
The homepage on a phone in dark mode
Dark

For a caption with formatting, use the component:

The portfolio homepage on desktop in dark mode
Same image via <Figure />, with a rich caption.

Everything else

Standard Markdown and GFM still work: bold, italic, strikethrough, links, and tables:

FeatureHow
Math$...$ and $$...$$ (KaTeX)
CodeFenced blocks (Shiki)
Charts<LineChart />, <BarChart />
Diagrams<Mermaid chart={...} />
Images![alt](/blog/slug/file.jpg "Caption")
Custom widgetsAny registered component

To write a new post, drop an .mdx file in content/blog/ with title, date, summary, and tags frontmatter. Add draft: true to hide it in production.