How the /learn glossary on sovgrid.org works, why it links itself, what makes each entry more than a definition, and the design calls I argued myself out of: tooltip versus link, /glossary versus /learn, and merging it into the book.

Building /learn: a reference layer, and the options I rejected

Self-hosted AI is an acronym swamp. A single setup post on this site can throw OOM, KV cache, VRAM, MoE, GPTQ, and TLA-soup at a reader inside three paragraphs, and every one of those is a wall a newcomer can hit and bounce off. For two years the site’s answer was define-on-first-use: spell the term out the first time it shows up, then move on. That works inside one article. It does nothing for the reader who arrives on article number forty and has never seen the term defined, because the definition lives in an article they never read.

/learn is the fix. It is a 100-term reference layer: every term in an article body links, on its first mention, to a short evergreen entry that says what it means, why it matters, and where to go deeper. This post is the build log. The logic, the strategy, the parts that are genuinely different from a normal glossary, the inspirations I copied from on purpose, and the design decisions I argued myself out of along the way.

The strategy: an evergreen floor under the dated articles

The articles on this site are dated war stories. They are the most valuable thing here and the most perishable. A throughput number is true on the day I measured it and slowly rots after. A glossary entry is the opposite: it should be true for years and carry no numbers at all.

So the strategy was never “extract the glossary from the articles.” It was to build a second surface with the opposite shape and let the two reference each other. The article is the dated record of what happened when I ran the thing. The /learn entry is the evergreen explanation of the term, and it links out to the articles as its dated evidence. The comparison table above is the whole thesis: same subject, opposite lifespan, opposite job.

This is the pillar-and-cluster pattern that documentation and SEO teams have used for a decade, and naming it correctly is the whole point. Each /learn entry is a pillar page: a stable, authoritative page that owns one concept, with the dated articles as the cluster pointing into it and the pillar pointing back out. That was the outcome of grilling the original idea hard before any code: what I am building is not a glossary. A glossary is a flat list of one-line definitions you scroll past. This is a pillar layer that you happen to enter through a short definition, then keep reading. The distinction drove every later decision, from the depth of each entry to the URL it lives at. The payoff is concrete: a reader who lands on any article gets a defined-term safety net, and a search engine sees a tightly linked cluster of pages on one subject instead of forty loosely related posts.

The thing I did not want was a content fork. A glossary you maintain by hand drifts from the articles the moment you touch either one. So the link is generated, and the vocabulary lives in exactly one place.

Each term is two files and no duplicated field. A row in a single manifest carries the linking vocabulary: the slug, the canonical term, its spelled-out abbreviation, a difficulty tier, a category, and any aliases the matcher should also catch. A separate markdown file carries the content: the definition, the at-a-glance facts, an optional diagram, the verify-it-yourself block, the do and don’t pair, and the links out. Nothing is written twice, so nothing can disagree with itself.

A small build-time plugin walks every article’s rendered text. On the first mention of any known term or alias, it wraps that text in a link to the matching entry, then marks the term as used so it never links the same word twice in one article. It skips anything already inside a link, a heading, or a code block, so it never rewrites a command or a title. The result, measured on the current build: 152 of the 157 published articles now carry at least one of these links, and not one of them was edited by hand to get it.

That is the single most important property of the system. Adding a term is one manifest row plus one markdown file. The 152 articles wire themselves up.

What makes an entry more than a definition

A plain glossary would have stopped at the definition. The brief I gave myself was that each entry had to be worth more than the dictionary line a reader could get from any other site, for the newcomer, the practitioner, and the machine reading the page. So every entry can carry, on top of the definition:

That depth is what makes each entry a pillar rather than a glossary line, and it is also the reason the pillar layer stays its own thing instead of being folded into anything else. More on that at the end.

The best-practice sources I copied from

None of this was invented from scratch. The honest version of “design” here is “I read who does it well and took the parts that survived scrutiny.”

The trigger was a German Bitcoin education site, blocktrainer.de, where in-text terms carry a dotted underline that opens a short explanation. That dotted-underline affordance, distinct from a normal link, is theirs and I kept it. The cluster strategy, a stable concept hub with dated material pointing in, is what Cloudflare’s Learning Center and MDN both do at scale, and both were open in a tab while I built this. The DefinedTerm and DefinedTermSet structured-data approach is straight from schema.org’s own vocabulary. And the accessibility rules, the ones that decided link versus tooltip below, come from the WCAG success criteria on links in text blocks and on content shown on hover or focus.

The naming argument: /glossary versus /learn

I did not want to call it /glossary, and the reason is not cosmetic. “Glossary” promises a flat list of definitions. What I was building had deep-dive entries with diagrams and runnable checks, which is more than a glossary, and the URL sets the expectation. I went through /field-guide and /guide before landing on /learn, copying the convention Cloudflare uses for exactly this kind of explanatory layer. /learn says “this is where you go to understand a thing,” which is the promise the entries actually keep. The slug is /learn; the entries are reference entries; the two are allowed to use different words because they name different things.

The first instinct everyone has, mine included, is a tooltip: hover the term, see the definition, never leave the page. I rejected it for two reasons that are not matters of taste. A tooltip does not exist on a touchscreen, where there is no hover, so every phone reader loses the feature entirely. And a tooltip that traps content behind hover runs straight into the WCAG rule on content shown on hover or focus, which requires it to be dismissable, hoverable, and persistent, all of which is a pile of fragile JavaScript to get right.

A plain link has none of those problems. It works on touch, it is one accessible element, and it survives with JavaScript turned off. So the term is a link. To keep it from looking like every other link, it carries the dotted underline from blocktrainer plus a small info icon, which signals “this opens an explanation” without lying about being anything other than a link. The deeper preview-on-hover idea is not dead, but it is a later enhancement layered on top of a thing that already works, not a dependency.

The decisions I reversed in public

Three of the calls on this feature were wrong on the first try and got fixed after they shipped, which is the normal way this site works.

The landing page launched with a sort menu that included “Newest.” All 100 entries were created in the same batch on the same day, so “Newest” reordered nothing and read as a broken control. The tempting fix was to spread fake dates across the entries so the sort would do something. That is fabricated timestamps, which is the exact thing this site does not do, so I deleted the option instead. The real date field stays; the sort returns on its own the day entries genuinely diverge.

The difficulty tiers were labelled basics, deeper, deep. A reader pointed out that this reads backwards, because “deeper” sounds further along than “deep.” They were right. The fix was one word: basics, deeper, deepest, a ladder that actually climbs.

And the cards on the landing page only signalled that they were clickable on hover, which, again, does not exist on touch. The fix was not to invent a new affordance but to copy the one the rest of the site already uses: an always-visible “Open entry” call to action and the same hover lift the blog cards have. Consistency with the existing UI beat cleverness, which is usually the right call.

What I deliberately kept out

Two places where the obvious move was to reuse the /learn content, and where reusing it would have been a mistake.

The first is this site’s machine-readable knowledge base, the corpus the on-site assistant retrieves from. Adding 100 short definition pages to it sounds like free coverage. It is actually retrieval dilution: a hundred thin, overlapping entries that compete with the dense articles for the same query and drag the average chunk quality down. The /learn pages are a reader and search surface on purpose, and they are deliberately absent from the knowledge base. I verified the corpus has zero of them.

The second is the book. The book has its own glossary, and it is the opposite shape from /learn by design: one frozen definition per term, no numbers, only the terms the book actually uses. Folding the rich, numbered, runnable /learn entries into it would break the book’s own rules and create a third copy to keep in sync. The right relationship there is the same as everywhere else in this build: the book is the frozen concept and the narrative, /learn is the living, dated, runnable companion, and they point at each other instead of duplicating. Of the 100 /learn terms, exactly 9 overlap with the book glossary, and the only thing those 9 need to share is a definition that does not contradict.

That is the whole spine of the thing. A glossary that links itself, an evergreen floor under the dated articles, entries that are worth more than a definition because you can run them, and a short list of tempting shortcuts that would have cost more than they saved. The reference architecture behind the rest of the stack is written up in the sovereign AI stack reference, and the rules this build follows are the ones in the engineering honesty manifesto. The fastest way to see /learn is to open any article and click the first dotted term, or start at the index.

Comparison

Two surfaces, one job split

Why the glossary is not just the articles minus the dates

An article
A /learn entry
Lifespan
Dated. A war story from one week.
Evergreen. The definition of record.
Numbers
Measured throughput, versions, configs.
Concept only. Numbers live in the articles it links.
Job
Show what happened when I ran it.
Explain the term a reader hit, then send them deeper.
Voice
First person, narrative.
Plain, neutral, citable by a stranger.

Was this worth it? Zap the article.

Value for value, no signup. Sats go straight to the writer.