<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bonnie Builds Things]]></title><description><![CDATA[Bonnie Builds Things]]></description><link>https://bonniebuildsthings.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a026e98fca21b0d4b7ceea9/08129074-5b38-4cb4-9c86-56863d02e596.jpg</url><title>Bonnie Builds Things</title><link>https://bonniebuildsthings.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 31 Aug 2026 14:55:55 GMT</lastBuildDate><atom:link href="https://bonniebuildsthings.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a glossary that adapts to the reader]]></title><description><![CDATA[As a technical writer, I’ve sometimes been frustrated by reading the engineering documents of services I needed to document. I’d make it through a few paragraphs before I stopped reading and started t]]></description><link>https://bonniebuildsthings.hashnode.dev/glossary-builder</link><guid isPermaLink="true">https://bonniebuildsthings.hashnode.dev/glossary-builder</guid><category><![CDATA[technical writing]]></category><category><![CDATA[glossary]]></category><category><![CDATA[ai-glossary]]></category><category><![CDATA[#ai-tools]]></category><dc:creator><![CDATA[Bonnie Chan]]></dc:creator><pubDate>Wed, 19 Aug 2026 17:40:48 GMT</pubDate><content:encoded><![CDATA[<p>As a technical writer, I’ve sometimes been frustrated by reading the engineering documents of services I needed to document. I’d make it through a few paragraphs before I stopped reading and started tab-hopping: one tab for a term I half-knew, another tab for an acronym I’d seen before but never in this context. Soon, I’d have 10-15 tabs open, a rough understanding of each term in isolation, and absolutely no memory of what the original paragraphs were about.</p>
<p>Translating convoluted information into clear, concise content is the entire job of a technical writer, and yet, our writing can sometimes frustrate readers just like engineering documents frustrate us. Docs get read by people with very different backgrounds, and the same sentence lands differently depending on who’s reading it. A term that’s obvious to a senior engineer can be perplexing for a junior engineer, and on the other hand, a term that’s written for a junior engineer can come across as condescending to the senior engineer.</p>
<p>So one afternoon, I built a <a href="https://github.com/cbonnie-fun/glossary-builder">glossary tool</a> that adapts to the reader instead of fixedly defining terms for a vague audience. The tool uses the same source file to generate different terms with different depths that are targeted towards different audiences. If you write docs, this tool lets you serve a junior and a senior reader without maintaining two versions of the same page. If you mostly read docs, such as specs, contracts, or anything dense, this tool gives you a jump start by only defining the terms that are unfamiliar to you. This post describes how the tool works.</p>
<h2>Why one definition never fits every reader</h2>
<p>A glossary collects specialized terms and acronyms in one place so a reader can understand an unfamiliar word without losing the thread of what they were reading. Most glossaries are static, where each term has one fixed definition.</p>
<p>Static glossaries have two problems. First, a single fixed definition is always pitched at somebody, and every reader who isn't that somebody gets a worse page. Second, fixed definitions get stale and hard to maintain as codebases evolve and teams repurpose words. A definition written eighteen months ago for a service that has since been rearchitected is worse than no definition at all, and the reader has no way to tell it’s stale.</p>
<p>A dynamic glossary generates its definitions at read time instead of storing them. Because nothing is fixed, the same term can be explained one way for a junior reader and another way for a senior one, and each definition is derived from the current source text rather than from whatever was true the last time someone edited the page.</p>
<h3>What a franken-definition looks like</h3>
<p>Take a term like <em>dependency injection</em>. A junior engineer needs the concept, while a senior engineer needs the architecture. Two different definitions:</p>
<p><strong>For a junior SWE:</strong> "Dependency injection is a design pattern where an object receives the objects it depends on instead of creating them itself. Think of a car: rather than building its own engine, the car gets an engine that was built separately and installed at the factory."</p>
<p><strong>For a senior SWE:</strong> "Dependency injection implements Inversion of Control by supplying an object with its required components from an external source. It moves responsibility for object creation and lifecycle management out of individual classes and into a centralized container."</p>
<p>A static glossary has to pick one. Or worse, it splits the difference:</p>
<p><strong>Franken-definition:</strong> "Dependency injection is a design pattern used to implement Inversion of Control (IoC) where an object receives its dependencies from an external source. Think of a car: rather than building its own engine, the car gets an engine that was built separately and installed at the factory. Architecturally, responsibility for object creation and lifecycle management is transferred from individual classes to a centralized DI container."</p>
<p>Now the junior reader hits "Inversion of Control" in the first sentence and stops. The senior reader gets a car metaphor in the middle of a paragraph they were already following, and quietly concludes these docs aren't for them.</p>
<h2>How the tool works</h2>
<p>My glossary builder is a CLI tool that reads a technical document and generates a glossary pitched at the target reader you specify, so the same source produces different terms and explanations that are calibrated for different audiences. For details on the command, see the tool’s <a href="https://github.com/cbonnie-fun/glossary-builder#run-the-python-command">README</a>.</p>
<p>My glossary tool’s workflow has 4 steps:</p>
<ol>
<li><p><strong>Ingest</strong>: The tool reads your source file and chunks it into pieces of roughly 8,000 characters. It breaks on paragraph boundaries so a term never gets separated from the sentences that give it meaning.</p>
</li>
<li><p><strong>Extract</strong>: The tool passes each chunk of text to Claude Haiku and prompts it to return a JSON array of terms a reader at the target level would be unfamiliar with. A maximum of 8 terms can be returned.</p>
</li>
<li><p><strong>Define</strong>: The tool sends the array of terms and the surrounding text to Claude Sonnet and prompts it to write a concise definition for each term based on how the terms are used in context. Steps 2 and 3 run per chunk.</p>
</li>
<li><p><strong>Format</strong>: Results are merged across chunks and rendered as Markdown, HTML, JSON, plain text, or a terminal table.</p>
</li>
</ol>
<p>The reader levels (junior developer, mid-level developer, and senior developer) are defined in a module-level lookup table and interpolated by the prompts for extraction and definition. For example, when you specify <code>--expertise-level senior</code> in the command, the prompts interpolate the phrase “a senior developer with 7+ years of experience” and generate advanced terms explained in a deeper level. When you specify <code>--expertise-level junior</code>, you get introductory terms that are explained more gently.</p>
<h3>Engineering decisions</h3>
<p>I purposely decided to split extraction from definition so I could utilize my tokens more efficiently while preserving the core power of the glossary tool. Instead of making a single API call where I hand Claude the document, ask for terms and definitions together, and then parse the result, I treated extraction and definition as distinct phases of the workflow. Extraction is about triaging a list of strings as output, which Haiku can do very well while running at $0.25 per million input tokens. Definition is about writing, which Sonnet performs better at, even though it costs $3 per million input tokens. Separating the API calls means Haiku handles the bulk reading at a cheaper rate, while Sonnet is reserved for writing the content that a reader actually sees.</p>
<p>Separating the API calls also means that it’s easier to troubleshoot when things go wrong. If the glossary tool defines a term that the target reader doesn’t need, I’ll know to fix the extraction prompt sent to Haiku. If the definition of a term is written in a way that doesn’t suit the target reader’s expertise level, I’ll know to fix the definition prompt to Sonnet.</p>
]]></content:encoded></item></channel></rss>