New

Fresh coat of paint. The blog has a new theme: shader backdrops, search, and more. Take the tour

A tour of the theme

Syntax highlighting, Mermaid diagrams, Swiper galleries, and everything else this blog can render.

This post exercises every part of the theme, so it doubles as a visual test page. Edit it, or delete it once you’ve seen how things look.

Backdrops

The background is a WebGL shader with four scenes: aurora, topo, nebula and halftone. Set a site default with theme_options.backdrop in _config.yml, or pick one per post with backdrop: in the front matter (this post uses nebula). Visitors can choose their own, or turn it off, from the footer.

All scenes react to scrolling and the pointer. Click or tap anywhere to send a ripple through the field. With reduced motion turned on, the shader draws a single still frame.

Callouts

Use GitHub-style alert syntax in a blockquote. They’re rendered at build time, so they work without JavaScript.

Badges

Posts get badges automatically: New for recent posts, Featured, and Updated when the front matter has an updated: date. Add your own with a badges: list.

You can also use them inline in Markdown: stable beta deprecated v2.1 Pro

<span class="badge badge--success">stable</span>

Banners and notifications

  • Post banners sit above the post body. Set banner: in the front matter, like the one at the top of this post.
  • Older posts get a notice automatically once they pass theme_options.outdated_after_days. Set outdated: false on a post to skip it.
  • Announcements live in _data/announcements.yml. Each one shows either as a bar above the header or as a toast. Visitors can dismiss them, and they can have start and end dates.
  • Toasts are also available from JavaScript: toast({ title, message, variant, action }). The button below tries it.

Code

Fenced code blocks get syntax highlighting from Rouge, plus a language label and a copy button.

type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };

export async function fetchJson<T>(url: string): Promise<Result<T>> {
  try {
    const res = await fetch(url, { headers: { Accept: "application/json" } });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    return { ok: true, value: (await res.json()) as T };
  } catch (error) {
    return { ok: false, error: error as Error };
  }
}
use std::collections::HashMap;

fn word_counts(text: &str) -> HashMap<&str, usize> {
    let mut counts = HashMap::new();
    for word in text.split_whitespace() {
        *counts.entry(word).or_insert(0) += 1;
    }
    counts
}
func worker(ctx context.Context, jobs <-chan Job, results chan<- Result) {
	for {
		select {
		case <-ctx.Done():
			return
		case job := <-jobs:
			results <- job.Run()
		}
	}
}
# Deploy a preview build
git switch -c my-feature
git commit -am "Try something" && git push -u origin my-feature
- const timeout = 1000;
+ const timeout = 5_000; // allow slow cold starts

Inline code like bundle exec jekyll serve works too.

Diagrams

Write Mermaid in a mermaid fenced block. Add accTitle and accDescr so screen readers get a description of the diagram.

flowchart LR
  accTitle: Deployment pipeline
  accDescr: A git push triggers a Vercel build. Main deploys to production; other branches get a preview URL.
  push([git push]) --> build[Vercel build]
  build --> branch{Branch?}
  branch -- main --> prod[Production]
  branch -- other --> preview[Preview URL]
sequenceDiagram
  accTitle: Request lifecycle
  accDescr: A browser requests a page from the Vercel edge, which serves the static file from its cache.
  participant B as Browser
  participant E as Vercel Edge
  participant S as Static files
  B->>E: GET /2026/10/16/theme-tour/
  E->>S: Cache miss
  S-->>E: index.html
  E-->>B: 200 OK

Swiper powers galleries. Swipe, drag, or use the arrow keys when the gallery has focus.

Everything else

Simplicity is prerequisite for reliability. — Edsger W. Dijkstra

Layer Tool Notes
Content Markdown Lives in _posts/
Build Jekyll 4 Runs on Vercel
Effects WebGL, GSAP Turned off for reduced motion
Carousels Swiper Loaded only where it’s used
  1. Ordered lists
  2. With bold, italic, and links
  3. And a footnote.1
  • Unordered lists
  • Nest nicely
    • Like this

That’s the tour.

  1. Footnotes collect at the bottom of the post. ↩︎

    ↑↓ to move · Enter to open