This page exercises every construct the blog pipeline supports. Each section states the feature under test and the output that constitutes correct rendering, so that a regression in a plugin, a style rule, or a component override is visible on inspection.
The pipeline consists of @next/mdx with the remark and rehype plugins listed below, and typography supplied by the Tailwind prose classes as configured in BlogContent.tsx.
| Plugin | Stage | Function |
|---|---|---|
remark-frontmatter | remark | Parses the YAML block so it can be removed from the tree |
remark-math | remark | Recognizes $...$ and $$...$$ delimiters |
remark-gfm | remark | Tables, task lists, strikethrough, footnotes |
rehype-highlight | rehype | Syntax highlighting by language |
rehype-highlight-code-lines | rehype | Line numbers within code blocks |
rehype-katex | rehype | Renders math to HTML |
1. Headings
Second-level headings carry a bottom border and increased top margin. Third-level headings are smaller and unruled. Fourth-level headings receive no explicit override and fall back to the prose defaults.
1.1 A third-level heading
Body text at the third level is styled identically to body text elsewhere; only the heading differs.
A fourth-level heading
Correct rendering shows four distinct sizes with decreasing weight and no border below the third and fourth levels.
2. Inline text
Text may be bold, italic, bold and italic, struck through, or set as inline code. Inline code is rendered on a muted background with rounded corners and no surrounding backticks; visible backtick characters indicate that the prose-code pseudo-element overrides have regressed.
Links take the prose defaults, as in the Next.js MDX documentation. Link styling is only observable inline, so it is tested in a sentence rather than in isolation.
A single newline within a paragraph does not produce a line break. Two trailing spaces do produce one, as at the end of the previous line.
3. Lists
Unordered lists nest to three levels:
- First-level item
- Item containing
inline code- Second level
- Second level, sibling
- Third level
- First level, resumed
Ordered lists nest and renumber independently at each level:
- First step
- Second step
- Substep
- Substep, sibling
- Third step
Task lists are provided by remark-gfm. Correct rendering shows a checkbox with no list marker beside it:
- Parse frontmatter and remove it from the output
- Render block and inline mathematics
- Provide a
Calloutcomponent - Add anchor links to headings
4. Blockquotes
A blockquote is rendered with a left border and italic text, and should remain legible when the content is long enough to wrap across several lines.
Consecutive paragraphs are permitted, and inline formatting is preserved within them. No quotation marks are inserted; if they appear, the
proseblockquote pseudo-elements have not been cleared.
5. Code blocks
Code blocks are wrapped by the CodeBlock component, which adds a copy button on hover, and line numbers are supplied by rehype-highlight-code-lines. Highlighting is selected by the language tag on the opening fence.
import numpy as np
def neuron(inputs, weights, bias):
"""
Single-neuron computation.
"""
weighted_sum = np.dot(inputs, weights) + bias
return sigmoid(weighted_sum)
def sigmoid(x):
"""Sigmoid activation function."""
return 1 / (1 + np.exp(-x))
type Post = {
slug: string;
title: string;
date: string;
draft?: boolean;
};
export function published(posts: Post[]): Post[] {
return posts
.filter((post) => !post.draft)
.sort((a, b) => b.date.localeCompare(a.date));
}
npm run generate-mdx # regenerate content/blog imports
npm run dev # runs generate-mdx first
{
"title": "Rendering Showcase",
"date": "2024-01-20",
"draft": false
}
A line wider than the content column determines whether the block scrolls horizontally or wraps. Correct behavior is a horizontal scrollbar confined to the block, with no horizontal scrolling of the page:
const result = await fetch('https://example.com/api/posts?limit=50&offset=0&include=author,tags&sort=-publishedAt').then((response) => response.json());
A fence with no language is rendered without highlighting and retains both the line numbers and the copy button:
$ curl -s https://example.com/health
ok
6. Mathematics
Inline mathematics is set on the surrounding baseline and must not disturb the line spacing. The mass-energy relation and the taller expression both appear in this paragraph for that reason.
Display mathematics is centered in its own block:
where are the inputs, the weights, the bias, and the activation function. Definitions of this kind are set as running text rather than as a list, since the terms are short.
Propagation between layers, with the output of one layer forming the input to the next:
The chain rule applied to the loss with respect to a single weight:
Multi-line alignment and matrix environments are the constructs most likely to fail in a KaTeX configuration, and are tested here:
Equation numbering is available through \tag, which renders right-aligned within the display block:
Numbered equations may then be referred to by number, as (6.1) is here.
7. Tables
Tables are provided by remark-gfm. The table in the introduction uses default alignment; the one below sets alignment per column, with the numeric column right-aligned.
| Feature | Status | Lines of config |
|---|---|---|
| Syntax highlighting | done | 3 |
| Mathematics | done | 2 |
| Callouts | pending | 0 |
8. Horizontal rules
A horizontal rule separates content without introducing a level of hierarchy, and is distinguishable from the border beneath a second-level heading by its position and full width.
9. MDX components
Because these files are compiled as MDX, JSX may be written inline. This is the mechanism for any content Markdown cannot express.
not-prose class excludes it from the surrounding typography styles.Multi-line children of a JSX element are reparsed as Markdown and wrapped in a paragraph. A <p> element with children on separate lines therefore produces a paragraph nested inside a paragraph, which is invalid HTML and raises a hydration error at runtime. Use <div> for such containers, as above.
9.1 Registered components
Components registered in mdx-components.tsx are available in MDX without an import. The file currently overrides pre to supply the copy button on code blocks and registers the NeuralManifold component below.
The element above is written as <NeuralManifold size="sm" /> in the MDX source, inside a centering wrapper and with no import statement in this file. It is a client component rendering WebGL to a canvas, and it responds to dragging, which makes it a test of three things at once: that a registered component resolves, that a 'use client' component can be mounted inside a server-rendered MDX page, and that an interactive canvas survives hydration inside the prose container.
9.2 Components taking props
NeuralManifold accepts size, backgroundClassName, and transparentBackground. Props pass through the MDX compiler unchanged, including expression props in braces, so a component may be configured from the MDX source in the ordinary way.
10. Footnotes
Footnotes are provided by remark-gfm and are collected into an automatically titled section at the foot of the page, which is why this heading is numbered rather than named for them.1 A second reference confirms the numbering and the back-links.2