Alan

TOC & Typography Test Page

4 min read

A kitchen-sink post that exercises the table of contents, reading progress bar, scroll-spy, and prose styling. Delete me once everything looks right.

This post exists to verify the reading experience end-to-end: the sticky table of contents on the right, the scroll-spy highlight following your position, the progress bar at the very top of the viewport, and the prose typography for headings, lists, quotes, code, and links. If anything here looks off, the component that owns it is the first suspect.

Introduction

Every h2 on this page should appear as a top-level entry in the TOC. As you scroll into each section, the corresponding TOC link should become bold and brighter because the IntersectionObserver in TableOfContents.astro adds the is-active class when the heading enters the top third of the viewport.

The thin accent-colored bar pinned to the top of the window is the ReadingProgress component. It listens for scroll events and updates its width via requestAnimationFrame, so it should move smoothly as you scroll without jittering.

What to look for

  • The TOC is sticky on desktop (lg: breakpoint and above).
  • On mobile, it isn’t rendered — there’s no collapsed <details> yet, that’s a known deferred item.
  • Links inside the prose body should be underlined with a wavy accent color, not black.
  • The page title h1 should NOT appear inside the TOC — the filter is depth >= 2 && depth <= 4.

Even deeper

h4 headings should also show up in the TOC, indented further than h3. This section exists to prove that.

Paragraphs and inline formatting

Here is a paragraph with bold text, italic text, both at once, inline code, and a link to Astro docs. The link should use the accent-color wavy underline from the prose overrides in global.css.

Lists

An unordered list:

  • First item
  • Second item with bold inside it
  • Third item with a link
  • Fourth item with inline code

An ordered list:

  1. One
  2. Two
  3. Three

Nested lists

  • Parent
    • Child A
    • Child B
      • Grandchild
  • Sibling

Blockquote

This is a blockquote. It should render with a left border, muted foreground color, and italic text thanks to @tailwindcss/typography. Multiple lines in the same block quote collapse into one paragraph.

A second, single-line quote for good measure.

Code blocks

Inline code like const x = 42; should use Geist Mono and pick up the muted background from the prose overrides.

A JavaScript fence:

// This exercises rehype-pretty-code with the vitesse-light / vitesse-dark
// dual-theme setup. Switch the site theme with the header button and
// this block should recolor without a page reload.
function fibonacci(n) {
  if (n < 2) return n;
  let a = 0;
  let b = 1;
  for (let i = 2; i <= n; i++) {
    const next = a + b;
    a = b;
    b = next;
  }
  return b;
}

console.log(fibonacci(10)); // 55

A TypeScript fence:

type Post = {
  title: string;
  pubDate: Date;
  tags: string[];
};

const example: Post = {
  title: "Hello",
  pubDate: new Date("2026-04-13"),
  tags: ["meta", "test"],
};

A shell fence:

npm run dev
npm run build
npx astro check

Another h3 under Code blocks

Confirming that h3 headings under the same parent h2 still appear in the TOC as siblings, indented correctly.

Horizontal rule and images

Below should be a horizontal rule:


And that’s it — there’s no image in this post because content collection images need to be in src/content/posts/ alongside the MDX and the test post doesn’t ship one.

A long section to force scrolling

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac neque nec arcu aliquet suscipit. Quisque tempor, nisi sed fermentum elementum, nibh arcu aliquet justo, vel feugiat nulla magna a lorem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin eget tortor risus.

Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Vivamus suscipit tortor eget felis porttitor volutpat. Nulla quis lorem ut libero malesuada feugiat. Cras ultricies ligula sed magna dictum porta.

Sed porttitor lectus nibh. Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Proin eget tortor risus. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui.

Reading time sanity check

The header of this post should say something like “4 min read” or similar — the remark-reading-time plugin counts words and clamps the result to at least 1. If the number looks absurdly low or high, check src/lib/remark-reading-time.mjs.

Scroll-spy sanity check

Scroll slowly from the top to here. The TOC link for “A long section to force scrolling” should become active as this section enters the top of the viewport. When you continue past this heading to the conclusion, the active link should advance accordingly.

Conclusion

If every section above renders cleanly, the TOC updates as you scroll, the progress bar advances, code blocks recolor when you toggle the theme, and the wavy heading anchors don’t strike through the heading text, the reading subsystem is in good shape.

Delete this file (src/content/posts/toc-test.mdx) once you’re satisfied — it’s only here as a kitchen sink.