This page exists to be looked at, not read. It puts one of everything the templates know how to render on a single screen, so that after a change to the type scale, the colour tokens, or the font loading, there is one URL that will show the damage.
Everything below is live output from the same pipeline that renders real posts: Goldmark for Markdown, Chroma for syntax highlighting, and KaTeX rendered at build time — no math JavaScript is shipped to your browser.1
Prose and inline marks
Running text sets in Lora at 17px across a 720px measure. The face carries
italics, bold, and bold italics, plus inline code, strikethrough,
and an internal link alongside an external one — the
latter picks up target="_blank" automatically from the link render hook.
The fonts ship as two unicode-range slices, and most accents live in the first
one: the latin file covers U+0000–00FF plus a few strays, so Gödel, Poincaré,
naïve, Ångström and Œuvre all come from the same file as the rest of this
sentence. Only a handful of characters fall through to the latin-ext file —
Erdős (ő, U+0151) and Łukasiewicz (Ł, U+0141) are the ones to watch. If those two
render in a visibly different face from the names beside them, the extended
subset failed to load; the others would not tell you anything either way.
A blockquote marks the left edge with the brand colour and drops the text to the muted foreground. It should still read as part of the article, not as a callout box bolted onto it.
Three kinds of list, one after another:
- Unordered, first item
- Second item, with a nested level below it
- Nested item, which sets one step tighter
- Another nested item
- Third item
- Ordered lists number in the prose face
- Second step
- Third step
Term-style lists work through plain paragraphs and bold leads:
Blocking period — how long the browser hides text while it waits for a webfont. Swap period — how long it will still replace the fallback once the real face arrives.
Mathematics
Inline math sits on the text baseline: the golden ratio satisfies , and for any we have where .
Display math gets its own block and centres:
Multi-line alignment, sums, and products:
Matrices, cases, and the calligraphic and blackboard faces — these pull in KaTeX’s AMS and Caligraphic files, which are not preloaded, so they are the slowest glyphs on the page:
A softmax over logits, the one formula every ML post eventually needs:
Code
Python, with a language chip in the corner and a copy button on hover:
from dataclasses import dataclass
@dataclass(frozen=True)
class FontFace:
family: str
weight: tuple[int, int]
display: str = "swap"
def css(self) -> str:
lo, hi = self.weight
return (
f"@font-face{{font-family:{self.family!r};"
f"font-weight:{lo} {hi};font-display:{self.display}}}"
)
faces = [FontFace("Lora", (400, 700)), FontFace("Raleway", (100, 900))]
print("\n".join(f.css() for f in faces))
Go, to check a second lexer’s colour assignments:
package main
import "fmt"
// preload reports whether a face is worth a top-priority hint: only if the
// page actually paints glyphs in it.
func preload(face string, used map[string]int) bool {
return used[face] > 0
}
func main() {
used := map[string]int{"Lora": 3926, "Raleway": 0}
for _, face := range []string{"Lora", "Raleway"} {
fmt.Printf("%-8s used=%-5d preload=%v\n", face, used[face], preload(face, used))
}
}
A shell session, where the prompt and comments carry most of the colour:
# Rebuild and check what the page actually shipped
hugo --gc --minify --baseURL "https://hxiang-sun.com/"
find .hugo/public -name '*.woff2' -exec ls -la {} \; | awk '{print $5/1024 "KB", $9}'
And a short config sample, since JSON and YAML land in posts often enough:
{
"fonts": { "lora": "400 700", "raleway": "100 900" },
"preload": ["lora-latin.woff2"],
"display": "swap"
}
guessSyntax: true is set, so a fence with no language does not stay unlabelled —
Chroma guesses, and the corner chip ends up reading whatever it guessed. Tag the
fence text when the block is output rather than source:
$ curl -sI https://hxiang-sun.com/ | grep -i cache-control
cache-control: public, max-age=0, must-revalidate, s-maxage=600
Tables
Tables stretch to the measure and rule every cell:
| Face | Subset | Axis | Size | Preloaded |
|---|---|---|---|---|
| Lora | latin | wght 400–700 | 37 KB | on posts |
| Lora | latin-ext | wght 400–700 | 20 KB | no |
| Lora italic | latin | wght 400–700 | 40 KB | no |
| Raleway | latin | wght 100–900 | 42 KB | off posts |
| Raleway | latin-ext | wght 100–900 | 26 KB | no |
Numbers set with lining figures, so a column of them stays even: 1234567890.
Raw HTML
unsafe: true is on in the Goldmark renderer, so hand-written HTML passes
through — useful for figures that need a caption:
Heading depth
The table of contents indexes h2 only, so the levels below exist to be looked
at rather than navigated.
Third level
Sets smaller than an h2 but keeps the serif face and the same tight leading.
Body copy under it stays at the normal measure.
Fourth level
Smaller again, still a heading rather than emphasised prose.
Fifth level becomes a quiet label
Small caps and letter-spacing take over at this depth, which is why it reads as a label instead of a title.
Sixth level matches it
The last rung of the ladder.
Footnotes and the end
Footnotes collect at the bottom with a rule above them and a back-reference arrow on each.2 They renumber automatically, so the order they are written in does not matter.3
The
render-passthroughhook callstransform.ToMathduringhugo, so the finished HTML already contains the formula markup. Only KaTeX’s stylesheet and its woff2 faces load at runtime, and only on pages that setmath: truein front matter. ↩︎A second note, to check that the list markers survive the global
<ol>reset that strips numbering everywhere else on the site. ↩︎A third, with
inline codeand italics inside it, since footnote text sets one step down and the smaller size is where a bad fallback shows first. ↩︎