{
    "version": "https://jsonfeed.org/version/1",
    "title": "Faith Wachukwu — Blog",
    "home_page_url": "https://faithwachukwu.com/blog/",
    "description": "Technical writing, documentation strategy, and docs-as-code insights.",
    "items": [
        {
            "id": "https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/mkdocs1.png\" alt=\"#\">\n<p>If you maintain technical documentation in 2026, there’s a good chance you’re using <a href=\"https://www.mkdocs.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">MkDocs</a> or <a href=\"https://pypi.org/project/mkdocs-material/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Material for MkDocs</a>.</p>\n<p>You picked it for good reasons. You can get a docs site running in minutes, write everything in <a href=\"https://www.markdownguide.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Markdown</a>, deploy to <a href=\"https://pages.github.com/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">GitHub Pages</a> with a lightweight CI pipeline, and end up with a polished-looking documentation site without much setup.</p>\n<p>What you might not know is that there is a shift. The team behind Material for MkDocs has introduced <a href=\"https://squidfunk.github.io/mkdocs-material/blog/2025/11/05/zensical/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical</a>, a new static site generator written from scratch in Rust, and <a href=\"https://github.com/squidfunk/mkdocs-material/issues/8523\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">placed Material for MkDocs into maintenance mode</a>. At the same time, MkDocs 2.0 is heading in a direction that won’t remain compatible with Material for MkDocs or much of its existing plugin ecosystem.</p>\n<p>If your team builds docs-as-code, then this matters to you. In this walkthrough, you’ll learn what Zensical actually is, how to migrate an existing Material for MkDocs project step by step, and whether it makes sense to move now or wait.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-we-got-here\">How We Got Here<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#how-we-got-here\" class=\"hash-link\" aria-label=\"Direct link to How We Got Here\" title=\"Direct link to How We Got Here\" translate=\"no\">​</a></h2>\n<p><a href=\"https://www.mkdocs.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">MkDocs</a> has been around since 2014. It’s a simple Python-based static site generator that works by pointing it to a folder of Markdown files, providing a YAML config, and generating a searchable documentation site. It has a minimal and clean architecture.</p>\n<p>In 2016, <a href=\"https://github.com/squidfunk\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Martin Donath (known online as Squidfunk)</a> released <a href=\"https://squidfunk.github.io/mkdocs-material/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Material for MkDocs</a>. Technically, it’s a theme, but it has evolved into a framework for technical writing. We’re talking about tabs, admonitions, code annotations, versioned navigation, and instant search.</p>\n<p>Here's the part most people miss: <strong>Material for MkDocs and MkDocs are two different projects with two different teams</strong>. Squidfunk's team maintains Material for MkDocs. They have no control over MkDocs itself; they just depend on it.</p>\n<p>As for the underlying MkDocs engine, MkDocs 1.x has been effectively unmaintained since August 2024, with <a href=\"https://github.com/mkdocs/mkdocs/releases/tag/1.6.1\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">version 1.6.1, released on August 30, 2024</a>. It remains the last release to date, as of the time of writing this article.</p>\n<p>With issues piling up and no maintained path forward, the Material for MkDocs team faced a strategic question: keep building on a stagnant dependency, or move, and they chose to move.</p>\n<p>On <a href=\"https://squidfunk.github.io/mkdocs-material/blog/2025/11/05/zensical/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">November 5, 2025, the Material for MkDocs team announced Zensical</a> — a static site generator they'd been building from scratch for over a year. About six days later, they shipped <a href=\"https://squidfunk.github.io/mkdocs-material/blog/2025/11/11/insiders-now-free-for-everyone/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Material for MkDocs 9.7.0</a>, which made all previously paid “insiders”  features free, and put the project into a <a href=\"https://github.com/squidfunk/mkdocs-material/issues/8523\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">12-month maintenance window</a> covering critical bug fixes and security updates only.</p>\n<p>In late January 2026, MkDocs 2.0 entered pre-release as a ground-up rewrite with breaking changes that would have broken Material for MkDocs and the plugins built on top of it based on the <a href=\"https://squidfunk.github.io/mkdocs-material/blog/2026/02/18/mkdocs-2.0/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">team's analysis</a>. The decision to build Zensical was already validated.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/zensical-timeline.png\" alt=\"Timeline showing MkDocs stagnation from Aug 2024, Zensical announcement in Nov 2025, and continued Zensical releases into 2026.\"><p><em>The ecosystem shift from Material for MkDocs to Zensical, marked by stagnation, announcement, and rapid post-launch development through 2026.</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-zensical-actually-is\">What Zensical Actually Is<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#what-zensical-actually-is\" class=\"hash-link\" aria-label=\"Direct link to What Zensical Actually Is\" title=\"Direct link to What Zensical Actually Is\" translate=\"no\">​</a></h2>\n<p><a href=\"https://zensical.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical</a> is a modern static site generator designed to replace the MkDocs stack while staying backwards-compatible with existing projects.  It’s built from years of experience, so they’ve learned what works and what doesn’t. They created it to fix the problems in MkDocs and go beyond what MkDocs can do.</p>\n<p>Although it’s a new project, it’s compatible with your existing <code>mkdocs.yml</code>. Not all plugins are supported yet, but your core configuration works.</p>\n<p>Zensical is built in Rust, with a thin Python layer on top using <a href=\"https://pyo3.rs/v0.28.3/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">PyO3</a>. That’s why you install it with <code>pip</code> like any Python package, but it runs much faster, closer to a Rust tool than a typical Python one.</p>\n<p>Underneath, two components do the heavy lifting:</p>\n<ul>\n<li class=\"\"><strong>ZRX (Zen Reactive Extensions)</strong> handles caching, data flow, and incremental builds. It’s the reason rebuilds are fast instead of painfully slow.</li>\n<li class=\"\"><strong>Disco</strong> powers search, with better ranking and filtering than the usual setup.</li>\n</ul>\n<p>Zensical ships two theme variants. The <strong>classic</strong> variant, which matches the Material for MkDocs look and the <strong>modern</strong> variant, which gives your site a fresh appearance.</p>\n<p>There is, however, an honest caveat; Zensical is still in its early stage (alpha). The current version on PyPI is <a href=\"https://pypi.org/project/zensical/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">0.0.43, released May 19, 2026</a>, as of the time of writing. However, the project has shipped frequently since going public in November 2025.</p>\n<p>Even though it’s in its early stages, it works. The <a href=\"https://github.com/zensical\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">GitHub Repo</a> already has 4,700+ stars, and major projects are already migrating.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/zensical.png\" alt=\"Zensical homepage displaying its documentation tooling features and navigation layout.\"><p><em>Zensical’s landing page introducing its modern documentation platform.</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-migration\">The Migration<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#the-migration\" class=\"hash-link\" aria-label=\"Direct link to The Migration\" title=\"Direct link to The Migration\" translate=\"no\">​</a></h2>\n<p>Before migrating to Zensical, make sure your current setup meets the following prerequisites.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"prerequisites\">Prerequisites<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#prerequisites\" class=\"hash-link\" aria-label=\"Direct link to Prerequisites\" title=\"Direct link to Prerequisites\" translate=\"no\">​</a></h4>\n<ul>\n<li class=\"\">A working Material for MkDocs site</li>\n<li class=\"\"><a href=\"https://git-scm.com/install/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Git installed</a></li>\n<li class=\"\">Python 3.10 or newer <a href=\"https://pypi.org/project/zensical/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">(Zensical's minimum on PyPI)</a></li>\n<li class=\"\">A CI/CD pipeline that builds and deploys your docs.</li>\n</ul>\n<p>Before making changes, audit your project dependencies against the <a href=\"https://zensical.org/compatibility/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical compatibility documentation</a>. To get a clear picture of what you are working on, spend time looking at these three areas:</p>\n<ul>\n<li class=\"\"><strong>Plugins</strong>: Review everything under <code>plugins:</code> in your <code>mkdocs.yml</code>. Zensical supports many of them, but not all yet. So make sure you check the <a href=\"https://claude.ai/chat/c13daa5b-7562-429e-bec2-2662e56d64e1#plugin-compatibility-matrix-current-state\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">compatibility matrix below</a> or <a href=\"https://zensical.org/compatibility/plugins/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical's official plugins page</a> before committing to a migration timeline.</li>\n<li class=\"\"><strong>Theme overrides</strong>: List out your custom templates, CSS, JavaScript, and any hooks. These are the usual suspects when things don’t render the same.</li>\n<li class=\"\"><strong>Markdown extensions</strong>: Look for anything using <code>material.extensions.*</code>. You’ll need to rename those later.</li>\n</ul>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>If a key plugin isn’t supported yet, don’t force it. Either you wait or plan to build the missing piece yourself.</p></div></div>\n<p>Once you’ve reviewed these, follow these steps:</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-1-create-a-migration-branch\">Step 1: Create a migration branch<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-1-create-a-migration-branch\" class=\"hash-link\" aria-label=\"Direct link to Step 1: Create a migration branch\" title=\"Direct link to Step 1: Create a migration branch\" translate=\"no\">​</a></h4>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">git checkout -b migrate/zensical</span><br></div></code></pre></div></div>\n<p>You’ll keep <code>main</code> as your baseline. When something breaks during migration, you need something to compare against, or in case a rollback is needed. Otherwise, you will spend more time guessing.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-2-install-zensical-in-a-new-virtual-environment\">Step 2: Install Zensical in a new virtual environment<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-2-install-zensical-in-a-new-virtual-environment\" class=\"hash-link\" aria-label=\"Direct link to Step 2: Install Zensical in a new virtual environment\" title=\"Direct link to Step 2: Install Zensical in a new virtual environment\" translate=\"no\">​</a></h4>\n<p>Install Zensical in a new virtual environment. You won’t want to mess up your existing mkdocs environment. Run the commands:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">python3 -m venv .venv-zensical</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">source .venv-zensical/bin/activate     # Windows: .venv-zensical\\Scripts\\activate</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">pip install --upgrade pip</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">pip install \"zensical==0.0.43\"         # Pin the version. Alpha velocity is real.</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">zensical --version</span><br></div></code></pre></div></div>\n<p>For <code>uv</code> users:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">uv tool install \"zensical==0.0.43\"</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-3-build-off-your-existing-mkdocsyml\">Step 3: Build off your existing mkdocs.yml<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-3-build-off-your-existing-mkdocsyml\" class=\"hash-link\" aria-label=\"Direct link to Step 3: Build off your existing mkdocs.yml\" title=\"Direct link to Step 3: Build off your existing mkdocs.yml\" translate=\"no\">​</a></h4>\n<p>You don’t need to switch to <code>zensical.toml</code> yet, Zensical works with <code>mkdocs.yml</code>. From the directory containing your <code>mkdocs.yml</code> file, run the command:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">zensical build --clean</span><br></div></code></pre></div></div>\n<p>Zensical reads <code>mkdocs.yml</code> directly and writes to <code>site/</code> . This will show you any first-build errors, and you can fix them.</p>\n<p>Some of the common ones include:</p>\n<table><thead><tr><th>Error</th><th>Fix</th></tr></thead><tbody><tr><td><code>docs_dir</code> cannot be set to <code>'.'</code></td><td>Set <code>docs_dir</code> to a subdirectory such as <code>docs</code> and move your source files there.</td></tr><tr><td>Unknown plugin <code>&lt;name&gt;</code></td><td>Plugin not yet supported. Check the <a href=\"https://claude.ai/chat/c13daa5b-7562-429e-bec2-2662e56d64e1#plugin-compatibility-matrix-current-state\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">compatibility matrix</a>; remove the plugin or stay on MkDocs.</td></tr><tr><td>Unknown setting remote_branch / hooks / etc.</td><td>One of the unsupported settings. Remove.</td></tr><tr><td><code>material.extensions.*</code> unresolved</td><td>Rename to <code>zensical.extensions.*</code> — see step 5.</td></tr></tbody></table>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-4-select-your-theme-variant\">Step 4: Select your theme variant<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-4-select-your-theme-variant\" class=\"hash-link\" aria-label=\"Direct link to Step 4: Select your theme variant\" title=\"Direct link to Step 4: Select your theme variant\" translate=\"no\">​</a></h4>\n<p>To minimize drift during your migration, start with the <code>classic</code> variant.</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"># mkdocs.yml</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">theme:</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  name: material</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  variant: classic       # add this</span><br></div></code></pre></div></div>\n<p>You can switch to <code>modern</code> later if you want.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-5-rename-material-extensions-and-icons\">Step 5: Rename Material extensions and icons<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-5-rename-material-extensions-and-icons\" class=\"hash-link\" aria-label=\"Direct link to Step 5: Rename Material extensions and icons\" title=\"Direct link to Step 5: Rename Material extensions and icons\" translate=\"no\">​</a></h4>\n<p>Do a namespace swap from <code>material.</code> to <code>zensical.</code>:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"># Before</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">markdown_extensions:</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  - pymdownx.emoji:</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      emoji_index: !!python/name:material.extensions.emoji.twemoji</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      emoji_generator: !!python/name:material.extensions.emoji.to_svg</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"># After</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">markdown_extensions:</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  - pymdownx.emoji:</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      emoji_index: !!python/name:zensical.extensions.emoji.twemoji</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      emoji_generator: !!python/name:zensical.extensions.emoji.to_svg</span><br></div></code></pre></div></div>\n<p>For icons, swap the Material brightness icons for Lucide equivalents: <code>material/brightness-7 → lucide/sun</code>, and <code>material/brightness-4 → lucide/moon</code>.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-6-preview-locally\">Step 6: Preview locally<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-6-preview-locally\" class=\"hash-link\" aria-label=\"Direct link to Step 6: Preview locally\" title=\"Direct link to Step 6: Preview locally\" translate=\"no\">​</a></h4>\n<p>Run the command:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">zensical serve</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"># default: http://localhost:8000</span><br></div></code></pre></div></div>\n<p>Open <code>http://local:8000</code> and click through your docs. Don't just spot-check the homepage.</p>\n<p>Compare against your live MkDocs site and look for:</p>\n<ul>\n<li class=\"\">Broken links from absent plugins</li>\n<li class=\"\">Missing icons or admonitions</li>\n<li class=\"\">Empty search results</li>\n<li class=\"\">Layout regressions in custom templates</li>\n</ul>\n<p>If you use <code>mike</code> for versioning, double-check version switching. There's an <a href=\"https://github.com/squidfunk/mike\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">official mike fork maintained by the Zensical team</a>, you'll install it from the Git URL listed in <a href=\"https://zensical.org/compatibility/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">compatibility documentation</a>.</p>\n<div class=\"theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success\"><div class=\"admonitionHeading_Gvgb\"><span class=\"admonitionIcon_Rf37\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_BuS1\"><p>Some setups need temporary pinning to avoid conflicts.</p></div></div>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"step-7-update-your-build-pipeline\">Step 7: Update your build pipeline<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#step-7-update-your-build-pipeline\" class=\"hash-link\" aria-label=\"Direct link to Step 7: Update your build pipeline\" title=\"Direct link to Step 7: Update your build pipeline\" translate=\"no\">​</a></h4>\n<p>If you have a pipeline already setup, replace your CI build command with:</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">zensical build --clean</span><br></div></code></pre></div></div>\n<p>A typical GitHub Actions workflow looks like this:</p>\n<div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> Documentation</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"></span><span class=\"token key atrule\">on</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  </span><span class=\"token key atrule\">push</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">    </span><span class=\"token key atrule\">branches</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> main</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"></span><span class=\"token key atrule\">permissions</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  </span><span class=\"token key atrule\">contents</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> read</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  </span><span class=\"token key atrule\">pages</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> write</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  </span><span class=\"token key atrule\">id-token</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> write</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\"></span><span class=\"token key atrule\">jobs</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">  </span><span class=\"token key atrule\">deploy</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">    </span><span class=\"token key atrule\">environment</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token key atrule\">name</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> github</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">pages</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token key atrule\">url</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> $</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">{</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">{</span><span class=\"token plain\"> steps.deployment.outputs.page_url </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">}</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">    </span><span class=\"token key atrule\">runs-on</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> ubuntu</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">latest</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">    </span><span class=\"token key atrule\">steps</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">uses</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> actions/configure</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">pages@v5</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">uses</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> actions/checkout@v5</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">uses</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> actions/setup</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">python@v5</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">        </span><span class=\"token key atrule\">with</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">          </span><span class=\"token key atrule\">python-version</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> </span><span class=\"token number\">3.10</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">run</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> pip install \"zensical==0.0.43\"   </span><span class=\"token comment\" style=\"color:rgb(98, 114, 164)\"># Add installation commands for other dependencies if needed.</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">run</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> zensical build </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">clean </span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">uses</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> actions/upload</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">pages</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">artifact@v4</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">        </span><span class=\"token key atrule\">with</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">          </span><span class=\"token key atrule\">path</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> site</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\">uses</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> actions/deploy</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">-</span><span class=\"token plain\">pages@v4</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">        </span><span class=\"token key atrule\">id</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">:</span><span class=\"token plain\"> deployment</span><br></div></code></pre></div></div>\n<p>If you're on Read the Docs, build with Zensical and copy the output into their expected directory. The canonical config is in <a href=\"https://zensical.org/docs/setup/basics/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical's setup docs</a>.</p>\n<p>If anything breaks in production after deployment, the rollback is straightforward: revert the merge of the <code>migrate/zensical</code> branch.</p>\n<p>That’s it. Your <code>mkdocs.yml</code> keeps working, and your Markdown files don’t need changes to work with Zensical. Your templates, override, CSS, and JavaScript extensions carry over the same configuration because Zensical uses the same HTML structure and Python-Markdown parser under the hood.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"plugin-compatibility-matrix-current-state\">Plugin compatibility matrix (current state)<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#plugin-compatibility-matrix-current-state\" class=\"hash-link\" aria-label=\"Direct link to Plugin compatibility matrix (current state)\" title=\"Direct link to Plugin compatibility matrix (current state)\" translate=\"no\">​</a></h2>\n<p>Plugin compatibility is one of the first things teams ask about during a migration, but right now the information is spread across Zensical’s docs, GitHub backlog, and community threads. To make things easier, <a href=\"https://zensical.org/compatibility/plugins/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">here’s a consolidated table based on the official Zensical plugin compatibility page</a> as of May 2026.</p>\n<p>The Zensical team analyzed the top 1,000 GitHub repositories using Material for MkDocs to determine which plugins to support first. They grouped the work into two tiers. Tier 1 covers the highest-priority plugins and focuses on getting close to feature parity first, while Tier 2 plugins are still in the backlog.</p>\n<p>A few details matter if you’re planning a migration:</p>\n<ul>\n<li class=\"\">Many teams still use the popular <a href=\"https://github.com/lukasgeiter/mkdocs-awesome-pages-plugin\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">awesome-pages</a> plugin, but its original author has replaced it with <a href=\"https://lukasgeiter.github.io/mkdocs-awesome-nav/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">awesome-nav</a>. Zensical is building support around <code>awesome-nav</code>, not <code>awesome-pages</code>. If your project still depends on <code>awesome-pages</code>, you’ll likely need a two-step migration: move from awesome-pages to awesome-nav in MkDocs first, then migrate to Zensical.</li>\n<li class=\"\">Some plugins don’t appear in either tier because Zensical plans to handle those features differently at the architectural level. The<code>typeset</code> plugin is a good example. Material for MkDocs has already <a href=\"https://zensical.org/compatibility/plugins/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">deprecated</a> it because the upcoming modular navigation system will support rich navigation content natively.</li>\n</ul>\n<p>If your site depends on a Tier 2 plugin that Zensical hasn’t shipped yet, you have options to choose from: wait for support, replace the feature with a workaround, or stay on Material for MkDocs during its 12-month maintenance window until the matching Zensical module becomes available.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"who-should-move-now-and-who-should-wait\">Who should move now, and who should wait<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#who-should-move-now-and-who-should-wait\" class=\"hash-link\" aria-label=\"Direct link to Who should move now, and who should wait\" title=\"Direct link to Who should move now, and who should wait\" translate=\"no\">​</a></h2>\n<p>Based on where the project stands today.</p>\n<p><strong>Migrate now if you:</strong></p>\n<ul>\n<li class=\"\">Run a personal site, a small project without deep plugin customization</li>\n<li class=\"\">Care about the build performance on your large sites (500+ pages)</li>\n<li class=\"\">Already hit limitations with MkDocs’ build speed or search</li>\n</ul>\n<p><strong>Wait a quarter or two if you:</strong></p>\n<ul>\n<li class=\"\">Rely heavily on plugins that aren’t supported yet</li>\n<li class=\"\">Maintain docs for a regulated product where switching to “alpha software” is a hard no</li>\n<li class=\"\">Have a 500-line customized mkdocs.yml stitched together by three different people that span over four years</li>\n</ul>\n<p>The best advice is for you not to wait indefinitely, though. And that’s because Material for MkDocs is in a <a href=\"https://github.com/squidfunk/mkdocs-material/issues/8523\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">12-month maintenance window that already began November 6, 2025</a>, with focus on critical bugs and security fixes only, so no new features will be released. After that, you’ll be running unmaintained software.</p>\n<p>There are early adopters already talking about how easy the process is. Here are some:</p>\n<ul>\n<li class=\"\"><a href=\"https://blog.grosdouli.dev/blog/mkdocs-material-migration-zensical\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Eleni Grosdouli</a> migrated the <a href=\"https://projectsveltos.github.io/sveltos/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Sveltos project documentation</a> and described the process as \"easy and headache-free,\" noting that the main work was adjusting the GitHub Actions workflow.</li>\n<li class=\"\">The <a href=\"https://github.com/ddev/ddev/issues/7840\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">DDEV team</a> and <a href=\"https://github.com/renovatebot/renovate/discussions/39232\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Renovate</a> have all either completed the move or filed migration issues.</li>\n</ul>\n<p>The plugin ecosystem hasn't fully caught up though, so if your project depends on a lot of plugins, expect some friction.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-does-this-signal-for-docs-as-code\">What does this signal for docs-as-code<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#what-does-this-signal-for-docs-as-code\" class=\"hash-link\" aria-label=\"Direct link to What does this signal for docs-as-code\" title=\"Direct link to What does this signal for docs-as-code\" translate=\"no\">​</a></h2>\n<p>In my view, for docs-as-code, Zensical is bigger than the tool itself. There are three things worth noting about it:</p>\n<ul>\n<li class=\"\">\n<p><strong>End of the sponsorware era</strong>: Material for MkDocs used a model in which sponsors received early access to features. But with the 9.7.0 release, <a href=\"https://squidfunk.github.io/mkdocs-material/blog/2025/11/11/insiders-now-free-for-everyone/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">all Insider features became free for everyone</a>. Zensical, however, replaced sponsorware with <a href=\"https://zensical.org/spark/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical Spark</a>  — a support-and-services tier aimed at organizations rather than individual developers.</p>\n</li>\n<li class=\"\">\n<p><strong>Compatibility</strong>: The team could have shipped a clean-break rewrite and forced the users to rewrite their docs, but they didn’t. They shipped something that can work with your existing config. That’s a good product decision, and it’s why adoption is moving faster.</p>\n</li>\n<li class=\"\">\n<p><strong>Docs-as-code is maturing</strong>: For a long time, documentation tools lagged behind developer tools. Now, tools like Zensical with faster builds and better search are catching up. This raises the standard higher, and that’s good for anyone writing docs.</p>\n</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>MkDocs 1.x is no longer actively maintained, and Material for MkDocs has received only limited support for about a year. The same team has already moved forward with Zensical, which is faster, still works with your current setup, and is actively being built.</p>\n<p>If your docs matter to your product, your team, or your users, then you need a plan. Start with the <a href=\"https://claude.ai/chat/c13daa5b-7562-429e-bec2-2662e56d64e1#plugin-compatibility-matrix-current-state\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">compatibility matrix</a>, try a small migration in a separate branch, see what breaks, and plan from there.  If you're stuck on a Tier 2 plugin, watch the <a href=\"https://github.com/orgs/zensical/projects/2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Zensical backlog</a> or consider contributing a module.</p>\n<p>For deeper context on the ecosystem dynamics that led here, Florian Maas's The <a href=\"https://fpgmaas.com/blog/collapse-of-mkdocs/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Slow Collapse of MkDocs</a> is the most thorough public account, and Martin Donath's interview on <a href=\"https://talkpython.fm/episodes/show/542/zensical-a-modern-static-site-generator\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Talk Python #542</a> covers the technical and strategic reasoning behind Zensical from the team itself.</p>",
            "url": "https://faithwachukwu.com/blog/migrating-from-material-for-mkdocs-to-zensical/",
            "title": "Migrating from Material for MkDocs to Zensical: A Documentation Engineer Walkthrough",
            "summary": "If you maintain technical documentation in 2026, there’s a good chance you’re using MkDocs or Material for MkDocs.",
            "date_modified": "2026-05-20T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "technical-writing",
                "documentation",
                "Zensical",
                "Material for MkDocs",
                "Docs"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/why-on-call-engineers-ignore-your-runbooks/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/oncall-cover.png\" alt=\"#\">\n<p>It's 5:15 AM. An alert fires: <em>payments-api, p99 latency &gt; 2000ms for 5m</em>. Olivia's on call. The team has a runbook, but that’s not where she looks for the solution. She completely ignores it. The last few times she followed one at 5 AM, the fix didn’t match the symptom, or the runbook links attached to the alerts were wrong. So she opens Slack, finds a thread from eight months ago, copies the fix, and goes back to bed.</p>\n<p>You wrote that runbook. She didn't use it, and she had reasons. This isn't a failure on Olivia's part. Here's why on-call engineers reach for Slack history before the docs you maintain, and what you can do about it.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-myth-of-the-calm-reader\">The myth of the calm reader<a href=\"https://faithwachukwu.com/blog/why-on-call-engineers-ignore-your-runbooks/#the-myth-of-the-calm-reader\" class=\"hash-link\" aria-label=\"Direct link to The myth of the calm reader\" title=\"Direct link to The myth of the calm reader\" translate=\"no\">​</a></h2>\n<p>In most cases, documentation is written for a reader who has time. They have the mental bandwidth to read prose, follow a tutorial sequentially, and absorb all the concepts. For an on-call engineer like Olivia, she doesn’t have that time. She’s triaging. She scans, copies and pastes, and bails if it doesn’t work. If your runbook starts with three paragraphs of context before the first command, she’s gone.</p>\n<p><a href=\"https://sre.google/sre-book/being-on-call/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">The Google SRE book</a> made this point years ago: the quantity of on-call can be calculated by the percentage of time spent by engineers on on-call duty.</p>\n<p>So, for on-call engineers, a runbook isn’t documentation in the literary sense. It’s a tool. What matters is whether it helps shorten the incident.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-your-docs-lose-at-3-am\">Why your docs lose at 3 AM<a href=\"https://faithwachukwu.com/blog/why-on-call-engineers-ignore-your-runbooks/#why-your-docs-lose-at-3-am\" class=\"hash-link\" aria-label=\"Direct link to Why your docs lose at 3 AM\" title=\"Direct link to Why your docs lose at 3 AM\" translate=\"no\">​</a></h2>\n<p>There are a few patterns that show up in almost every team that struggles with on-call docs. Let's take a look at some of them:</p>\n<ul>\n<li class=\"\">\n<p><strong>The docs aren’t where the alert is</strong>. The runbooks live on Confluence, the alert fires on PagerDuty, the dashboard is in Grafana, while Olivia is in her terminal. None was linked to the others. She is context-switching more often to get information; this is costing her thirty seconds per switch and a little more of her composure while she is frantically searching for a solution.</p>\n</li>\n<li class=\"\">\n<p><strong>The runbook is a tutorial, not a checklist</strong>. It explains in deep details how the payments service works. It does not say <em>if p99 &gt; 2s, check queue depth first; if queue depth &gt; 10k, scale workers; if workers are healthy, page the database team</em>. The <a href=\"https://diataxis.fr/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Diataxis framework</a> nailed this distinction between tutorials, how-to-guides, references, and explanation. They are four different things, and runbooks are how-tos. You don’t need to start explaining in details.</p>\n</li>\n<li class=\"\">\n<p><strong>The runbook is stale</strong>. It tells Olivia to restart <em>payments-worker</em> meanwhile, that service was renamed <em>txn-processor</em> seven months ago. She runs the command, gets service not found, and now she trusts nothing on that page.</p>\n</li>\n<li class=\"\">\n<p><strong>Nobody owns it</strong>. The original author has left the company. The team that runs the service has never opened the doc to update it. There have been countless postmortem-generated action items to update runbooks that weren’t assigned to anyone or verified either.</p>\n</li>\n</ul>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/oncall-1.png\" alt=\"A simple incident response flowchart showing an alert leading to a broken or missing runbook link, then to stale commands, ending with a frustrated engineer during an outage.\"><p><em>A flowchart showing a bad runbook chain reaction: the alert fires, the documentation link fails, the commands are outdated, and the engineer loses time during an incident.</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-makes-a-runbook-usable-during-incidents\">What makes a runbook usable during incidents<a href=\"https://faithwachukwu.com/blog/why-on-call-engineers-ignore-your-runbooks/#what-makes-a-runbook-usable-during-incidents\" class=\"hash-link\" aria-label=\"Direct link to What makes a runbook usable during incidents\" title=\"Direct link to What makes a runbook usable during incidents\" translate=\"no\">​</a></h2>\n<p>For teams whose runbooks actually get read, share a few things in common.</p>\n<ol>\n<li class=\"\">\n<p>They link the runbook from the alert itself. <a href=\"https://response.pagerduty.com/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">PagerDuty</a>, <a href=\"https://www.atlassian.com/software/opsgenie/it-alerting\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Opsgenie</a>, and <a href=\"https://grafana.com/docs/grafana-cloud/monitor-infrastructure/kubernetes-monitoring/respond-to-alerts/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Grafana Alerting</a> all support adding runbook URLs in the alert payload. If your alert doesn’t include the link, it's like the runbook isn't available.</p>\n</li>\n<li class=\"\">\n<p>They start with action to take, not lots of context. The first thing on the page is what to do, how severe, what the symptoms look like, and commands you can copy to solve it. The explanations come much later, for those who want them after they’ve solved the problem.</p>\n</li>\n<li class=\"\">\n<p>They write for the worst version of the reader. The runbook works for someone who is half-asleep, new to the team, and has their adrenaline up. Not only for the senior engineer who wrote it.</p>\n</li>\n<li class=\"\">\n<p>They treat every incident as a doc bug. As <a href=\"https://www.atlassian.com/incident-management\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Atlassian’s incident handbook</a> puts it: <em>\"Every incident should be tracked and documented so you can identify trends and make comparisons over time.\"</em></p>\n</li>\n<li class=\"\">\n<p>They keep runbooks close to code. The Markdown is in the same repo as the code. The runbooks are reviewed in the same PR change that needs it. When docs live far from the code, they tend to rot. And that’s because those writing the code for the fix aren’t going to navigate to a separate wiki to update it.</p>\n</li>\n</ol>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/oncall3.png\" alt=\"An example alert payload showing a runbook_url field.\"><p><em>Runbook link included directly in the alert payload for quick access during incidents.</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-uncomfortable-part\">The uncomfortable part<a href=\"https://faithwachukwu.com/blog/why-on-call-engineers-ignore-your-runbooks/#the-uncomfortable-part\" class=\"hash-link\" aria-label=\"Direct link to The uncomfortable part\" title=\"Direct link to The uncomfortable part\" translate=\"no\">​</a></h2>\n<p>If you’re a docs engineer and the on-call team keeps ignoring your work, it’s tempting to blame them for not searching, reading, or following the process. With a customer-facing outage happening, they definitely would want a solution fast.</p>\n<p>The reader, just like Olivia you’re writing for, is exhausted, scared, and looking for one specific sentence that tells her what to do next to fix the problem.\nMake sure you write that sentence, put it at the top, link it from the alert, update it after every incident, and delete what is not needed.</p>\n<p>The on-call engineer doesn’t read your docs, so make docs that don’t need to be read, but only used.</p>",
            "url": "https://faithwachukwu.com/blog/why-on-call-engineers-ignore-your-runbooks/",
            "title": "Why On-Call Engineers Ignore Your Runbooks ",
            "summary": "It's 5 payments-api, p99 latency > 2000ms for 5m. Olivia's on call. The team has a runbook, but that’s not where she looks for the solution. She completely ignores it. The last few times she followed one at 5 AM, the fix didn’t match the symptom, or the runbook links attached to the alerts were wrong. So she opens Slack, finds a thread from eight months ago, copies the fix, and goes back to bed.",
            "date_modified": "2026-05-18T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "On-call",
                "documentation",
                "technical writing",
                "engineer"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/cover-doc-ux.png\" alt=\"#\">\n<p>When a user lands on your documentation, they’re looking for answers. If they hit a wall of text with no starting point or see steps that assume knowledge they don’t have yet. Within minutes, they’ll be frustrated and say it's a bad product.</p>\n<p>Believing that if the content is accurate and up to date, the docs are good is wrong. The docs being accurate is a starting point. In this article, we’ll dive into what documentation user experience (UX) is, how writing and structure shape it, what having bad documentation UX costs for your product, and how to improve it.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-is-documentation-ux\">What Is Documentation UX?<a href=\"https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/#what-is-documentation-ux\" class=\"hash-link\" aria-label=\"Direct link to What Is Documentation UX?\" title=\"Direct link to What Is Documentation UX?\" translate=\"no\">​</a></h2>\n<p><strong>Documentation User Experience(UX)</strong> is the overall experience users have while interacting with your documentation. It goes beyond the layout, color schemes, or which static site generator you used. It includes how content is structured, how language is used, how the navigation works, and most importantly how well the documentation meet the users where they are.</p>\n<p>Good documentation UX helps users answer three questions quickly:</p>\n<ul>\n<li class=\"\">Am I in the right place?</li>\n<li class=\"\">Do I understand what I'm reading?</li>\n<li class=\"\">What should I do next?</li>\n</ul>\n<p>The moment the answer to any of these questions becomes “I’m not sure”, the experience has already started to crack. And once that crack forms, users rarely stick around for you to fix it.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/find-understand-act.png\" alt=\"Three-step documentation journey: find, understand, act\"></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-writing-and-structure-shape-documentation-ux\">How Writing and Structure Shape Documentation UX<a href=\"https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/#how-writing-and-structure-shape-documentation-ux\" class=\"hash-link\" aria-label=\"Direct link to How Writing and Structure Shape Documentation UX\" title=\"Direct link to How Writing and Structure Shape Documentation UX\" translate=\"no\">​</a></h2>\n<p>Documentation UX problems can arise from writing too close to the product. When you build a feature, you understand it deeply, but the users don’t, and that deep understanding can be a blind spot. You’ll write docs that make perfect sense to someone who already knows how everything fits together. But for a new user discovering it for the first time, that's a different story.</p>\n<p>These patterns show over and over again:</p>\n<ul>\n<li class=\"\">There's no clear starting point for new users.</li>\n<li class=\"\">Pages assume background knowledge users haven't picked up yet.</li>\n<li class=\"\">Critical steps get buried inside long, dense paragraphs.</li>\n<li class=\"\">Navigation reflects how the internal team thinks, not how users actually search for answers.</li>\n</ul>\n<p>The content itself might be technically correct, but if users can’t easily act on it, the documentation still fails them.</p>\n<p>Good documentation UX shows up in the little things users never have to think about like clear headings that guide their eyes, sections that unfold in a predictable order, and language that doesn't make them pause and re-read.</p>\n<p>The choice of words, tone, and sentence structure all shape how quickly users absorb information. Using short sentences helps users scan, familiar words lower the barrier to understanding, and the active voice makes the instructions easier to follow. Following these doesn’t mean you should dumb things down. It means you should be intentional as a writer.</p>\n<p>When it comes to structure, users don’t read documentation top to bottom. They jump in from a search result, scan for what they need, and move on. The pages in your documentation needs to support that kind of behaviour. Clear headings, predictable section order, and logical grouping let users locate content fast. Strong documentation UX comes from deliberate choices: deciding what users need first, what can wait, and what doesn't belong on the page at all.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-hidden-cost-of-poor-documentation-ux\">The Hidden Cost of Poor Documentation UX<a href=\"https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/#the-hidden-cost-of-poor-documentation-ux\" class=\"hash-link\" aria-label=\"Direct link to The Hidden Cost of Poor Documentation UX\" title=\"Direct link to The Hidden Cost of Poor Documentation UX\" translate=\"no\">​</a></h2>\n<p>When documentation UX is poor, the damage spreads quickly. Users will take longer to onboard, and you’ll have support tickets piling up with questions the docs should have answered. You’re losing trust in the documentation and pushing the users to other sources like Stack Overflow, community forums, or even worse, a competitor with better docs.</p>\n<p>Over time, users will not say “The documentation UX is bad”. They’ll frame it as:</p>\n<ul>\n<li class=\"\"><em>\"This is confusing.\"</em></li>\n<li class=\"\"><em>\"This tool is hard to use.\"</em></li>\n<li class=\"\"><em>\"I couldn't get it to work.\"</em></li>\n</ul>\n<p>Each of these statements makes it sound like the product has a problem. And in a way, it does because documentation is a product. This shapes how people feel about what you've built, whether they consciously realize it or not.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-to-start-improving-your-documentation-ux-today\">How to Start Improving Your Documentation UX Today<a href=\"https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/#how-to-start-improving-your-documentation-ux-today\" class=\"hash-link\" aria-label=\"Direct link to How to Start Improving Your Documentation UX Today\" title=\"Direct link to How to Start Improving Your Documentation UX Today\" translate=\"no\">​</a></h2>\n<p>You don't need a redesign, a new tool, or a bigger team to start making documentation UX better. Small, focused changes go a long way.</p>\n<ol>\n<li class=\"\"><strong>Watch a new user navigate the docs without guidance.</strong> Just observe and you’ll notice where they hesitate, where they click, and where they give up. This alone will reveal more than any internal review.</li>\n<li class=\"\"><strong>Review your landing pages and entry points.</strong> These are the first things users see. If they don't immediately communicate \"here's where to start,\" you're already losing them.</li>\n<li class=\"\"><strong>Rewrite one confusing section with clarity in mind.</strong> Pick the page that generates the most support questions and rework it. Focus on plain language, logical order, and remove assumptions.</li>\n<li class=\"\"><strong>Audit your headings and page flow for scannability.</strong> Read just the headings on a page. Ask yourself if they tell a coherent story and if someone scanning them will understand what the page covers and find what they need. Then make changes based on those findings.</li>\n</ol>\n<p>When you apply small changes like these over time, there’ll be a noticeable difference in how users experience your documentation and your product.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"final-thoughts\">Final Thoughts<a href=\"https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/#final-thoughts\" class=\"hash-link\" aria-label=\"Direct link to Final Thoughts\" title=\"Direct link to Final Thoughts\" translate=\"no\">​</a></h2>\n<p>Documentation is part of your product experience. Treating it that way through thoughtful UX, clear writing, and intentional structure changes how people interact with everything you build. And once you start seeing your docs through a UX lens, you won't want to go back.</p>",
            "url": "https://faithwachukwu.com/blog/documentation-ux-and-why-matters-more-than-accurate-content-alone/",
            "title": "Documentation UX: Why It Matters More Than Accurate Content Alone",
            "summary": "When a user lands on your documentation, they’re looking for answers. If they hit a wall of text with no starting point or see steps that assume knowledge they don’t have yet. Within minutes, they’ll be frustrated and say it's a bad product.",
            "date_modified": "2026-04-13T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "Documentation UX",
                "documentation",
                "technical writing"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/cli-tool.png\" alt=\"I Built a CLI Tool That Writes Changelogs For You — Here's Why\">\n<p>As a developer, writing changelogs can be a boring task. You already did the work, wrote the code, the commit messages, and shipped the feature. Now you’d need to go through all the commits for a release to create a changelog. This can be a lot.<br>\n<!-- -->With this in mind, I created a Python CLI tool that reads your git history and uses AI to generate a clean and publish-ready changelog with one command and one file. Here’s the thinking behind it.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-real-problem-of-translation\">The Real Problem of Translation<a href=\"https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/#the-real-problem-of-translation\" class=\"hash-link\" aria-label=\"Direct link to The Real Problem of Translation\" title=\"Direct link to The Real Problem of Translation\" translate=\"no\">​</a></h2>\n<p>Developers write commit messages when creating a pull request to close out tasks they are assigned. They’d create commit messages like: <code>fix: resolve edge case in auth token refresh</code> or <code>chore: bump deps</code>. This is useful for context in git blame, but useless to a user reading release notes.</p>\n<p>A good changelog translates those commit messages into something a user actually cares about. Like <code>Fixed a bug where login sessions expired unexpectedly</code> can be easily understood by the user than <code>Fix: token refresh edge case.</code></p>\n<p>The step where these messages are translated is where teams give up. It takes correct judgement, context, and effort for a changelog not to feel like an afterthought.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-a-cli-tool-and-not-a-web-app\">Why a CLI Tool and Not a Web App<a href=\"https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/#why-a-cli-tool-and-not-a-web-app\" class=\"hash-link\" aria-label=\"Direct link to Why a CLI Tool and Not a Web App\" title=\"Direct link to Why a CLI Tool and Not a Web App\" translate=\"no\">​</a></h2>\n<p>I wanted this CLI tool to fit into existing workflows and not replace them entirely. Developers live in the terminal, so it should be easy to use the tool there. As a developer, you’ll simply run the command in your terminal, which reads your git history, sends the commits to an LLM, and saves a formatted changelog.</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">python changelog</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">.</span><span class=\"token plain\">py </span><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token plain\">repo </span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">.</span><span class=\"token operator\">/</span><span class=\"token plain\">my</span><span class=\"token operator\">-</span><span class=\"token plain\">project </span><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token plain\">version </span><span class=\"token number\">1.1</span><span class=\"token number\">.0</span><span class=\"token plain\"> </span><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token plain\">output CHANGELOG</span><span class=\"token punctuation\" style=\"color:rgb(248, 248, 242)\">.</span><span class=\"token plain\">md</span><br></div></code></pre></div></div>\n<p>I tested it out on a GitHub Repository I found online called <a href=\"https://github.com/microsoft/VibeVoice\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Vibevoice</a>:</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/changelog2.png\" alt=\"The python changelog script run in a terminal.\"></div>\n<p>This created a <code>CHANGELOG.md</code> file in the project directory that looked like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#F8F8F2;--prism-background-color:#282A36\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"color:#F8F8F2;background-color:#282A36\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">## [v1.0.0] - 2026-03-30</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">**Added**</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Gradio ASR demo with video support, including demo audio/video files and Cloudflare tunnel integration. (09ca114f)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Data parallel (DP) support to the vLLM server launcher, allowing for multiple GPU replicas with automatic load balancing. (9634518c)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Tensor parallel (TP) support to the vLLM server launcher. (9634518c)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Announcement regarding VibeVoice ASR integration into Transformers v5.3.0, with a link to the Hugging Face release page. (7e73beec)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">**Changed**</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Nginx worker processes are now set to 2x DP replicas for optimal HTTP throughput, rather than defaulting to 'auto'. (cd945395)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Implemented nginx-based data parallelism for improved ASR throughput, utilizing a reverse proxy to avoid single-process HTTP bottlenecks. (3817f74d)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Per-worker environment variables in DP mode are now auto-tuned, ensuring correct settings are passed to each worker subprocess. (e6b65abb)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">**Fixed**</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Resolved GPU Out-of-Memory (OOM) errors by restoring sequential encoder usage, as the batch encoder caused memory issues under heavy load. (5cd81bb4)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">**Documentation**</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Added Vibing download links. (c766f12e)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Added Vibing demo video to the news section. (8f133837)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Corrected bold formatting in the news section. (0857b6d5)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Added news about Vibing voice input adoption. (c8371b6b)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Added the Trendshift #1 trending badge to the README. (b691f991)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\">- Updated documentation for multi-GPU deployment configurations, including DP, TP, and hybrid setups. (9634518c)</span><br></div><div class=\"token-line\" style=\"color:#F8F8F2\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div></code></pre></div></div>\n<p>With this, you have your changelog file ready.\nThis also works with a CI/CD pipeline. I included a GitHub Actions workflow in the project README so you can auto-generate changelogs on every release.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"choosing-the-ai-provider\">Choosing the AI Provider<a href=\"https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/#choosing-the-ai-provider\" class=\"hash-link\" aria-label=\"Direct link to Choosing the AI Provider\" title=\"Direct link to Choosing the AI Provider\" translate=\"no\">​</a></h2>\n<p>When it came to choosing an AI provider, I started with Anthropic’s Claude API because I was already familiar with it. Claude produces excellent results, follows instructions well and respects the formatting constraints.</p>\n<p>Then I hit a problem with it: the Anthropic API requires a paid key. For a tool that runs maybe once or twice per release cycle, that looked excessive.</p>\n<p>So I added Google Gemini as the default provider. Its free tier gives a good amount of requests per day.\nWith that, the tool supports both Gemini by default and Claude with a <code>–provider claude</code> flag.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-prompt-is-the-product\">The Prompt Is the Product<a href=\"https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/#the-prompt-is-the-product\" class=\"hash-link\" aria-label=\"Direct link to The Prompt Is the Product\" title=\"Direct link to The Prompt Is the Product\" translate=\"no\">​</a></h2>\n<p>The interesting part of this project is the prompt. The LLM need to do several things consistently: group commits by type (Added, Changed, Fixed, Security, etc.), rewrite these commit messages into user-friendly descriptions, drop noise like merge commits and typo fixes, keep commit hashes to make it easy to trace, and follow the <a href=\"https://keepachangelog.com/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Keep a Changelog format</a> without deviating from it.</p>\n<p>Getting all of this right took iteration.\nThe prompt lives in a <code>build_prompt()</code> function in the script, so you can customize it. The prompt is the part you can tweak to suit your needs.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-working-on-this-project-taught-me\">What Working on this Project Taught me<a href=\"https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/#what-working-on-this-project-taught-me\" class=\"hash-link\" aria-label=\"Direct link to What Working on this Project Taught me\" title=\"Direct link to What Working on this Project Taught me\" translate=\"no\">​</a></h2>\n<p>Building this reinforced something I keep telling people: <strong>prompt engineering is part of documentation engineering</strong>. The prompt I wrote for this tool is basically a style guide for the changelog. It tells the LLM what voice to use, how to structure content, what to include, and what to leave out. That's exactly what a documentation style guide does for human writers.</p>\n<p>If you're a technical writer wondering how AI fits into your career, this is the answer. You're not being replaced. You're being promoted from writing every word to designing the systems that generate them.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"try-it-yourself\">Try It Yourself<a href=\"https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/#try-it-yourself\" class=\"hash-link\" aria-label=\"Direct link to Try It Yourself\" title=\"Direct link to Try It Yourself\" translate=\"no\">​</a></h2>\n<p>The project is open source. Clone it, point it at any git repo, and see what it produces.</p>\n<p>GitHub: <a href=\"https://github.com/FaithKovi/changelog-generator\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/FaithKovi/changelog-generator</a></p>\n<p>It takes a few minutes to set up; the README walks you through every step. If you build something with it or find a bug, open an issue. I'd love to hear how other teams are handling their changelog workflows.</p>",
            "url": "https://faithwachukwu.com/blog/i-built-a-cli-tool-that-writes-changelogs-for-you/",
            "title": "I Built a CLI Tool That Writes Changelogs For You — Here's Why",
            "summary": "As a developer, writing changelogs can be a boring task. You already did the work, wrote the code, the commit messages, and shipped the feature. Now you’d need to go through all the commits for a release to create a changelog. This can be a lot.",
            "date_modified": "2026-04-01T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "changelog automation",
                "LLM",
                "AI tools for developers",
                "technical writing",
                "prompt engineering",
                "documentation engineering",
                "Google Gemini API",
                "LLM developer tools",
                "Keep a Changelog",
                "CI/CD automation"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/cover-docs-humans-ai.png\" alt=\"A hand-drawn style illustration showing a document in the center with two readers: a stick-figure human on the left reading the document from top to bottom, and a boxy robot on the right reaching in to grab a single highlighted chunk. Text reads: Your docs now have two readers. Write for both, compromise on neither.\">\n<p>Your documentation has a new reader with no eyes. AI tools like the chatbots, IDE assistants, and <strong>Retrieval-Augmented Generation (RAG)</strong> systems now stand between your docs and the engineer who needs them. These tools chop your pages into chunks, search for relevant matches, and then generate their responses.</p>\n<p>That means your documentation now serve two audiences: the person trying to solve a problem, and the machine trying to extract the right answer. In this post, you’ll learn how to write documentation that serves both the human and the AI retrieval systems.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-structure-matters-in-documentation\">Why Structure Matters in Documentation<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#why-structure-matters-in-documentation\" class=\"hash-link\" aria-label=\"Direct link to Why Structure Matters in Documentation\" title=\"Direct link to Why Structure Matters in Documentation\" translate=\"no\">​</a></h2>\n<p>Human and AI retrieval systems function differently during information retrieval. A human can open a page with badly structured content, scan and find the specific information they came for. But for AI retrieval systems, if the information it’s looking for is in a different heading other than the heading it came for, it retrieves the wrong information. This impacts the quality of the output.</p>\n<p>This kind of documentation was written for linear reading, and these AI retrieval systems don’t work that way. Even for a human, that’s bad structure. This is why it's important to be deliberate about where answers to questions live in documentation.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/excalidraw1.png\" alt=\"A flowchart showing how a RAG system processes documentation: a full document is split into smaller chunks, each chunk is converted into a vector embedding, a user query triggers a similarity search across those embeddings, and the most relevant chunk is fed into a language model to generate a response.\"><p><em>How RAG systems process your documentation: chunk, search, generate. The quality of the output depends on how well each chunk stands on its own.</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-each-reader-actually-needs\">What Each Reader Actually Needs<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#what-each-reader-actually-needs\" class=\"hash-link\" aria-label=\"Direct link to What Each Reader Actually Needs\" title=\"Direct link to What Each Reader Actually Needs\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-human-reader\">The Human Reader<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#the-human-reader\" class=\"hash-link\" aria-label=\"Direct link to The Human Reader\" title=\"Direct link to The Human Reader\" translate=\"no\">​</a></h3>\n<p>When a reader opens a documentation page, they have a problem they want to solve. In doing that, they don’t want to read more than they have to. They need enough context to solve their problem.</p>\n<p>Good documentation should explain ideas that build on each other. With headings, spacing, and code blocks in place, the mental effort needed to parse information is reduced. The <a href=\"https://www.nngroup.com/articles/inverted-pyramid/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Nielsen Norman Group's research on the inverted pyramid</a> confirms what most tech writers already feel: people scan first and read second. They want to understand the core idea before the deep implementation.</p>\n<p>This principle is called <strong>progressive disclosure</strong>. You start with the simplest version of the explanation and gradually layer the complex parts. This reflects how people actually learn.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-machine-reader\">The Machine Reader<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#the-machine-reader\" class=\"hash-link\" aria-label=\"Direct link to The Machine Reader\" title=\"Direct link to The Machine Reader\" translate=\"no\">​</a></h3>\n<p>For the chatbot or RAG tool, it’s a different ball game. It doesn’t start at the top and build understanding. It breaks your page into chunks, searches for the most relevant match to the query, and uses what it finds to generate a response. This means each section has to stand on its own. If a section depends on a context from three sections earlier, the retrieval system will respond without it, and the reader gets an incomplete answer.</p>\n<p>RAG systems perform better when they receive self-sufficient sections with clear headings and consistent metadata that indicate what each page covers.</p>\n<p>An example is an engineer asking an AI assistant: <em>“How do I roll back a failed deployment on Y?”</em></p>\n<p>Consider these two versions of the documentation:</p>\n<blockquote>\n<p><strong>Version A</strong> — Page title: Release Workflow. Section heading: Post-deployment considerations.</p>\n<p><strong>Version B</strong> — Page title: Roll back a failed deployment. Section heading: How to roll back a deployment. Tags: deployment, rollback, &gt;incident response.</p>\n</blockquote>\n<p>Version B makes it easy for both humans and machines to find the right answer.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/comparison1.png\" alt=\"A side-by-side comparison of two reading styles. On the left, a human reads a document sequentially from the first paragraph to the last. On the right, a retrieval system skips directly to a single section that matches the search query, ignoring everything else on the page.\"><p><em>Same document, two completely different reading patterns. One reads linearly. The other grabs and runs.</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-the-two-readers-clash\">Where the Two Readers Clash<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#where-the-two-readers-clash\" class=\"hash-link\" aria-label=\"Direct link to Where the Two Readers Clash\" title=\"Direct link to Where the Two Readers Clash\" translate=\"no\">​</a></h2>\n<p>Some best practices for human readers aren’t for AI retrieval systems. An example is progressive disclosure. Humans benefit from getting the context before the answer, and this feels natural. It’s like getting a good explanation from a colleague. But with AI retrieval systems, it doesn’t care about your buildup. It wants the answer straight up. If you lead with context and bury the solution four paragraphs down in an unrelated heading, the system would grab the preamble and miss the instructions.</p>\n<p>Let’s say you’ve written a section on <em>\"configuring retry policies\"</em>. A human reader would benefit from the first paragraph explaining why the retry policies matter. But for an AI retrieval system, it just needs: \"<code>Set maxRetries</code> to <code>3</code> and <code>backoffMultiplier</code> to <code>2.9</code> in your service config.” Looking at that, both readers need that information, but in a different order.</p>\n<p>To make it serve them both, restructure each section so the answer comes first, followed by the context. Journalists have done this for over a century, and it’s called the <a href=\"https://owl.purdue.edu/owl/subject_specific_writing/journalism_and_journalistic_writing/the_inverted_pyramid.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">inverted pyramid</a>. The machine gets its clean answer while the human gets their narrative.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"five-structural-rules-that-serve-both-readers\">Five Structural Rules That Serve Both Readers<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#five-structural-rules-that-serve-both-readers\" class=\"hash-link\" aria-label=\"Direct link to Five Structural Rules That Serve Both Readers\" title=\"Direct link to Five Structural Rules That Serve Both Readers\" translate=\"no\">​</a></h2>\n<p>You don’t need to rewrite everything. You should make these changes:</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-every-section-should-answer-one-specific-question\">1. Every Section Should Answer One Specific Question<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#1-every-section-should-answer-one-specific-question\" class=\"hash-link\" aria-label=\"Direct link to 1. Every Section Should Answer One Specific Question\" title=\"Direct link to 1. Every Section Should Answer One Specific Question\" translate=\"no\">​</a></h4>\n<p>Before you write any section, ask yourself: <em>“What question is this section answering?”</em><br>\n<!-- -->Then drive at answering that question.\nWhen a section answers one question, the human readers can scan the table of contents and jump straight to what they need. The same goes for the AI retrieval system; it can match the section directly to the query without parsing unnecessary information.</p>\n<p>The <a href=\"https://diataxis.fr/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Diátaxis framework</a> applies a similar principle at the page level, separating documentation into tutorials, how-to guides, reference, and explanation. This idea scales down to individual sections, too.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/diataxis.png\" alt=\"Diataxis framework\"><p><em>The Diátaxis Framework</em></p></div>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-write-headings-like-search-queries\">2. Write Headings Like Search Queries<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#2-write-headings-like-search-queries\" class=\"hash-link\" aria-label=\"Direct link to 2. Write Headings Like Search Queries\" title=\"Direct link to 2. Write Headings Like Search Queries\" translate=\"no\">​</a></h4>\n<p>Writing vague headings forces the reader to open the section and scan through to decide if it’s relevant or not. They also make it nearly impossible for an AI retrieval system to match the section to a query.</p>\n<p>The  <a href=\"https://developers.google.com/style/headings\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Google developer documentation style</a> guide recommends the use of task-based headings that describe what the reader will accomplish. This serves the AI retrieval systems just as well.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-open-every-section-with-the-answer\">3. Open Every Section with the Answer<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#3-open-every-section-with-the-answer\" class=\"hash-link\" aria-label=\"Direct link to 3. Open Every Section with the Answer\" title=\"Direct link to 3. Open Every Section with the Answer\" translate=\"no\">​</a></h4>\n<p>Opening every section with the answer is a high-impact change you can make. It’ll feel wrong at first, but for documentation, you aim to solve a problem and not write too much prose as you’d do in a novel.</p>\n<p>Open with the key ideas in the first sentence, then use the rest of the section to explain and give more context with examples. Your answer is now at the frontline. The human reader immediately knows they’re in the right place, and the AI retrieval system has the correct answer in the first chunk it grabs. This mirrors the <a href=\"https://www.nngroup.com/articles/inverted-pyramid/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">inverted pyramid</a> structure that's been the backbone of news writing since the telegraph era.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-make-every-code-example-self-contained\">4. Make Every Code Example Self-Contained<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#4-make-every-code-example-self-contained\" class=\"hash-link\" aria-label=\"Direct link to 4. Make Every Code Example Self-Contained\" title=\"Direct link to 4. Make Every Code Example Self-Contained\" translate=\"no\">​</a></h4>\n<p>Using phrases like “as configured in the previous section” might not work for AI retrieval systems. When adding code examples, include everything needed to understand or run the example right there, like the import statements, variable definitions, and configuration values. Yes, looks like repetition, but it’s worthwhile.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"5-write-metadata-like-youre-the-one-searching\">5. Write Metadata Like You're the One Searching<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#5-write-metadata-like-youre-the-one-searching\" class=\"hash-link\" aria-label=\"Direct link to 5. Write Metadata Like You're the One Searching\" title=\"Direct link to 5. Write Metadata Like You're the One Searching\" translate=\"no\">​</a></h4>\n<p>Metadata is the first thing search systems and AI retrieval systems use to decide whether your page is relevant. You could structure every section well, but none of it matters if readers can’t find your page in the first place. Metadata is what gets your documentation into the room.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"before-and-after\">Before and After<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#before-and-after\" class=\"hash-link\" aria-label=\"Direct link to Before and After\" title=\"Direct link to Before and After\" translate=\"no\">​</a></h2>\n<p>Here's the same documentation written two ways.</p>\n<p>Before (traditional narrative structure):</p>\n<blockquote>\n<h5 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"working-with-retry-policies\">Working with Retry Policies<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#working-with-retry-policies\" class=\"hash-link\" aria-label=\"Direct link to Working with Retry Policies\" title=\"Direct link to Working with Retry Policies\" translate=\"no\">​</a></h5>\n<p>Retry policies are an important part of building resilient services. When a request fails due to a transient error, such as a network timeout or a temporary service outage, a retry policy determines whether and how the system attempts the request again.</p>\n<p>There are several factors to consider when configuring retries, including the maximum number of attempts, the delay between attempts, and whether to use exponential backoff.</p>\n<p>To configure a retry policy, set <code>maxRetries</code> to 3 and <code>backoffMultiplier</code> to 2.0 in your service configuration file.</p>\n</blockquote>\n<p>A retrieval system grabbing the first paragraph gets a general explanation with zero actionable content. The actual instruction is buried at the bottom.</p>\n<p>After (structured for both readers):</p>\n<blockquote>\n<h5 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-to-configure-a-retry-policy-for-transient-failures\">How to Configure a Retry Policy for Transient Failures<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#how-to-configure-a-retry-policy-for-transient-failures\" class=\"hash-link\" aria-label=\"Direct link to How to Configure a Retry Policy for Transient Failures\" title=\"Direct link to How to Configure a Retry Policy for Transient Failures\" translate=\"no\">​</a></h5>\n<p>Set <code>maxRetries</code> to 3 and <code>backoffMultiplier</code> to 2.0 in your service configuration file. This ensures failed requests are retried with increasing delays, preventing cascading failures.</p>\n<p>Retry policies handle transient errors like network timeouts and temporary outages. Without them, a single failed request surfaces as a user-facing error even when the issue resolves in milliseconds. Exponential backoff — doubling the wait between each retry — gives the downstream service time to recover without piling on additional load.</p>\n</blockquote>\n<p>This example shows they both have the same information and depth, except that in the second, the answer comes first. An AI retrieval system grabs the solution on the first pass. A human gets the answer immediately and reads on to understand why.</p>\n<p>Another example can be seen in this image below:</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/chatbot-bad-vs-good.png\" alt=\"Side-by-side comparison of two AI chatbot responses to the same question about rotating API keys. The left response, generated from poorly structured docs, gives a vague answer telling the user to refer to their security policy — the retrieval visualization below shows only two lines were grabbed from a conceptual overview. The right response, from well-structured docs, provides a direct answer with five numbered steps — the retrieval visualization shows nearly the entire chunk was useful because the answer was in the first sentence.\"><p><em>The difference between a useless chatbot response and a helpful one often comes down to where the answer sits in the section</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>To make your documentation fit for both human and AI retrieval systems, don’t overhaul everything at once. Pick your most visited page and start from there. Audit it against these five rules. Restructure it and watch whether the AI retrieval systems and engineers get better answers. Then do the next page. Teams that structure documentation for both the human and machine readers are building knowledge bases that actually scale.</p>",
            "url": "https://faithwachukwu.com/blog/how-to-write-documentation-for-both-humans-and-ai-retrieval-systems/",
            "title": "How to Write Documentation for Both Humans and AI Retrieval Systems",
            "summary": "Your documentation has a new reader with no eyes. AI tools like the chatbots, IDE assistants, and Retrieval-Augmented Generation (RAG) systems now stand between your docs and the engineer who needs them. These tools chop your pages into chunks, search for relevant matches, and then generate their responses.",
            "date_modified": "2026-03-26T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "technical-writing",
                "documentation",
                "AI",
                "RAG",
                "developer-experience",
                "content-strategy",
                "LLM"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/cover-writing-engineer.jpg\" alt=\"An engineer working in the dark.\">\n<p>You’re staring at internal documentation at 11 PM, trying to figure out why a deployment pipeline is failing, but it's incomplete. It looks like whoever wrote it stopped midway, like they got pulled into a meeting and never came back. Well, what matters now is that you’re stuck.</p>\n<p>As someone who has been in this situation, you should think differently when writing documentation about who you’re writing for and how they would feel with incomplete docs. In this post, you’ll learn how to approach documentation as an engineer.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"youre-not-writing-for-your-team\">You're Not Writing for Your Team<a href=\"https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/#youre-not-writing-for-your-team\" class=\"hash-link\" aria-label=\"Direct link to You're Not Writing for Your Team\" title=\"Direct link to You're Not Writing for Your Team\" translate=\"no\">​</a></h2>\n<p>When starting a new role or in your current role, you might think your colleagues might not need your docs. And yes, that’s right, they might not. I mean, they were in the same Slack threads and meetings. They were there when someone made a questionable decision on the infrastructure on a Friday.</p>\n<p>Your real audience is the person who is employed 18 months later, handed the workload and is told, “You own this now.” With no context, no Slack history, and no memory of what has happened previously that shaped how the systems work today. All they have is what was left behind.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-why-matters\">The \"Why\" Matters<a href=\"https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/#the-why-matters\" class=\"hash-link\" aria-label=\"Direct link to The &quot;Why&quot; Matters\" title=\"Direct link to The &quot;Why&quot; Matters\" translate=\"no\">​</a></h2>\n<p>Initially, at the start of my career in DevOps, I would document things I did by writing things clearly. Well, it became useless six months down the line when the steps had changed. I didn’t go back to update the document.</p>\n<p>Knowing the reason why decisions were made is important in documentation. Beyond writing out the steps of actions taken, you should know the context behind decisions to understand the why, instead of following what you don’t understand. This could be as simple as two sentences, not like a full-blown write-up, and it can save someone the time and financial cost due to a mistake.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"write-for-the-2-am-version-of-that-person\">Write for the 2 AM Version of That Person<a href=\"https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/#write-for-the-2-am-version-of-that-person\" class=\"hash-link\" aria-label=\"Direct link to Write for the 2 AM Version of That Person\" title=\"Direct link to Write for the 2 AM Version of That Person\" translate=\"no\">​</a></h2>\n<p>When you’re on call, you know there is a difference between reading documentation to find out how a tool works versus reading it when there is downtime, and you are getting pinged nonstop. At that moment, you’re a different reader. One who is not interested in how it was written, you just want answers fast. You’d want to know:</p>\n<ul>\n<li class=\"\">what does this service depend on?</li>\n<li class=\"\">what breaks when it goes down?</li>\n<li class=\"\">how do I restart it without making it worse?</li>\n</ul>\n<p>So when you’re structuring anything operational, keep that person in mind. Make sure you use short sentences, clear headings, and remove what would create doubt in their minds. If there’s a command they’ll need to run, include it, make it visible and easy to find and not buried deep into a paragraph section.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"treat-documentation-like-a-product\">Treat Documentation Like a Product<a href=\"https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/#treat-documentation-like-a-product\" class=\"hash-link\" aria-label=\"Direct link to Treat Documentation Like a Product\" title=\"Direct link to Treat Documentation Like a Product\" translate=\"no\">​</a></h2>\n<p>Treating your documentation as a product, not a side work, is a shift you should make. Think about it this way: if the person replacing you can’t understand the system from your documentation, then you haven’t finished working on that documentation.</p>\n<p>When you see documentation as a product that has users, a purpose, and a quality standard to follow, you start making different choices. You’ll think about the structure, what is important to add or leave out, and how to maintain it.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/writingEngineer2.png\" alt=\"A simple flowchart showing Documentation-Users-Feedback-Improvements.\"><p><em>A simple workflow diagram of documentation lifecycle</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-to-do-differently\">What To Do Differently<a href=\"https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/#what-to-do-differently\" class=\"hash-link\" aria-label=\"Direct link to What To Do Differently\" title=\"Direct link to What To Do Differently\" translate=\"no\">​</a></h2>\n<p>With the mindset of seeing documentation as a product, you’d document the state of things for every system you own. Mention what works well, what’s been held together by strings, and if there are potential risks in the systems.</p>\n<p>If you had to dig through 3 Jira tickets and a Slack thread to figure something out that is needed, then it’s a sign you should document it. The fact that it was hard to find means someone will face the same issue. It’s easier to revisit docs than to dig through Slack threads.</p>\n<p>In cases where there were recent additions or something was confusing in a runbook you own, correct it right then and not later. That’s because the next person who’ll read it won’t have context to know there is a problem. They’ll trust it blindly.</p>\n<p>Additionally, write like a human. Use “we” and “you” occasionally. When something is genuinely confusing, you’d say, “This is confusing, but here’s the deal”. Don’t pretend everything works perfectly when it doesn’t. Writing honestly in documentation helps to build trust, even with someone you’ll never meet.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>At the end, everything you’ll build, configure, or every shortcut you’ll take to implement things will be inherited by someone else. The quality of the documentation you leave behind says something about you as a professional.</p>\n<p>Leave brilliant documentation handoffs to the next person. Brilliant, not in the sense of perfect documentation, but documentation that is written with the next person in mind. Let it be written clearly with the necessary information. This leaves a trail that says, “I cared about whoever came after me.”</p>",
            "url": "https://faithwachukwu.com/blog/writing-for-the-engineer-who-will-replace-you/",
            "title": "Writing for the Engineer Who Will Replace You",
            "summary": "You’re staring at internal documentation at 11 PM, trying to figure out why a deployment pipeline is failing, but it's incomplete. It looks like whoever wrote it stopped midway, like they got pulled into a meeting and never came back. Well, what matters now is that you’re stuck.",
            "date_modified": "2026-03-09T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "devops",
                "docs"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/what-makes-api-documentation-work/",
            "content_html": "<img src=\"https://faithwachukwu.com/img/blog/apidocswork.jpg\" alt=\"What makes API documentation work?.\">\n<p>Some APIs can be easily understood from the moment you open their documentation, while others will leave you hovering from one page to another to get started. The key difference is rarely about the API but the quality of documentation created for it. By studying the documentation practices of companies like <a href=\"https://docs.stripe.com/api\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Stripe</a>, <a href=\"https://www.twilio.com/docs\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Twilio</a>, <a href=\"https://docs.github.com/en/rest?apiVersion=2022-11-28\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">GitHub</a>, <a href=\"https://developer.spotify.com/documentation/web-api\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Spotify</a>, and <a href=\"https://docs.x.com/x-api/introduction\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">X</a>, there are several characteristics that show up consistently. Let’s take a look at some of them.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"clear-getting-started-guides\">Clear getting started guides<a href=\"https://faithwachukwu.com/blog/what-makes-api-documentation-work/#clear-getting-started-guides\" class=\"hash-link\" aria-label=\"Direct link to Clear getting started guides\" title=\"Direct link to Clear getting started guides\" translate=\"no\">​</a></h2>\n<p>For developers, their experience in the first few minutes of opening the documentation shapes their outlook on the API. This often determines if they continue exploring how to use the API or move to a different alternative.</p>\n<p>In effective documentation, there is a clear path from account creation to making your first successful API request. The focus is on helping developers achieve their first win rather than pushing technical details in their faces.</p>\n<p><a href=\"https://docs.stripe.com/development\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Stripe</a>, for example, provides dedicated getting started resources, SDK installation instructions, testing guides, and integration tools that can help developers build things quickly.</p>\n<p>A clear getting started guide should answer the following questions immediately:</p>\n<ul>\n<li class=\"\">What does this API do?</li>\n<li class=\"\">How do I authenticate?</li>\n<li class=\"\">How do I make my first request?</li>\n<li class=\"\">What should I expect in the response?</li>\n</ul>\n<p>When developers find these answers within minutes, it becomes easier for them to adopt the API.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"practical-code-examples\">Practical code examples<a href=\"https://faithwachukwu.com/blog/what-makes-api-documentation-work/#practical-code-examples\" class=\"hash-link\" aria-label=\"Direct link to Practical code examples\" title=\"Direct link to Practical code examples\" translate=\"no\">​</a></h2>\n<p>For developers, they learn by doing. There is no amount of descriptive text that can replace a working code example. To create effective documentation, you should include examples that demonstrate real-world cases. The examples should be complete enough to copy, run, and modify.</p>\n<p>A good example is Twilio’s documentation that includes multi-language code examples to help developers understand how to implement across different environments.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/twilio-multilang.png\" alt=\"A multi-language code example in the Twilio API docs.\"><p><em>A multi-language code example in the Twilio API docs</em></p></div>\n<p>Good examples normally:</p>\n<ul>\n<li class=\"\">Use realistic data</li>\n<li class=\"\">Show complete requests and responses</li>\n<li class=\"\">Cover common workflows</li>\n<li class=\"\">Include error-handling examples</li>\n</ul>\n<p><a href=\"https://arxiv.org/abs/2102.08486\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Research on API documentation</a> has also shown that developers place significant value on practical usage scenarios and examples when learning about new APIs.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"comprehensive-api-references\">Comprehensive API references<a href=\"https://faithwachukwu.com/blog/what-makes-api-documentation-work/#comprehensive-api-references\" class=\"hash-link\" aria-label=\"Direct link to Comprehensive API references\" title=\"Direct link to Comprehensive API references\" translate=\"no\">​</a></h2>\n<p>In API documentation, guides help developers get started, but with references, they can build production applications.\nA good API reference should clearly document:</p>\n<ul>\n<li class=\"\">Endpoints</li>\n<li class=\"\">Parameters</li>\n<li class=\"\">Authentication requirements</li>\n<li class=\"\">Request formats</li>\n<li class=\"\">Response schemas</li>\n<li class=\"\">Status codes</li>\n<li class=\"\">Error messages</li>\n</ul>\n<p><a href=\"https://docs.stripe.com/api\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Stripe's API reference</a> is a strong example of this approach. It provides predictable resource structures, request formats, authentication guidance, testing information, and error-handling documentation in a consistent format.</p>\n<p>For these references, completeness matters because developers frequently rely on references while troubleshooting. When there are missing parameters or unclear error responses, it can lead to frustration.</p>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/stripe-error-page.png\" alt=\"Error codes page in Stripe API docs.\"><p><em>Error codes page in Stripe API docs</em></p></div>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"excellent-navigation-and-search\">Excellent navigation and search<a href=\"https://faithwachukwu.com/blog/what-makes-api-documentation-work/#excellent-navigation-and-search\" class=\"hash-link\" aria-label=\"Direct link to Excellent navigation and search\" title=\"Direct link to Excellent navigation and search\" translate=\"no\">​</a></h2>\n<p>Even with the best content, if developers cannot find it, it becomes ineffective. Your documentation should be organized around the user’s goals rather than how the internal product is structured. The navigation should make it easy to move between tutorials, guides, API references, troubleshooting resources, and changelogs.</p>\n<p>Developers can easily identify poor navigation in your documentation and weak search experiences.\nGood documentation sites should make it easy to answer questions such as:</p>\n<ul>\n<li class=\"\">How do I authenticate?</li>\n<li class=\"\">How do webhooks work?</li>\n<li class=\"\">What causes this error?</li>\n<li class=\"\">Has this endpoint changed recently?</li>\n</ul>\n<p>How quickly the developers can find the answers they are looking for leads to the likelihood of trusting the documentation.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"documentation-that-stays-current\">Documentation that stays current<a href=\"https://faithwachukwu.com/blog/what-makes-api-documentation-work/#documentation-that-stays-current\" class=\"hash-link\" aria-label=\"Direct link to Documentation that stays current\" title=\"Direct link to Documentation that stays current\" translate=\"no\">​</a></h2>\n<p>Documentation should be viewed as a product that requires continuous maintenance.</p>\n<p>Having outdated examples, deprecated SDK references, and inaccurate endpoint information will create confusion and increase support costs. Developers can judge how reliable an API is by the reliability of its documentation.</p>\n<p>Top API providers invest heavily in versioning, changelogs, and regular documentation updates. Stripe, for example, maintains versioning guidance, API upgrade documentation, and changelogs to help developers manage these changes over time. This means that maintaining documentation should be part of the development lifecycle.</p>\n<p>Using <a href=\"https://www.writethedocs.org/guide/docs-as-code/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">docs-as-code</a> practices, automated reviews, and implementing documentation ownership models can help teams keep content accurate as the product evolves.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://faithwachukwu.com/blog/what-makes-api-documentation-work/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>What makes API documentation work is its ability to help developers achieve their goals with minimal friction.\nGood documentation shares several characteristics: clear getting-started guides, practical examples, comprehensive references, excellent navigation, and consistent maintenance. Together, these characteristics transform the developer experience. When documentation helps the developers quickly, the API is easier to trust and adopt.</p>",
            "url": "https://faithwachukwu.com/blog/what-makes-api-documentation-work/",
            "title": "What Makes API Documentation Work?",
            "summary": "Some APIs can be easily understood from the moment you open their documentation, while others will leave you hovering from one page to another to get started. The key difference is rarely about the API but the quality of documentation created for it. By studying the documentation practices of companies like Stripe, Twilio, GitHub, Spotify, and X, there are several characteristics that show up consistently. Let’s take a look at some of them.",
            "date_modified": "2025-10-15T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "API documentation",
                "docs",
                "API",
                "technicalwriting"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/",
            "content_html": "<p>DevOps teams love talking about automation, observability, infrastructure as code, and deployment speed. But what usually determines whether systems survive incidents, handoffs, or employee exits is <strong>accurate documentation</strong>.</p>\n<p>For teams to ship reliably, they need up-to-date runbooks, READMEs, and architecture docs. In this post, you’ll learn why documentation is <strong>non-negotiable</strong> in DevOps, the types of documentation in DevOps, best practices and common challenges, and how to overcome them. Let’s dive right in.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-documentation-matters-in-devops\">Why documentation matters in DevOps<a href=\"https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/#why-documentation-matters-in-devops\" class=\"hash-link\" aria-label=\"Direct link to Why documentation matters in DevOps\" title=\"Direct link to Why documentation matters in DevOps\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">\n<p><strong>Bridging Communication Gaps</strong><br>\n<!-- -->DevOps is about collaboration, but let’s be honest, there is a high chance that miscommunication can happen. When there is no proper documentation, tribal knowledge becomes the go-to for information, and teams end up wasting time trying to figure out processes instead of executing them.\nHaving well-documented deployment workflows removes guesswork and ensures everyone stays on the same page. So instead of relying on Slack messages and word-of-mouth explanations, teams can refer to a <a href=\"https://en.wikipedia.org/wiki/Single_source_of_truth\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">single source of truth</a> to prevent errors.</p>\n</li>\n<li class=\"\">\n<p><strong>Building Faster Onboarding and Stronger Knowledge Sharing</strong><br>\n<!-- -->For new team members, having a smooth transition into the team’s workflow is a huge task. Imagine having to rely on scattered notes or having endless back-and-forths with team members just to understand better how things are done. It would have been easier and faster if there were runbooks, workflow guides and system overviews readily available for new team members.<br>\n<!-- -->With this, the dependency on senior engineers for answers reduces. Think of documentation as a self-serve knowledge base. When it is done right, it helps teams operate efficiently.</p>\n</li>\n<li class=\"\">\n<p><strong>Enabling automation and standardization</strong><br>\n<!-- -->DevOps thrives on automation, from CI/CD pipelines to infrastructure as code (IaC). Let’s be real, having automation in place without documentation is like chaos waiting to happen.<br>\n<!-- -->When scripts, configurations, and processes are documented, teams can:</p>\n<ul>\n<li class=\"\">Maintain consistency across environments</li>\n<li class=\"\">Reduce human errors</li>\n<li class=\"\">Debug issues faster</li>\n</ul>\n</li>\n</ul>\n<p>For example, when you document <strong>Terraform modules</strong> or <strong>Ansible playbooks</strong>, everyone who comes across the document will get information to help them understand the infrastructure setup rather than blindly running scripts.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"types-of-documentation-in-devops\">Types of Documentation in DevOps<a href=\"https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/#types-of-documentation-in-devops\" class=\"hash-link\" aria-label=\"Direct link to Types of Documentation in DevOps\" title=\"Direct link to Types of Documentation in DevOps\" translate=\"no\">​</a></h2>\n<p>An effective DevOps documentation cuts across various categories such as:</p>\n<ul>\n<li class=\"\"><strong>Process Documentation</strong>: Guides for deployment workflows, incident response playbooks, and escalation procedures.</li>\n<li class=\"\"><strong>Technical Documentation</strong>: API documentation, infrastructure diagrams, and IaC scripts like Terraform or Ansible.</li>\n<li class=\"\"><strong>Knowledge Bases</strong>: Centralised platforms (e.g., Confluence, Notion) for team knowledge sharing.</li>\n<li class=\"\"><strong>Runbooks</strong>: Step-by-step troubleshooting guides for common incidents or outages.</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"best-practices-for-writing-effective-devops-documentation\">Best Practices for Writing Effective DevOps Documentation<a href=\"https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/#best-practices-for-writing-effective-devops-documentation\" class=\"hash-link\" aria-label=\"Direct link to Best Practices for Writing Effective DevOps Documentation\" title=\"Direct link to Best Practices for Writing Effective DevOps Documentation\" translate=\"no\">​</a></h2>\n<p>When creating documentation, ensure the information you add is useful and practical. Here are some best practices to keep in mind:</p>\n<ol>\n<li class=\"\"><strong>Keep it clear and simple</strong><br>\n<!-- -->Make sure you use plain language, avoid jargon where possible, and structure your content logically. A good way to judge if your documentation is actually helpful is to ask a new team member to follow it and see if they can without asking for clarification.</li>\n<li class=\"\"><strong>Make it a team effort</strong><br>\n<!-- -->When it comes to documentation, it’s not a one-person job. To encourage collaborative contributions, integrate documentation updates into pull requests, sprint retrospectives, or post-mortems.</li>\n<li class=\"\"><strong>Maintain Up-to-Date Docs</strong><br>\n<!-- -->Having outdated documentation is almost as bad as having no documentation. For specific documents, you should assign ownership and conduct regular reviews, and use version control (e.g., Git) to track changes.</li>\n<li class=\"\"><strong>Create a standard for documentation format</strong><br>\n<!-- -->Use templates to ensure consistency across teams. Markdown, AsciiDoc, or structured formats like OpenAPI (for APIs) help maintain clarity.</li>\n</ol>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tools-and-techniques-for-managing-documentation\">Tools and Techniques for Managing Documentation<a href=\"https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/#tools-and-techniques-for-managing-documentation\" class=\"hash-link\" aria-label=\"Direct link to Tools and Techniques for Managing Documentation\" title=\"Direct link to Tools and Techniques for Managing Documentation\" translate=\"no\">​</a></h2>\n<p>To make documentation easier to create and maintain, DevOps teams can use:</p>\n<ol>\n<li class=\"\">\n<p><strong>Version Control for Documentation</strong></p>\n<ul>\n<li class=\"\">Store documentation in Git repositories to track changes and collaborate efficiently.</li>\n<li class=\"\">Use tools like <a href=\"https://www.mkdocs.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">MkDocs</a> or <a href=\"https://docusaurus.io/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Docusaurus</a> to help generate documentation from Markdown files.</li>\n</ul>\n</li>\n<li class=\"\">\n<p><strong>Documentation Platforms</strong></p>\n<ul>\n<li class=\"\"><a href=\"https://www.atlassian.com/software/confluence\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Confluence</a>, <a href=\"https://www.notion.com/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Notion</a>, or <a href=\"https://www.gitbook.com/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">GitBook</a> provide structured and visually appealing documentation spaces.</li>\n<li class=\"\"><a href=\"https://swagger.io/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Swagger</a> (OpenAPI) auto-generates API documentation.</li>\n</ul>\n</li>\n<li class=\"\">\n<p><strong>Automation for Documentation Updates</strong></p>\n<ul>\n<li class=\"\">Integrate documentation updates into CI/CD pipelines to keep them aligned with your deployments.</li>\n<li class=\"\">Use tools like <a href=\"https://terraform-docs.io/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">terraform-docs</a> to auto-generate Terraform module documentation.</li>\n</ul>\n</li>\n</ol>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"overcoming-common-challenges\">Overcoming Common Challenges<a href=\"https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/#overcoming-common-challenges\" class=\"hash-link\" aria-label=\"Direct link to Overcoming Common Challenges\" title=\"Direct link to Overcoming Common Challenges\" translate=\"no\">​</a></h2>\n<p>Teams often face challenges that affect accuracy, consistency, collaboration, and long-term maintainability. Here are a few that are common:</p>\n<ol>\n<li class=\"\">\n<p><strong>“We don’t have time for documentation.”</strong>\nTo solve this, you have to make documentation a part of the workflow rather than waiting till the end. Ask for updates during sprint reviews or integrate them into pull requests.</p>\n</li>\n<li class=\"\">\n<p><strong>“Documentation is inconsistent across teams.”</strong>\nMake sure you establish clear documentation standards and templates that teams can follow. This ensures consistency across all documentation.</p>\n</li>\n<li class=\"\">\n<p><strong>“Keeping documentation updated is hard.”</strong>\nYou should assign ownership for key documents, track them, set review cycles to ensure they stay relevant, and automate updates where possible.</p>\n</li>\n</ol>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>When it comes to documentation in DevOps, you shouldn’t treat it like an afterthought. It’s a core part of DevOps success. From bridging the communication gaps to enabling knowledge sharing, having good documentation helps drive efficiency and prevent costly mistakes.\nSo you should prioritize it in your workflows, keep it up-to-date, and you’d see how this improves your DevOps processes.</p>",
            "url": "https://faithwachukwu.com/blog/docs-and-deployments-the-power-of-clear-documentation-in-devops/",
            "title": "Docs and Deployments: The Power of Clear Documentation in DevOps",
            "summary": "DevOps teams love talking about automation, observability, infrastructure as code, and deployment speed. But what usually determines whether systems survive incidents, handoffs, or employee exits is accurate documentation.",
            "date_modified": "2025-06-23T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "devops",
                "docs",
                "docs as code",
                "documentation"
            ]
        },
        {
            "id": "https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/",
            "content_html": "<p>Let’s be honest, working on documentation can feel overwhelming. It’s easy to feel stuck when you’re staring at a blank page, or you’re trying to clean up existing content. That’s where <a href=\"https://diataxis.fr/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Diátaxis</a> comes in. </p>\n<p>Instead of following the pattern of following rigid rules and overwhelming plans. Diataxis offers you a refreshing approach: take things one step at a time, let the structure emerge naturally, focus on making small, meaningful improvements. The best part is that you don’t need to fully understand it before diving right into it. With Diátaxis, you learn by doing, taking small, meaningful steps to transform your docs into something clear.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"diátaxis-a-guide-not-a-plan\">Diátaxis: A Guide, Not a Plan<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#di%C3%A1taxis-a-guide-not-a-plan\" class=\"hash-link\" aria-label=\"Direct link to Diátaxis: A Guide, Not a Plan\" title=\"Direct link to Diátaxis: A Guide, Not a Plan\" translate=\"no\">​</a></h2>\n<p>Diátaxis, at its core, offers a complete picture of documentation without imposing rules that are too rigid. It’s more like a guide that helps you understand where your documentation is and where it needs to go. Unlike following the traditional way of prioritizing extensive planning, Diátaxis advocates for adaptability and incremental progress.</p>\n<p>Diátaxis encourages writers to focus on small changes instead of striving for immediate perfection. Over time, with these improvements, the documentation shapes into more of a clear user-focused structure without forcing it into already predefined categories.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"avoid-top-down-structures\">Avoid top-down structures<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#avoid-top-down-structures\" class=\"hash-link\" aria-label=\"Direct link to Avoid top-down structures\" title=\"Direct link to Avoid top-down structures\" translate=\"no\">​</a></h2>\n<p>When writing following the traditional writing process, it’s often emphasized that you should start with a clear structure: divide the content into tutorials, how-to guides, reference materials, and explanations.</p>\n<p>However, Diátaxis warns against this approach. Instead of creating empty sections for future content, which is counterproductive and frustrating, you should let the structure emerge naturally.</p>\n<p>This is done by addressing what the user needs at that specific time and improving the content piece by piece; then your documentation will organically align with the Diátaxis framework. This inside-out development makes sure the structure reflects well-formed content.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-power-of-small-steps\">The Power of Small Steps<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#the-power-of-small-steps\" class=\"hash-link\" aria-label=\"Direct link to The Power of Small Steps\" title=\"Direct link to The Power of Small Steps\" translate=\"no\">​</a></h2>\n<p>One of Diátaxis’ key principles is iterative improvement. Even if your documentation feels like an unmanageable mess, there’s always a way forward by taking it one small step at a time. Here’s how to apply this method:</p>\n<ol>\n<li class=\"\"><strong>Choose a starting point</strong>: Select any piece of documentation. It could be a page you last read or even a frequently referenced section. Don’t waste your time searching for the “perfect” starting point.</li>\n<li class=\"\"><strong>Assess it critically</strong>: After selecting, evaluate the selected content and ask yourself these questions:<!-- -->\n<ul>\n<li class=\"\">What user need does this address?</li>\n<li class=\"\">How effectively does it serve that need?</li>\n<li class=\"\">What changes could enhance its value?<br>\n<!-- -->Then consider how clear, logical, correct, and useful the content is.</li>\n</ul>\n</li>\n<li class=\"\"><strong>Make a decision</strong>: Once you’ve answered the questions above, identify one immediate action to take that will improve the content, whether it’s rewriting a sentence, adding an example, or clarifying instructions.</li>\n<li class=\"\"><strong>Execute and Publish</strong>: Simply implement the change and publish your content. It’s best to avoid the temptation of waiting until you’ve completed a larger part. Every small improvement counts.</li>\n<li class=\"\"><strong>Repeat</strong>: Repeat this process from step one and continue iterating.</li>\n</ol>\n<p>By using this approach, you’ve reduced decision paralysis and progressed steadily. This keeps your documentation consistently aligned with what your users need.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"organic-growth-a-living-system\">Organic Growth: A Living System<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#organic-growth-a-living-system\" class=\"hash-link\" aria-label=\"Direct link to Organic Growth: A Living System\" title=\"Direct link to Organic Growth: A Living System\" translate=\"no\">​</a></h2>\n<p>Diátaxis likens documentation to a living organism, emphasizing well-formed organic growth. Just as a plant develops from a healthy seed into a mature tree, documentation evolves through iterative improvements at the “cellular” level, these include individual paragraphs, sentences, or sections.</p>\n<p>When each component is carefully nurtured and improved, the overall structure emerges naturally, adapting to external conditions like user feedback and product updates. This type of growth fosters better, more resilient documentation.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"complete-not-finished\">Complete, Not Finished<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#complete-not-finished\" class=\"hash-link\" aria-label=\"Direct link to Complete, Not Finished\" title=\"Direct link to Complete, Not Finished\" translate=\"no\">​</a></h2>\n<p>A defining concept in Diátaxis is the difference between what is complete and what is finished. Documentation, like a living organism, is never truly finished because it must continuously evolve alongside the product and its users. However, it can always be completely useful, appropriate, and ready for its current stage of development.</p>\n<p>Imagine a plant at every stage of its life. From a seedling to a fully-grown tree, it is always complete in its own right, even as it continues to grow and mature. Documentation can follow the same principle: providing value to users at every stage while remaining open to future refinements.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-four-modes-of-documentation\">The Four Modes of Documentation<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#the-four-modes-of-documentation\" class=\"hash-link\" aria-label=\"Direct link to The Four Modes of Documentation\" title=\"Direct link to The Four Modes of Documentation\" translate=\"no\">​</a></h2>\n<div style=\"text-align:center\"><img src=\"https://faithwachukwu.com/img/blog/diataxis.png\" alt=\"Diataxis framework\"><p><em>Image of Diátaxis Framework</em></p></div>\n<p>Diátaxis framework groups documentation into four distinct modes, each of which serves a specific purpose:</p>\n<ul>\n<li class=\"\"><strong>Tutorials</strong>: Learning-oriented experiences that guide users through a process step by step.</li>\n<li class=\"\"><strong>How-to Guides</strong>: Goal-oriented instructions for accomplishing specific tasks.</li>\n<li class=\"\"><strong>Reference</strong>: Technical descriptions focused on providing precise, factual information.</li>\n<li class=\"\"><strong>Explanations</strong>: Understanding-oriented discussions that dive into the why and how of a topic.</li>\n</ul>\n<p>By iterating on your content with these modes in mind, your documentation will naturally take on a shape that serves the diverse user needs.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"navigating-common-challenges\">Navigating Common Challenges<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#navigating-common-challenges\" class=\"hash-link\" aria-label=\"Direct link to Navigating Common Challenges\" title=\"Direct link to Navigating Common Challenges\" translate=\"no\">​</a></h2>\n<p>Applying Diátaxis can feel counterintuitive at first, especially if you’re used to traditional documentation practices. Here are some practical tips to navigate common challenges:</p>\n<ul>\n<li class=\"\">If you’re overwhelmed by existing content, you should start small. Focus on one paragraph, page, or section at a time. No matter how incremental, progress is still progress.</li>\n<li class=\"\">If you’re tempted to restructure everything at a time, resist! By tearing down an entire documentation, you’ve already introduced unnecessary complexity. Instead, build on what you already have by improving it step by step.</li>\n<li class=\"\">If you’re struggling to define user needs, use the feedback from real users. Most of their questions and challenges can help guide you in deciding what your priorities are thereby ensuring your documentation addresses users needs.</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>Diátaxis transforms documentation from a complex task into a manageable, iterative process. By focusing on small, meaningful changes and allowing the structure to emerge organically, this approach empowers writers to produce user-centric, adaptable documentation. Whether starting from scratch or refining a chaotic documentation, Diátaxis offers the tools and principles to guide you toward clarity and success one step at a time.</p>\n<p>Understand that with documentation, it’s not just a deliverable. Rather you should see it as a dynamic and evolving process. With Diátaxis, you can embrace the process with confidence that every small step contributes to a clearer, more effective documentation.</p>",
            "url": "https://faithwachukwu.com/blog/how-diataxis-turns-documentation-chaos-into-clarity/",
            "title": "How Diátaxis Turns Documentation Chaos into Clarity",
            "summary": "Let’s be honest, working on documentation can feel overwhelming. It’s easy to feel stuck when you’re staring at a blank page, or you’re trying to clean up existing content. That’s where Diátaxis comes in.",
            "date_modified": "2025-01-08T00:00:00.000Z",
            "author": {
                "name": "Faith Wachukwu",
                "url": "https://faithkovi.xyz"
            },
            "tags": [
                "diataxis",
                "docs"
            ]
        }
    ]
}