<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://www.marlasowards.com/blog</id>
    <title>Marla Sowards Blog</title>
    <updated>2026-09-29T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://www.marlasowards.com/blog"/>
    <subtitle>Marla Sowards Blog</subtitle>
    <icon>https://www.marlasowards.com/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Build your own MCP server to hand off content management system tasks to an AI agent]]></title>
        <id>https://www.marlasowards.com/blog/build-mcps</id>
        <link href="https://www.marlasowards.com/blog/build-mcps"/>
        <updated>2026-09-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Have you ever worked with a CMS or CCMS that required lots of repetitive clicking through the UI to get things done? If the tool has a REST API, you can trade those clicks for natural language prompts by building an MCP (Model Context Protocol) server that's a simple API wrapper and use it with an AI agent skill. Here's how I did it using Claude to handle the coding.]]></summary>
        <content type="html"><![CDATA[<p>Have you ever worked with a CMS or CCMS that required <em>lots</em> of repetitive clicking through the UI to get things done? If the tool has a REST API, you can trade those clicks for natural language prompts by building an MCP (Model Context Protocol) server that's a simple API wrapper and use it with an AI agent skill. Here's how I did it using Claude to handle the coding.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="a-no-click-workflow">A no-click workflow<a href="https://www.marlasowards.com/blog/build-mcps#a-no-click-workflow" class="hash-link" aria-label="Direct link to A no-click workflow" title="Direct link to A no-click workflow" translate="no">​</a></h2>
<p>I once needed to add labels to dozens of articles at a time in a Zendesk help site to optimize search results. I was looking at hours of tedious clicks and entering terms.</p>
<p>The <a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/introduction/" target="_blank" rel="noopener noreferrer" class="">Zendesk Help Center REST API</a> gave me a better way. It offers these endpoints:</p>
<ul>
<li class=""><a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/article_labels/" target="_blank" rel="noopener noreferrer" class=""><code>/articles/{article_id}/labels</code></a>: List, add, or remove the labels on one article</li>
<li class=""><a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/article_labels/" target="_blank" rel="noopener noreferrer" class=""><code>/articles/labels</code></a>: List all labels or delete a label from every article</li>
<li class=""><a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/articles/" target="_blank" rel="noopener noreferrer" class=""><code>/articles</code></a>: List all articles and see each article's labels</li>
</ul>
<p>I wired up an MCP server (to call the API and authenticate) and a Claude skill (to trigger the calls). This let me prompt Claude to handle any tasks the API supports.</p>
<p><span class="zoomImage__wrap"><img alt="Flow diagram: your prompt goes to Claude (with the zendesk-guide-pal skill for rate limits and pagination rules), which makes tool calls to the Python MCP server (OAuth, pagination, confirm before changes), which sends API requests to the Zendesk Help Center REST API and returns JSON" src="https://www.marlasowards.com/assets/images/mcp-workflow-d3be0986dfcebf9487a49e7d497aff5f.png" width="1488" height="1200" class="zoomImage " loading="lazy"><span class="zoomImage__badge" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="7"></circle><path d="M21 21l-4.3-4.3"></path><path d="M11 8v6M8 11h6"></path></svg></span></span></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-the-mcp-server">Building the MCP server<a href="https://www.marlasowards.com/blog/build-mcps#building-the-mcp-server" class="hash-link" aria-label="Direct link to Building the MCP server" title="Direct link to Building the MCP server" translate="no">​</a></h2>
<p>To build the MCP server, I prompted Claude with something like this:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Build a Python MCP server for managing labels on Zendesk Help Center (Guide) articles. It should allow OAuth authentication (see https://developer.zendesk.com/documentation/authentication/api-tokens-to-oauth).</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">It should let me perform actions for:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Labels:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all labels in the Help Center</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- See how often each label is used, including labels that no article uses</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- See the labels on a specific article</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Find all articles that have a given label, with each article's title, URL, section and category</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Find articles that have no labels</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Add or remove labels by name, on one article or many at once</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Delete labels I no longer need, one at a time or in bulk</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Articles:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all articles, or only the articles in one section</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Get a specific article, including its full HTML body</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Search articles by keyword, with optional filters for section, label and locale, and sorting</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Return search results with each article's title, URL, section and category</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Creating and updating articles:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Create an article in a section, with a title, HTML body, locale and draft status (draft by default)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Update an article's body or title</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Requirements:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Handle pagination so results are always complete.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Every tool that adds, removes or deletes an entity must require confirm=True before it runs.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Bulk actions should keep going when one item fails and report what succeeded and what failed.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Give each tool a clear description so Claude knows when to use it.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">When you're done, help me get a Zendesk client ID and secret and store them securely.</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="building-the-skill">Building the skill<a href="https://www.marlasowards.com/blog/build-mcps#building-the-skill" class="hash-link" aria-label="Direct link to Building the skill" title="Direct link to Building the skill" translate="no">​</a></h2>
<p>Then I built and iterated on a skill with Claude's help that included instructions like:</p>
<div class="language-markdown codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-markdown codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token title important punctuation" style="color:#393A34">##</span><span class="token title important"> Rate limits</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Zendesk's general API rate limit is 700 requests per minute. Use a concurrency limit of 5 concurrent requests and exponential backoff on 429 responses (retry up to 3 times, starting at 1 second, doubling each attempt).</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token hr punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token title important punctuation" style="color:#393A34">##</span><span class="token title important"> Pagination</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Most Help Center list endpoints (/help_center/...) use offset-based pagination with a next_page URL in the response. Fetch the next_page URL and combine results until next_page is null.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Guide endpoints (/guide/...), including redirect rules, use cursor-based pagination. Use page[size] and page[after] query parameters, and check meta.has_more and meta.after_cursor in the response. Do not use per_page or page on these endpoints. They silently return only the first page with no indication that more pages exist.</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token hr punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token title important punctuation" style="color:#393A34">##</span><span class="token title important"> Labels</span><span class="token plain"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Labels are additive. Posting a label that already exists on an article is a no-op (does not duplicate).</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="invoking-the-skill-to-use-the-mcp-server">Invoking the skill to use the MCP server<a href="https://www.marlasowards.com/blog/build-mcps#invoking-the-skill-to-use-the-mcp-server" class="hash-link" aria-label="Direct link to Invoking the skill to use the MCP server" title="Direct link to Invoking the skill to use the MCP server" translate="no">​</a></h2>
<p>When I invoked the skill, I gave it prompts like these (which I've genericized):</p>
<ul>
<li class=""><em>Apply an "export_data" label to every article in the "Export data" section of the Data User Guide.</em></li>
<li class=""><em>Remove callouts with "Coming soon" at the top of all articles with a "sprint_201_release" label.</em></li>
<li class=""><em>List all articles that have no label, including their title and direct URL, and suggest labels.</em></li>
<li class=""><em>List all unused labels and delete them with my approval.</em></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="expanding-the-skill">Expanding the skill<a href="https://www.marlasowards.com/blog/build-mcps#expanding-the-skill" class="hash-link" aria-label="Direct link to Expanding the skill" title="Direct link to Expanding the skill" translate="no">​</a></h2>
<p>Later I expanded the MCP server and skill to include more API actions, like:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Content tags:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all content tags in the Help Center, optionally filtered by a name prefix</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- See how often each content tag is used, including tags that no article uses</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- See the content tags on a specific article, by name</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Find all articles that have a given content tag, with each article's title, URL, section and category</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Find articles that have no content tags, optionally excluding certain sections</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Add or remove content tags by name, on one article or many at once, and create any tag that doesn't exist yet</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Rename a content tag</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Delete content tags I no longer need</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Categories and sections:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all categories</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Get details for a specific category</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all sections, or only the sections in one category</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Get details for a specific section</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Export:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Export all articles from a section or category</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Fill in section names, category names, label names and content tag names instead of IDs</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Return both a full version with article bodies and a condensed version without them</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Redirect rules:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all redirect rules</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Find the redirect rule for a specific source path</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List redirect rules with the article title and URL filled in for the "from" and "to" articles</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Create a redirect from one article to another, using article IDs instead of full URLs, with a choice of redirect status (such as 301 or 302)</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Delete a redirect rule</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Themes:</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List all themes and show which one is live</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Get details for a specific theme</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Export a theme and extract its files into a local folder</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- List a theme's local files, grouped into templates, assets, settings and other</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Read and edit individual theme files</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Package a local theme folder into a zip that's ready to upload, leaving out hidden files and old zips</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Import a theme zip as a new, unpublished theme</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Publish a theme so it becomes live</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">- Delete a theme that isn't live</span><br></div></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="combining-mcp-server-toolchains">Combining MCP server toolchains<a href="https://www.marlasowards.com/blog/build-mcps#combining-mcp-server-toolchains" class="hash-link" aria-label="Direct link to Combining MCP server toolchains" title="Direct link to Combining MCP server toolchains" translate="no">​</a></h2>
<p>For ultimate time savings, I used the Zendesk Guide MCP in tandem with an MCP server I built for another enterprise tool (Paligo CCMS) to perform multi-system actions, like:</p>
<ul>
<li class=""><em>Publish the updated "Data User Guide" in Paligo to Zendesk and apply the Zendesk label "extract_data" to all new articles created in that guide in Paligo last week.</em></li>
</ul>
<p>If you've worked with that toolchain before, you know how much time and effort a prompt like that saves! Any CMS with a REST API can work this way.</p>
<p>Is there a smarter way I could have done this? I would be grateful to know.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
        <category label="Custom MCPs" term="Custom MCPs"/>
        <category label="Zendesk" term="Zendesk"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Google Drive MCP]]></title>
        <id>https://www.marlasowards.com/blog/mcp-google-drive</id>
        <link href="https://www.marlasowards.com/blog/mcp-google-drive"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about custom MCP servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about custom <a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreferrer" class="">MCP</a> servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/blob/main/mcp/gdrive_mcp.py" target="_blank" rel="noopener noreferrer" class="">gdrive_mcp.py</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/mcp-google-drive#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p>This MCP server performs actions like reading Google Drive files, creating files, and publishing content to them from another source. In particular, this MCP server let me manage content as Markdown.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/mcp-google-drive#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>Formatting a Google Doc with a Google Drive connection in AI tool is notoriously unpredictable. Applied styles can be offset by a character or two, bullets can be misaligned, and formatting can disappear. This custom MCP server allows the content to be extracted from the Google Doc as Markdown using the Google Docs API's <code>text/markdown</code> export MIME type, formats the content straightforwardly Markdown, and converts it into a native Google Doc format.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="Custom MCPs" term="Custom MCPs"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Paligo XML CCMS MCP]]></title>
        <id>https://www.marlasowards.com/blog/mcp-paligo-ccms</id>
        <link href="https://www.marlasowards.com/blog/mcp-paligo-ccms"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about custom MCP servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about custom <a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreferrer" class="">MCP</a> servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/blob/main/mcp/paligo_mcp.py" target="_blank" rel="noopener noreferrer" class="">paligo_mcp.py</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/mcp-paligo-ccms#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p>This MCP server performs actions like creating, updating, and deleting articles; creating publications and productions; uploading and inserting images; and managing taxonomies and variables. It is a wrapper around the <a href="https://docs.paligo.net/en/paligo-rest-api.html" target="_blank" rel="noopener noreferrer" class="">Paligo API</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/mcp-paligo-ccms#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>It's tedious and time consuming to work with Paligo content by clicking around the Paligo UI performing one action at a time. AI agent skills using this MCP server can perform multiple actions at a time - even a full publishing workflow - from transforming a Google doc into XML according to the Paligo XML spec, uploading it to a new document in Paligo, adding it to a guide's table of contents, and triggering the publishing pipeline.</p>
<p>See <a class="" href="https://www.marlasowards.com/portfolio/ai-agent-skills/#paligo-pal">Paligo Pal</a> for a sample of an AI agent skill that uses the Paligo MCP server.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="Custom MCPs" term="Custom MCPs"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Zendesk Guide MCP]]></title>
        <id>https://www.marlasowards.com/blog/mcp-zendesk-guide</id>
        <link href="https://www.marlasowards.com/blog/mcp-zendesk-guide"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about custom MCP servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about custom <a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreferrer" class="">MCP</a> servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/blob/main/mcp/zendesk_guide_mcp.py" target="_blank" rel="noopener noreferrer" class="">zendesk_guide_mcp.py</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/mcp-zendesk-guide#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p>This MCP server performs actions around Zendesk categories, sections, articles, labels, content tags, redirects, and themes. It is a wrapper around the <a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/introduction" target="_blank" rel="noopener noreferrer" class="">Zendesk Help Center API</a>, including both content management and <a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/theming" target="_blank" rel="noopener noreferrer" class="">theming</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/mcp-zendesk-guide#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>It's tedious and time consuming to work with Zendesk content by clicking around the Zendesk UI, and some features (like redirects) aren't even available there. AI agent skills using this MCP server allow me to use natural language prompts for things like:</p>
<ul>
<li class=""><em>Apply an <code>export_data</code> label to every article in the <strong>Export data</strong> section of the <strong>Data User Guide</strong>.</em></li>
<li class=""><em>Remove callouts with <strong>Coming soon</strong> at the top of all articles with a <code>sprint_201_release</code> label.</em></li>
<li class=""><em>List all articles that have no label, including their title and direct URL, and suggest labels.</em></li>
<li class=""><em>List all unused labels and delete them with my approval.</em></li>
</ul>
<p>For ultimate time savings, this MCP server can also be used in tandem with MCP servers for other enterprise tools (like Paligo CCMS) to perform multi-system actions like:</p>
<ul>
<li class=""><em>Publish the updated <strong>Data User Guide</strong> in Paligo to Zendesk and apply the Zendesk label <code>extract_data</code> to all new articles created in that guide in Paligo last week.</em></li>
</ul>
<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>See <a class="" href="https://www.marlasowards.com/portfolio/ai-agent-skills/#zendesk-guide-pal">Zendesk Guide Pal</a> for a sample of an AI agent skill that uses the Zendesk guide MCP server.</p><p>See my blog post, <a class="" href="https://www.marlasowards.com/blog/build-mcps">Build your own MCP server to hand off content management system tasks to an AI agent</a>, for details on how I built the Zendesk Guide MCP server and wired it up with the <a class="" href="https://www.marlasowards.com/portfolio/ai-agent-skills/#zendesk-guide-pal">Zendesk Guide Pal</a> skill.</p></div></div>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="Custom MCPs" term="Custom MCPs"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Zendesk Ticketing MCP]]></title>
        <id>https://www.marlasowards.com/blog/mcp-zendesk-ticketing</id>
        <link href="https://www.marlasowards.com/blog/mcp-zendesk-ticketing"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about custom MCP servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about custom <a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreferrer" class="">MCP</a> servers I've built to connect the systems I work in, so I can generate content from the information they hold, set up workflows that cover multiple tools, and eliminate manual, repetitive work that would otherwise only be possible through the application UI.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/blob/main/mcp/zendesk_tickets_mcp.py" target="_blank" rel="noopener noreferrer" class="">zendesk_tickets_mcp.py</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/mcp-zendesk-ticketing#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p>This MCP server reads Zendesk ticket contents, including the user's question and any conversation following. It also reads fields like a user's organization, ticket labels, ticket status, and custom fields like a user's product platform. It is a wrapper around the <a href="https://developer.zendesk.com/api-reference/ticketing/introduction" target="_blank" rel="noopener noreferrer" class="">Zendesk Ticketing API</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/mcp-zendesk-ticketing#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>Support tickets from users have a wealth of information around issues users experience and agent resolutions, which can reveal opportunities to deflect future tickets with strategic content. But with thousands of tickets in play, it's time consuming and ineffective to manually read through even a subset. AI agent skills using this MCP server can slice tickets into segments, analyze them for common issues and resolutions, and draft troubleshooting articles, FAQs, cheat sheets, and reference material.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="Custom MCPs" term="Custom MCPs"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/ai-optimizer]]></title>
        <id>https://www.marlasowards.com/blog/skill-ai-optimizer</id>
        <link href="https://www.marlasowards.com/blog/skill-ai-optimizer"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/ai-optimizer" target="_blank" rel="noopener noreferrer" class="">ai-optimizer</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-ai-optimizer#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/ai-optimizer</code> checks a drafted Help Center article against 25 research-backed criteria for how well AI agents can use it and whether they retrieve it through RAG, web fetch, or MCP tool calling. It returns a report ranked by priority (critical, high, and medium), with a readiness rating for each access pattern.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-ai-optimizer#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>The skill flags things like sections that can't stand on their own, acronyms that aren't defined in each section, inconsistent terms for the same thing, unclear pronouns, reworded error messages, screenshots without text equivalents, content hidden in tabs or accordions, generic headings, missing checkpoints, and missing failure modes. Every recommendation names the exact section and includes replacement text I can use as is.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-ai-optimizer#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>I wanted generated content to be easily consumed by the company's internal Claude instance and be structured well for use in Zendesk, including optimized search results.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/diataxis-drafter]]></title>
        <id>https://www.marlasowards.com/blog/skill-diataxis-drafter</id>
        <link href="https://www.marlasowards.com/blog/skill-diataxis-drafter"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/diataxis-drafter" target="_blank" rel="noopener noreferrer" class="">diataxis-drafter</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-diataxis-drafter#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/diataxis-drafter</code> generates customer-facing Help Center articles in any Diátaxis type (how-to guide, tutorial, concept, troubleshooting, or reference).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-diataxis-drafter#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>I give the skill a topic and Diátaxis type. The skill reads files catalogued by <a class="" href="https://www.marlasowards.com/blog/skill-source-librarian"><code>/source-librarian</code></a> three cost-saving tiers: index files first, then metadata headers only, and finally full reads of just the files I confirm are relevant. Rules prioritize content sources to read first and most carefully. Flags are thrown for unknowns and contradictions for human review.</p>
<p>The skill also includes Diátaxis templates in a reference file so every article type has a predictable structure.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-diataxis-drafter#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>I wanted to cheaply generate first drafts of articles to speed up the authoring process, including manually reading through multiple sources of product knowledge myself. I also wanted a way to pull directly from product code things like error messages, UI labels, and user paths.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-prompts">Example prompts<a href="https://www.marlasowards.com/blog/skill-diataxis-drafter#example-prompts" class="hash-link" aria-label="Direct link to Example prompts" title="Direct link to Example prompts" translate="no">​</a></h2>
<ul>
<li class=""><em>Draft a how-to guide and a troubleshooting article on Feature X.</em></li>
<li class=""><em>Write a concept article about Feature Y.</em></li>
<li class=""><em>Draft an FAQ about the top 10 most common issues in support tickets about Feature Z.</em></li>
</ul>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/paligo-pal]]></title>
        <id>https://www.marlasowards.com/blog/skill-paligo-pal</id>
        <link href="https://www.marlasowards.com/blog/skill-paligo-pal"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/paligo-pal" target="_blank" rel="noopener noreferrer" class="">paligo-pal</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-paligo-pal#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/paligo-pal</code> performs actions in the Paligo XML CCMS around documents, folders, forks, images, productions, imports, translation exports and imports, taxonomies, variables, users, and assignments. It also includes a Google Doc to Paligo pipeline that converts a doc into valid DocBook 5.1 XML, uploads its images, and turns Help Center links into Paligo cross-references.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-paligo-pal#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>A <a class="" href="https://www.marlasowards.com/portfolio/custom-mcp-servers#paligo-mcp-server">custom Python MCP server</a> connects Claude to the <a href="https://docs.paligo.net/en/paligo-rest-api.html" target="_blank" rel="noopener noreferrer" class="">Paligo REST API</a> so the skill can perform actions with natural language prompts. When interacting with documents, the skill applies Paligo's structural rules automatically. It respects section limits (converting extra headings to styled paragraphs), tells procedures apart from ordinary lists, and handles admonitions, tables, and image placement. Safety rules make it fetch the latest XML just before every update, so it never overwrites edits made in the Paligo editor. It also never guesses a document title or folder location.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-paligo-pal#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>Managing and updating content in the Paligo UI requires a lot of clicks, especially for things like changing content across multiple files or managing images. Also, I had a use case for copying drafts from Google Docs into Paligo, which is slow and error prone when done by hand.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-prompts">Example prompts<a href="https://www.marlasowards.com/blog/skill-paligo-pal#example-prompts" class="hash-link" aria-label="Direct link to Example prompts" title="Direct link to Example prompts" translate="no">​</a></h2>
<ul>
<li class=""><em>Convert this Google Doc to Paligo XML and post to a new document in the Product A Guide.</em></li>
<li class=""><em>Remove the Overview article from the Product B Guide by deleting the document and removing it from the table of contents.</em></li>
<li class=""><em>Upload image.png to the media directory and add it at the top of the Prerequisites article in the Product C Guide.</em></li>
</ul>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/release-notes-drafter]]></title>
        <id>https://www.marlasowards.com/blog/skill-release-notes-drafter</id>
        <link href="https://www.marlasowards.com/blog/skill-release-notes-drafter"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/release-notes-drafter" target="_blank" rel="noopener noreferrer" class="">release-notes-drafter</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-release-notes-drafter#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/release-notes-drafter</code> drafts customer-facing release notes for a specified audience by looking at Github Releases, commits, and Jira tickets. It frames each note in the context of value added to users.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-release-notes-drafter#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>The skill creates one note per Jira ticket associated with a release after filtering out internal work such as CI/CD changes, refactors, monitoring, and dependency upgrades, grouping changes that apply only to certain audiences. The final output lists every dropped item with a reason, so reviewers can check the call.</p>
<p>Notes are written to highlight value to users.</p>
<p>It also adjusts tone and formatting for each audience and replaces internal jargon with customer-facing terms.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-release-notes-drafter#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>I wanted to produce release notes that were more than just changelogs that describe what was built. I wanted to communicate clearly to customers the <em>why</em> behind and changes and how it improves their product experience. I also wanted practical help with grouping notes by product and audience.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/source-librarian]]></title>
        <id>https://www.marlasowards.com/blog/skill-source-librarian</id>
        <link href="https://www.marlasowards.com/blog/skill-source-librarian"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/source-librarian" target="_blank" rel="noopener noreferrer" class="">source-librarian</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-source-librarian#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/source-librarian</code> is a low-cost skill that takes in Zendesk tickets, Jira issues, GitHub code, Confluence pages, Notion pages, transcripts, Slack threads, Google Docs, Google Slides, PDFs, plain text, and other sources of product knowledge so drafting skills can find material relevant to the topic they've been given to write about.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-source-librarian#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>For each new file, it reads the full content, strips boilerplate, applies tags from a 16-dimension product taxonomy, and writes a PII-free summary and drafting guidance into the file's YAML front matter. A compact master index and one index shard per workflow connects the dots between sources.</p>
<p>The classification process includes:</p>
<ul>
<li class=""><strong>A faceted taxonomy with 16 categories and about 400 terms,</strong> covering product areas, features, workflows, objects, user roles, lifecycle stages, compliance, issues, and technical components.</li>
<li class=""><strong>Rules for required tags,</strong> so every source was findable by product area, workflow, and purpose, and troubleshooting and integration sources carried the detail they needed.</li>
</ul>
<p>For support tickets specifically: instead of treating tickets as troubleshooting-only material, the skill surfaces how-to steps, warnings, best practices, and conceptual explanations that would otherwise stay buried in support conversations. Because tickets are high volume, a Python script extracts the content so the company isn't paying for tokens to do it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-source-librarian#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>It's expensive for a drafting skill to find and read up to hundreds of files on every run. I needed a way to ingest each piece of content one time only, classify it, and index it so drafting runs know exactly where to find the information they need and read only the information they need.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/style-pal]]></title>
        <id>https://www.marlasowards.com/blog/skill-style-pal</id>
        <link href="https://www.marlasowards.com/blog/skill-style-pal"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/style-pal" target="_blank" rel="noopener noreferrer" class="">style-pal</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-style-pal#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/style-pal</code> is an audit skill that checks a document against my company Technical Style Guide, with the Microsoft Style Guide as a fallback. It returns a numbered list of violations with a suggested fix for each.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-style-pal#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>The skill checks for ampersands, title case and gerunds in headings, missing serial commas, <em>click on</em> instead of <em>click</em>, quotation marks used for emphasis, split infinitives, third-person instructions, unbolded UI elements and file names, passive voice, and more. Because the report is numbered, I can reply <code>fix 1, 3, 5</code> or <code>fix all but 2 and 4</code> so I stay in control of every change.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-style-pal#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>I wanted to easily catch and fix inconsistencies without manually reading through the text from start to finish or running inadequate manual searches and replaces. I created it as a separate skill so I can run it on any piece of content I write, not just content generated by an AI agent skill in my plugin.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/vocabulary-pal]]></title>
        <id>https://www.marlasowards.com/blog/skill-vocabulary-pal</id>
        <link href="https://www.marlasowards.com/blog/skill-vocabulary-pal"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/vocabulary-pal" target="_blank" rel="noopener noreferrer" class="">vocabulary-pal</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-vocabulary-pal#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/vocabulary-pal</code> audits a Google Doc, Markdown file, text file, or Word document against an organization's custom controlled vocabulary. It flags every non-preferred term and gives the preferred term, the style guide's reasoning, and a suggested rewrite.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-vocabulary-pal#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>The skill handles details a simple find-and-replace can't: case-sensitive terms, hyphenation, acronyms that must be spelled out on first use, plurals and possessives, exceptions for terms shown literally in the product UI, and look-alike terms that mean different things. When the context is ambiguous, it flags both readings instead of picking one silently.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-vocabulary-pal#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>Source materials I generated content from used all kinds of variations of terms, including their spelling and capitalization (for example, common internal use for <em>web app</em> was <em>WebApp</em>, which was not a product name). I wanted to easily catch and fix inconsistencies without manually reading through the text from start to finish or running inadequate manual searches and replaces. I created it as a separate skill so I can run it on any piece of content I write, not just content generated by an AI agent skill in my plugin.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[/zendesk-guide-pal]]></title>
        <id>https://www.marlasowards.com/blog/skill-zendesk-guide-pal</id>
        <link href="https://www.marlasowards.com/blog/skill-zendesk-guide-pal"/>
        <updated>2026-09-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.]]></summary>
        <content type="html"><![CDATA[<p>This is part of a series about the AI agent skills I designed, built, and maintained to cover the full lifecycle of end-user help documentation.</p>
<!-- -->
<p><span></span> <a href="https://github.com/cedar-ave/ai-content-toolkit/tree/main/skills/zendesk-guide-pal" target="_blank" rel="noopener noreferrer" class="">zendesk-guide-pal</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-is">What it is<a href="https://www.marlasowards.com/blog/skill-zendesk-guide-pal#what-it-is" class="hash-link" aria-label="Direct link to What it is" title="Direct link to What it is" translate="no">​</a></h2>
<p><code>/zendesk-guide-pal</code> performs Zendesk Help Center operations, like managing article metadata, content tags, labels, redirect rules, and themes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="how-it-works">How it works<a href="https://www.marlasowards.com/blog/skill-zendesk-guide-pal#how-it-works" class="hash-link" aria-label="Direct link to How it works" title="Direct link to How it works" translate="no">​</a></h2>
<p>A <a class="" href="https://www.marlasowards.com/portfolio/custom-mcp-servers#zendesk-guide-mcp-server">custom Python MCP server</a> is a wrapper around the <a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/introduction" target="_blank" rel="noopener noreferrer" class="">Zendesk Help Center API</a>, including both content management and <a href="https://developer.zendesk.com/api-reference/help_center/help-center-api/theming" target="_blank" rel="noopener noreferrer" class="">theming</a>. The skill then accepts natural language prompts for actions like (among many others):</p>
<ul>
<li class="">Add or remove labels by name, on one article or many at once</li>
<li class="">See how often each label is used, including labels that no article uses</li>
<li class="">Create, update, or delete an article</li>
<li class="">List all articles, or only the articles in one category or section</li>
<li class="">Find all articles that have a given content tag, with each article's title, URL, section and category</li>
<li class="">List all sections, or only the sections in one category</li>
<li class="">Create a redirect from one article to another, using article IDs instead of full URLs, with a choice of redirect status (such as 301 or 302)</li>
<li class="">Package a local theme folder into a zip that's ready to upload, leaving out hidden files and old zips</li>
<li class="">Perform actions in dev or prod</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-i-built-it">Why I built it<a href="https://www.marlasowards.com/blog/skill-zendesk-guide-pal#why-i-built-it" class="hash-link" aria-label="Direct link to Why I built it" title="Direct link to Why I built it" translate="no">​</a></h2>
<p>Performing actions through the Zendesk UI requires lots of repetitive clicking to get things done. This is especially true for custom themes managed locally. I wanted to save time and clicks so I could work faster, more efficiently, and without mistakes.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="example-prompts">Example prompts<a href="https://www.marlasowards.com/blog/skill-zendesk-guide-pal#example-prompts" class="hash-link" aria-label="Direct link to Example prompts" title="Direct link to Example prompts" translate="no">​</a></h2>
<ul>
<li class=""><em>Apply an "export_data" label to every article in the "Export data" section of the Data User Guide.</em></li>
<li class=""><em>Remove callouts with "Coming soon" at the top of all articles with a "sprint_201_release" label.</em></li>
<li class=""><em>List all articles that have no label, including their title and direct URL, and suggest labels.</em></li>
<li class=""><em>List all unused labels and delete them with my approval.</em></li>
</ul>
<p>For ultimate time savings, I used my <a class="" href="https://www.marlasowards.com/portfolio/custom-mcp-servers#zendesk-guide-mcp-server">Zendesk Guide MCP server</a> in tandem with my <a class="" href="https://www.marlasowards.com/portfolio/custom-mcp-servers#paligo-mcp-server">Paligo MCP server</a> to perform multi-system actions, like:</p>
<ul>
<li class=""><em>Publish the updated "Data User Guide" in Paligo to Zendesk and apply the Zendesk label "extract_data" to all new articles created in that guide in Paligo last week.</em></li>
</ul>
<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>See my blog post, <a class="" href="https://www.marlasowards.com/blog/build-mcps">Build your own MCP server to hand off content management system tasks to an AI agent</a>, for details on how I built the <a class="" href="https://www.marlasowards.com/portfolio/custom-mcp-servers#zendesk-guide-mcp-server">Zendesk Guide MCP server</a> and wired it up with the <code>/zendesk-guide-pal</code> skill.</p></div></div>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="AI agent skills" term="AI agent skills"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[A magic question: What problem are you trying to solve?]]></title>
        <id>https://www.marlasowards.com/blog/solving-the-real-problem</id>
        <link href="https://www.marlasowards.com/blog/solving-the-real-problem"/>
        <updated>2026-09-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[I once sat by two engineering leaders who were phenomenal at handling requests for new software features. Often team members would come to them and insist on something like, We really need to add a new feature that lets users do X. Our users are clamoring for it. We might lose customers over this! The leaders would respond, What problem are you trying to solve? The conversation immediately shifted to a discussion about root causes, user goals, business value, and real evidence. More often than not, it quickly became clear that the proposed solution was not the right thing to spend time on.]]></summary>
        <content type="html"><![CDATA[<p>I once sat by two engineering leaders who were phenomenal at handling requests for new software features. Often team members would come to them and insist on something like, <em>We really need to add a new feature that lets users do X. Our users are clamoring for it. We might lose customers over this!</em> The leaders would respond, <em><strong>What problem are you trying to solve?</strong></em> The conversation immediately shifted to a discussion about root causes, user goals, business value, and real evidence. More often than not, it quickly became clear that the proposed solution was not the right thing to spend time on.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="applying-the-question-in-techcomm">Applying the question in techcomm<a href="https://www.marlasowards.com/blog/solving-the-real-problem#applying-the-question-in-techcomm" class="hash-link" aria-label="Direct link to Applying the question in techcomm" title="Direct link to Applying the question in techcomm" translate="no">​</a></h2>
<p>I love as a technical writer when someone on the team comes to me with a request for new content. It shows they see the value of content and trust me to help. But this magic question works just as well on the requests I receive as it does on product feature requests. For example:</p>
<p><strong>Request:</strong> "Can we make an FAQ for new customers?"</p>
<p><strong>Actual problem:</strong> New customers don't know our help site exists, so they never find the answers already there.</p>
<p><strong>What might actually solve it:</strong> Introduce the help site during onboarding.</p>
<figure class="figure_XMQo"><div class="scroll_VL3y"><svg class="svg_VY1j" style="min-width:700px" viewBox="0 0 900 360" role="img" aria-labelledby="in-root-t in-root-d"><title id="in-root-t">Triage turns a requested solution into a root problem, then weighs every way content could fix it</title><desc id="in-root-d">A request arrives as a solution: can we make an FAQ for new customers? Triage questions ask what problem the requester is solving, who hits it and how often, what already exists, how much time a fix would save, and whether new content is needed. The answers reveal the root problem: new customers don't know the help site exists, so they never find answers that are already written. Three fixes are weighed. A new FAQ page would be one more page no one finds. Introducing the help site during onboarding and tracking help site awareness by customer organization address the cause and are chosen.</desc><defs><marker id="in-root-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" class="arrow_gfyr"></path></marker><marker id="in-root-arrow-key" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" class="arrowKey_Bb22"></path></marker></defs><text x="115" y="22" text-anchor="middle" class="heading_GGn4">Requested</text><text x="360" y="22" text-anchor="middle" class="heading_GGn4">Triage</text><text x="597" y="22" text-anchor="middle" class="heading_GGn4">Root problem</text><text x="800" y="22" text-anchor="middle" class="heading_GGn4">Fixes weighed</text><path d="M210 180 L248 180" class="edge_q04H" marker-end="url(#in-root-arrow)"></path><path d="M470 180 L508 180" class="edgeKey_YaqK" marker-end="url(#in-root-arrow-key)"></path><path d="M685 180 C705 180 690 100 708 100" class="edgeMuted_jYKi" marker-end="url(#in-root-arrow)"></path><path d="M685 180 C705 180 690 180 708 180" class="edgeKey_YaqK" marker-end="url(#in-root-arrow-key)"></path><path d="M685 180 C705 180 690 260 708 260" class="edgeKey_YaqK" marker-end="url(#in-root-arrow-key)"></path><g><rect x="20" y="120" width="190" height="120" rx="8" class="request_bSEt"></rect><text text-anchor="middle"><tspan x="115" y="165.5" class="quote_NGMn">“Can we make an FAQ</tspan><tspan x="115" y="184.5" class="quote_NGMn">for new customers?”</tspan><tspan x="115" y="203.5" class="sub_modF">Solution-shaped request</tspan></text></g><g><rect x="250" y="90" width="220" height="180" rx="8" class="hub_vyae"></rect><text text-anchor="middle"><tspan x="360" y="132" class="hubTitle_PT2W">Triage questions</tspan><tspan x="360" y="153" class="hubSub_Ch3x">What problem are you solving?</tspan><tspan x="360" y="174" class="hubSub_Ch3x">Who hits it, and how often?</tspan><tspan x="360" y="195" class="hubSub_Ch3x">What already exists?</tspan><tspan x="360" y="216" class="hubSub_Ch3x">How much time would a fix save?</tspan><tspan x="360" y="237" class="hubSub_Ch3x">New content or an update?</tspan></text></g><g><rect x="510" y="115" width="175" height="130" rx="8" class="root_9dQp"></rect><text text-anchor="middle"><tspan x="597.5" y="146.5" class="title_grh1">New customers don't</tspan><tspan x="597.5" y="165.5" class="title_grh1">know the help site</tspan><tspan x="597.5" y="184.5" class="title_grh1">exists</tspan><tspan x="597.5" y="203.5" class="sub_modF">The answers were written.</tspan><tspan x="597.5" y="222.5" class="sub_modF">Nobody knew where.</tspan></text></g><g><rect x="710" y="70" width="180" height="60" rx="8" class="rejected_sZhY"></rect><text text-anchor="middle"><tspan x="800" y="96" class="titleMuted_m0AT">New FAQ page</tspan><tspan x="800" y="113" class="sub_modF">Another page no one finds</tspan></text></g><g><rect x="710" y="150" width="180" height="60" rx="8" class="chosen_Kphb"></rect><text text-anchor="middle"><tspan x="800" y="176" class="title_grh1">Help site intro</tspan><tspan x="800" y="193" class="sub_modF">Built into onboarding</tspan></text></g><g><rect x="710" y="230" width="180" height="60" rx="8" class="chosen_Kphb"></rect><text text-anchor="middle"><tspan x="800" y="256" class="title_grh1">Track site awareness</tspan><tspan x="800" y="273" class="sub_modF">Readers per customer org</tspan></text></g></svg></div></figure>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="putting-the-question-into-a-process">Putting the question into a process<a href="https://www.marlasowards.com/blog/solving-the-real-problem#putting-the-question-into-a-process" class="hash-link" aria-label="Direct link to Putting the question into a process" title="Direct link to Putting the question into a process" translate="no">​</a></h2>
<p>A company I worked for used Jira heavily across the org. I created a Jira form and asked team members to use it to pass on their requests. I knew the form needed to be as short and as painless to fill out as possible, so I narrowed it down to five questions, with the most important at the top:</p>
<ul>
<li class="">What problem are you trying to solve?</li>
<li class="">Describe the new content you're requesting.</li>
<li class="">Who is the audience for the content?</li>
<li class="">How urgent is this request?</li>
<li class="">What have people been doing until now to meet this need? (A second magic question!)</li>
</ul>
<p><em>Urgent</em> is the most overused word in any request queue. For that question, I set up four options to help understand the request:</p>
<ul>
<li class=""><strong>Mission critical:</strong> Blocking a launch, legal obligation, or customer impact. Must address immediately to prevent measurable harm.</li>
<li class=""><strong>Time sensitive:</strong> Tied to a specific date or event with external visibility. Delay would reduce relevance or credibility.</li>
<li class=""><strong>Nice to have by a certain date:</strong> Helps a project or team but is not time-bound. Not blocking or externally visible.</li>
<li class=""><strong>Flexible:</strong> Schedule when capacity allows. No impact if delayed. Optimize timing for impact.</li>
</ul>
<section class="mock_CKQA" aria-label="Mockup: request for new content form and the Jira story it creates"><div class="mockBadge_ZNjA"><span>Form mockup</span><span>Illustrative content · try editing the fields</span></div><div class="mockBody_pc3P"><form class="form_Yj4u"><p class="formProject_Fuzj">Content Development</p><h3 class="formTitle_C58f">Request for new content</h3><p class="formIntro_SzSE">Tell us what's getting in the way. We'll work with you on the best way for content to solve it.</p><label class="field_n1ek"><span class="label_KTIc">What problem are you trying to solve? <em class="req_kiv7">Required</em></span><textarea rows="3">Customers keep opening tickets asking why their report is missing records after they apply the date filter.</textarea><span class="help_f2X5">Describe the situation, not the deliverable. Who is stuck, and on what?</span></label><label class="field_n1ek"><span class="label_KTIc">Describe the new content you're requesting. <em class="req_kiv7">Required</em></span><textarea rows="2">A new step-by-step guide for the reporting feature, with screenshots of every filter.</textarea></label><label class="field_n1ek"><span class="label_KTIc">Who is the audience for the content? <em class="req_kiv7">Required</em></span><input type="text" value="Customer end users"></label><fieldset class="field_n1ek"><legend class="label_KTIc">How urgent is this request? <em class="req_kiv7">Required</em></legend><div class="radios_uHoW"><label class="radio_gKkp "><input type="radio" name="urgency" value="critical"><span><strong>Mission critical</strong><span class="radioDesc_ubX1">Blocking a launch, legal obligation, or customer impact. Must address immediately to prevent measurable harm.</span></span></label><label class="radio_gKkp radioOn_gplj"><input type="radio" name="urgency" checked="" value="time"><span><strong>Time sensitive</strong><span class="radioDesc_ubX1">Tied to a specific date or event with external visibility. Delay would reduce relevance or credibility.</span></span></label><label class="radio_gKkp "><input type="radio" name="urgency" value="date"><span><strong>Nice to have by a certain date</strong><span class="radioDesc_ubX1">Helps a project or team but not time-bound. Not blocking or externally visible.</span></span></label><label class="radio_gKkp "><input type="radio" name="urgency" value="flexible"><span><strong>Flexible</strong><span class="radioDesc_ubX1">Schedule when capacity allows. No impact if delayed. Optimize timing for impact.</span></span></label></div></fieldset><label class="field_n1ek"><span class="label_KTIc">What content already exists about this topic, even if it's not in great shape?</span><input type="text" value="Existing reporting article; support macro for filter questions"><span class="help_f2X5">Google Docs or Slides, Notion pages, PRDs, communications, recordings, transcripts, Jira tickets, etc.</span></label><div class="field_n1ek"><span class="label_KTIc">Attachments</span><div class="drop_hiQy">Drag files here or <u>browse</u></div></div><button type="submit" class="submit_edjq">Submit request</button></form><div class="story_p7KL" aria-live="polite"><div class="storyTop_d7dt"><span class="storyHeading_IuKL">Creates a Jira story</span></div><div class="seg_fbuv" role="group" aria-label="Story state"><button type="button" aria-pressed="true" class="segBtn_g93e">As submitted</button><button type="button" aria-pressed="false" class="segBtn_g93e">After triage</button></div><div class="card_kzWI"><p class="crumb_dRA5"><span class="storyIcon_IGOZ" aria-hidden="true"></span>CONTENT DEVELOPMENT / CONT-142</p><p class="summary_GuoA">A new step-by-step guide for the reporting feature, with scree…</p><dl class="meta_uVdE"><dt>Type</dt><dd>Story</dd><dt>Status</dt><dd><span class="chip_jRJe chipGrey_oPfg">New</span></dd><dt>Priority</dt><dd><span class="muted_gL2Q">Suggested: <!-- -->High<!-- --> (from urgency)</span></dd><dt>Urgency</dt><dd>Time sensitive</dd><dt>Audience</dt><dd>Customer end users</dd><dt>Labels</dt><dd><span class="muted_gL2Q">Added at triage</span></dd></dl><div class="block_yimj"><p class="blockLabel_cVVx">Problem to solve</p><p>Customers keep opening tickets asking why their report is missing records after they apply the date filter.</p></div><div class="block_yimj"><p class="blockLabel_cVVx">Requested content</p><p>A new step-by-step guide for the reporting feature, with screenshots of every filter.</p></div><div class="block_yimj"><p class="blockLabel_cVVx">Existing content</p><p>Existing reporting article; support macro for filter questions</p></div></div></div></div></section>
<p>A submitted form immediately became a ticket on my technical writing Jira board. This was helpful for a couple reasons:</p>
<ul>
<li class=""><strong>The requester gets status updates.</strong> Because the requester is the ticket reporter, they get notifications of status changes and new comments.</li>
<li class=""><strong>Communication around the request is visible.</strong> Questions, answers, and progress updates happen in the ticket comments instead of private Slack conversations.</li>
<li class=""><strong>The requester can see the trajectory of their request.</strong> My project's Kanban board shows where the request sits in the queue and what's ahead of it.</li>
<li class=""><strong>A Jira dashboard shows my capacity and progress.</strong> Tracking what's on the table helps me and my leadership scope and prioritize.</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="answering-the-question">Answering the question<a href="https://www.marlasowards.com/blog/solving-the-real-problem#answering-the-question" class="hash-link" aria-label="Direct link to Answering the question" title="Direct link to Answering the question" translate="no">​</a></h2>
<p>Next, the requester and I worked together to scope and prioritize the request. A couple more magic questions helped frame the discussion:</p>
<ul>
<li class="">What percentage of this request comes from customers?</li>
<li class="">How much time will implementing this request save?</li>
<li class="">Is this more important than other things I'm working on delivering?</li>
</ul>
<p>From there, we could finally get down to whether it made sense to do what was asked, try another approach, or deprioritize the need.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="measuring-the-answer">Measuring the answer<a href="https://www.marlasowards.com/blog/solving-the-real-problem#measuring-the-answer" class="hash-link" aria-label="Direct link to Measuring the answer" title="Direct link to Measuring the answer" translate="no">​</a></h2>
<p>Finally, possibly most important of all: measuring if the intervention made a difference. Going back to the example above, where I avoided creating a new FAQ in favor of improving awareness of a help site that already had the answers, I put in a request for a visualization that showed if customers from a given organization visit the help site.</p>
<section class="dash_HFIB" aria-label="Dashboard mockup: Where are the site awareness and education gaps?"><div class="dashBadge_n6jW"><span>Dashboard mockup</span><span>Illustrative data</span></div><div class="dashHead_L282"><p class="dashQuestion_vNhb">Where are the site awareness and education gaps?</p><p class="dashMetric_n0SZ">Users at each organization with at least one article view vs. total users at that organization</p></div><div class="dashBody_zvGt"><div class="chartWrap_UymJ"><div class="legend_IW8u"><span class="legendItem_zzmV"><span class="swatch_JtqV swatchA_GuR1"></span>Users with ≥1 article view</span><span class="legendItem_zzmV"><span class="swatch_JtqV swatchB_rWEi"></span>Total users</span></div><div class="chartScroll_o5IT"><div class="chartInner_oU8E"><svg class="chartSvg_OBHP" viewBox="0 0 640 290" role="img" aria-label="Grouped bar chart of users with an article view and total users for each organization"><g><line x1="36" x2="632" y1="214" y2="214" class="baseline_yPPr"></line><text x="30" y="218" text-anchor="end" class="tick_BScq">0</text></g><g><line x1="36" x2="632" y1="164" y2="164" class="gridLine_nXfi"></line><text x="30" y="168" text-anchor="end" class="tick_BScq">35</text></g><g><line x1="36" x2="632" y1="114" y2="114" class="gridLine_nXfi"></line><text x="30" y="118" text-anchor="end" class="tick_BScq">70</text></g><g><line x1="36" x2="632" y1="64" y2="64" class="gridLine_nXfi"></line><text x="30" y="68" text-anchor="end" class="tick_BScq">105</text></g><g><line x1="36" x2="632" y1="14" y2="14" class="gridLine_nXfi"></line><text x="30" y="18" text-anchor="end" class="tick_BScq">140</text></g><g><rect x="36" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M43.09090909090909,214 L43.09090909090909,142.28571428571428 Q43.09090909090909,138.28571428571428 47.09090909090909,138.28571428571428 L58.09090909090909,138.28571428571428 Q62.09090909090909,138.28571428571428 62.09090909090909,142.28571428571428 L62.09090909090909,214 Z" class="barA_lsNA"></path><path d="M64.0909090909091,214 L64.0909090909091,128 Q64.0909090909091,124 68.0909090909091,124 L79.0909090909091,124 Q83.0909090909091,124 83.0909090909091,128 L83.0909090909091,214 Z" class="barB_hRyf"></path><text transform="translate(67.0909090909091 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Internal team</text><rect x="36" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Internal team: 53 of 63 users viewed an article"></rect></g><g><rect x="90.18181818181819" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M97.27272727272728,214 L97.27272727272728,195.14285714285714 Q97.27272727272728,191.14285714285714 101.27272727272728,191.14285714285714 L112.27272727272728,191.14285714285714 Q116.27272727272728,191.14285714285714 116.27272727272728,195.14285714285714 L116.27272727272728,214 Z" class="barA_lsNA"></path><path d="M118.27272727272728,214 L118.27272727272728,128 Q118.27272727272728,124 122.27272727272728,124 L133.27272727272728,124 Q137.27272727272728,124 137.27272727272728,128 L137.27272727272728,214 Z" class="barB_hRyf"></path><text transform="translate(121.27272727272728 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer A</text><rect x="90.18181818181819" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer A: 16 of 63 users viewed an article"></rect></g><g><rect x="144.36363636363637" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M151.45454545454547,214 L151.45454545454547,158 Q151.45454545454547,154 155.45454545454547,154 L166.45454545454547,154 Q170.45454545454547,154 170.45454545454547,158 L170.45454545454547,214 Z" class="barA_lsNA"></path><path d="M172.45454545454547,214 L172.45454545454547,113.71428571428571 Q172.45454545454547,109.71428571428571 176.45454545454547,109.71428571428571 L187.45454545454547,109.71428571428571 Q191.45454545454547,109.71428571428571 191.45454545454547,113.71428571428571 L191.45454545454547,214 Z" class="barB_hRyf"></path><text transform="translate(175.45454545454547 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer B</text><rect x="144.36363636363637" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer B: 42 of 73 users viewed an article"></rect></g><g><rect x="198.54545454545453" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M205.63636363636363,214 L205.63636363636363,208 Q205.63636363636363,204 209.63636363636363,204 L220.63636363636363,204 Q224.63636363636363,204 224.63636363636363,208 L224.63636363636363,214 Z" class="barA_lsNA"></path><path d="M226.63636363636363,214 L226.63636363636363,75.14285714285714 Q226.63636363636363,71.14285714285714 230.63636363636363,71.14285714285714 L241.63636363636363,71.14285714285714 Q245.63636363636363,71.14285714285714 245.63636363636363,75.14285714285714 L245.63636363636363,214 Z" class="barB_hRyf"></path><text transform="translate(229.63636363636363 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer C</text><rect x="198.54545454545453" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer C: 7 of 100 users viewed an article"></rect></g><g><rect x="252.72727272727272" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M259.8181818181818,214 L259.8181818181818,120.85714285714286 Q259.8181818181818,116.85714285714286 263.8181818181818,116.85714285714286 L274.8181818181818,116.85714285714286 Q278.8181818181818,116.85714285714286 278.8181818181818,120.85714285714286 L278.8181818181818,214 Z" class="barA_lsNA"></path><path d="M280.8181818181818,214 L280.8181818181818,60.85714285714286 Q280.8181818181818,56.85714285714286 284.8181818181818,56.85714285714286 L295.8181818181818,56.85714285714286 Q299.8181818181818,56.85714285714286 299.8181818181818,60.85714285714286 L299.8181818181818,214 Z" class="barB_hRyf"></path><text transform="translate(283.8181818181818 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer D</text><rect x="252.72727272727272" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer D: 68 of 110 users viewed an article"></rect></g><g><rect x="306.9090909090909" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M313.99999999999994,214 L313.99999999999994,159.42857142857142 Q313.99999999999994,155.42857142857142 317.99999999999994,155.42857142857142 L328.99999999999994,155.42857142857142 Q332.99999999999994,155.42857142857142 332.99999999999994,159.42857142857142 L332.99999999999994,214 Z" class="barA_lsNA"></path><path d="M334.99999999999994,214 L334.99999999999994,102.28571428571428 Q334.99999999999994,98.28571428571428 338.99999999999994,98.28571428571428 L349.99999999999994,98.28571428571428 Q353.99999999999994,98.28571428571428 353.99999999999994,102.28571428571428 L353.99999999999994,214 Z" class="barB_hRyf"></path><text transform="translate(337.99999999999994 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer E</text><rect x="306.9090909090909" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer E: 41 of 81 users viewed an article"></rect></g><g><rect x="361.09090909090907" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M368.18181818181813,214 L368.18181818181813,150.85714285714286 Q368.18181818181813,146.85714285714286 372.18181818181813,146.85714285714286 L383.18181818181813,146.85714285714286 Q387.18181818181813,146.85714285714286 387.18181818181813,150.85714285714286 L387.18181818181813,214 Z" class="barA_lsNA"></path><path d="M389.18181818181813,214 L389.18181818181813,150.85714285714286 Q389.18181818181813,146.85714285714286 393.18181818181813,146.85714285714286 L404.18181818181813,146.85714285714286 Q408.18181818181813,146.85714285714286 408.18181818181813,150.85714285714286 L408.18181818181813,214 Z" class="barB_hRyf"></path><text transform="translate(392.18181818181813 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer F</text><rect x="361.09090909090907" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer F: 47 of 47 users viewed an article"></rect></g><g><rect x="415.27272727272725" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M422.3636363636363,214 L422.3636363636363,96.57142857142858 Q422.3636363636363,92.57142857142858 426.3636363636363,92.57142857142858 L437.3636363636363,92.57142857142858 Q441.3636363636363,92.57142857142858 441.3636363636363,96.57142857142858 L441.3636363636363,214 Z" class="barA_lsNA"></path><path d="M443.3636363636363,214 L443.3636363636363,75.14285714285714 Q443.3636363636363,71.14285714285714 447.3636363636363,71.14285714285714 L458.3636363636363,71.14285714285714 Q462.3636363636363,71.14285714285714 462.3636363636363,75.14285714285714 L462.3636363636363,214 Z" class="barB_hRyf"></path><text transform="translate(446.3636363636363 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer G</text><rect x="415.27272727272725" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer G: 85 of 100 users viewed an article"></rect></g><g><rect x="469.45454545454544" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M476.5454545454545,214 L476.5454545454545,199.42857142857142 Q476.5454545454545,195.42857142857142 480.5454545454545,195.42857142857142 L491.5454545454545,195.42857142857142 Q495.5454545454545,195.42857142857142 495.5454545454545,199.42857142857142 L495.5454545454545,214 Z" class="barA_lsNA"></path><path d="M497.5454545454545,214 L497.5454545454545,165.14285714285714 Q497.5454545454545,161.14285714285714 501.5454545454545,161.14285714285714 L512.5454545454545,161.14285714285714 Q516.5454545454545,161.14285714285714 516.5454545454545,165.14285714285714 L516.5454545454545,214 Z" class="barB_hRyf"></path><text transform="translate(500.5454545454545 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer H</text><rect x="469.45454545454544" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer H: 13 of 37 users viewed an article"></rect></g><g><rect x="523.6363636363636" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="" class="barA_lsNA"></path><path d="M551.7272727272727,214 L551.7272727272727,66.57142857142858 Q551.7272727272727,62.571428571428584 555.7272727272727,62.571428571428584 L566.7272727272727,62.571428571428584 Q570.7272727272727,62.571428571428584 570.7272727272727,66.57142857142858 L570.7272727272727,214 Z" class="barB_hRyf"></path><g><text x="540.2272727272727" y="209" text-anchor="middle" class="tick_BScq">0</text><line x1="550.7272727272727" x2="550.7272727272727" y1="58.571428571428584" y2="46.571428571428584" class="annotLine_c53S"></line><text x="550.7272727272727" y="42.571428571428584" text-anchor="middle" class="annot_CxuU">no one has visited</text></g><text transform="translate(554.7272727272727 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer I</text><rect x="523.6363636363636" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer I: 0 of 106 users viewed an article"></rect></g><g><rect x="577.8181818181818" y="14" width="54.18181818181818" height="200" class="hit_mlKS"></rect><path d="M584.9090909090909,214 L584.9090909090909,120.85714285714286 Q584.9090909090909,116.85714285714286 588.9090909090909,116.85714285714286 L599.9090909090909,116.85714285714286 Q603.9090909090909,116.85714285714286 603.9090909090909,120.85714285714286 L603.9090909090909,214 Z" class="barA_lsNA"></path><path d="M605.9090909090909,214 L605.9090909090909,90.85714285714286 Q605.9090909090909,86.85714285714286 609.9090909090909,86.85714285714286 L620.9090909090909,86.85714285714286 Q624.9090909090909,86.85714285714286 624.9090909090909,90.85714285714286 L624.9090909090909,214 Z" class="barB_hRyf"></path><text transform="translate(608.9090909090909 228) rotate(-35)" text-anchor="end" class="catLabel_za1W">Customer J</text><rect x="577.8181818181818" y="14" width="54.18181818181818" height="276" class="hit_mlKS" tabindex="0" aria-label="Customer J: 68 of 89 users viewed an article"></rect></g></svg></div></div></div><div class="side_FfXr"><div class="kpi_xz87"><span class="kpiValue_ArQD">51%</span><span class="kpiLabel_OtWN">of users have viewed at least one help article</span></div><fieldset class="control_E9jf"><legend class="controlLabel_kdn7">View date</legend><div class="segmented_t21S"><button type="button" class="segBtn_ewM8" aria-pressed="false">30 days</button><button type="button" class="segBtn_ewM8" aria-pressed="false">90 days</button><button type="button" class="segBtn_ewM8" aria-pressed="true">12 mo</button></div></fieldset><fieldset class="control_E9jf"><legend class="controlLabel_kdn7">Sort organizations</legend><div class="segmented_t21S"><button type="button" class="segBtn_ewM8" aria-pressed="true">Name</button><button type="button" class="segBtn_ewM8" aria-pressed="false">Lowest coverage</button></div></fieldset><div class="control_E9jf"><span class="controlLabel_kdn7">Always applied</span><span class="lockedChip_HiIa">Admin and test accounts excluded</span></div></div></div><div class="dashFoot_tFpM">Internal team is pinned first as the benchmark: it shows what healthy awareness looks like for people who know the site exists.</div></section>
<p><strong>View date</strong> and <strong>User creation date</strong> sliders gave extra insight into things like how long it takes for customers to visit the site after an organization finishes onboarding. That way, I'm one step closer to figuring out how the education failure occurred.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="softening-the-answer">Softening the answer<a href="https://www.marlasowards.com/blog/solving-the-real-problem#softening-the-answer" class="hash-link" aria-label="Direct link to Softening the answer" title="Direct link to Softening the answer" translate="no">​</a></h2>
<p>It's important to note that good interpersonal skills (especially empathy) are critical when asking this magic question so the requester doesn't feel shut down and stop sharing ideas. They feel the pain firsthand and know a lot of things I don't. But in my experience, most people I've worked with have been more interested in solving the pain point than insisting on their solution. Ultimately, they're happy to see the needle move toward a better experience for users.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="Quality improvement" term="Quality improvement"/>
        <category label="Governance" term="Governance"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to choose an open-source static-site generator for a docs-as-code workflow]]></title>
        <id>https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs</id>
        <link href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs"/>
        <updated>2026-09-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[If you're launching a docs-as-code platform (or retooling one) and want to use an open-source static-site generator, choosing one can be overwhelming. There are a lot out there, and it's tempting to look at which one has the most stars in GitHub and go from there. I've been there, and I've learned a few things the hard way! Here are some things to think about that might help with your decision.]]></summary>
        <content type="html"><![CDATA[<p>If you're launching a docs-as-code platform (or retooling one) and want to use an open-source static-site generator, choosing one can be overwhelming. There are a lot out there, and it's tempting to look at which one has the most stars in GitHub and go from there. I've been there, and I've learned a few things the hard way! Here are some things to think about that might help with your decision.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-who-owns-the-project-and-how-long-has-it-been-around">1. Who owns the project, and how long has it been around?<a href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs#1-who-owns-the-project-and-how-long-has-it-been-around" class="hash-link" aria-label="Direct link to 1. Who owns the project, and how long has it been around?" title="Direct link to 1. Who owns the project, and how long has it been around?" translate="no">​</a></h2>
<p>Static-site generators on the newer side can be promising and exciting, but it can be a risk to lock in too early. Over time, interest in maintaining the project may wane, so new features to keep the tool aligned with advancing technology may never be added and bugs may never be fixed (unless you fix them yourself).</p>
<p>Take a look at static-site generators used by larger companies. While there's no guarantee, it's easier to trust that these projects will be maintained and advanced. For example:</p>
<ul>
<li class=""><strong><a href="https://gohugo.io/" target="_blank" rel="noopener noreferrer" class="">Hugo</a></strong>: <a href="https://kubernetes.io/docs/home" target="_blank" rel="noopener noreferrer" class="">Kubernetes docs</a> (see <a href="https://kubernetes.io/blog/2018/05/05/hugo-migration" target="_blank" rel="noopener noreferrer" class="">Docs are Migrating from Jekyll to Hugo</a>), <a href="https://docs.docker.com/" target="_blank" rel="noopener noreferrer" class="">Docker docs</a>, and <a href="https://v2.tauri.app/start" target="_blank" rel="noopener noreferrer" class="">GitLab docs</a> (see <a href="https://about.gitlab.com/blog/docs-site-design-overhaul" target="_blank" rel="noopener noreferrer" class="">The GitLab documentation site gets a major design overhaul</a> and <a href="https://kubernetes.io/blog/2020/06/better-docs-ux-with-docsy" target="_blank" rel="noopener noreferrer" class="">A Better Docs UX With Docsy</a>)</li>
<li class=""><strong><a href="https://docusaurus.io/" target="_blank" rel="noopener noreferrer" class="">Docusaurus</a></strong>: <a href="https://www.electronjs.org/docs" target="_blank" rel="noopener noreferrer" class="">Electron docs</a> (see the <a href="https://docusaurus.io/showcase" target="_blank" rel="noopener noreferrer" class="">Docusaurus showcase</a> too)</li>
<li class=""><strong><a href="https://starlight.astro.build/" target="_blank" rel="noopener noreferrer" class="">Astro/Starlight</a></strong>: <a href="https://developers.cloudflare.com/" target="_blank" rel="noopener noreferrer" class="">Cloudflare docs</a> (see <a href="https://blog.cloudflare.com/open-source-all-the-way-down-upgrading-our-developer-documentation" target="_blank" rel="noopener noreferrer" class="">Open source all the way down: Upgrading our developer documentation</a>)</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-how-broadly-is-the-tool-used">2. How broadly is the tool used?<a href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs#2-how-broadly-is-the-tool-used" class="hash-link" aria-label="Direct link to 2. How broadly is the tool used?" title="Direct link to 2. How broadly is the tool used?" translate="no">​</a></h2>
<p>The more companies and people who use it, the more you're going to see templates, add-ons, extensions, and answers to questions shared in GitHub repo comments and Stack Overflow. The number of stars in a tool's GitHub repo can be one clue.</p>
<p>However, take into account that some tools may have passed the height of their popularity. Few companies seem to run their documentation sites on Jekyll, even though it was a popular choice a few years ago. It's still a good tool but may no longer have large, active communities developing enhancements for full-blown docs sites.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-how-often-is-the-tool-updated">3. How often is the tool updated?<a href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs#3-how-often-is-the-tool-updated" class="hash-link" aria-label="Direct link to 3. How often is the tool updated?" title="Direct link to 3. How often is the tool updated?" translate="no">​</a></h2>
<p>A tool that's updated infrequently or only with minor changes is probably less likely to support new requirements that emerge over time. A GitHub repo's code frequency graph can show you if contributions are waning.</p>
<p>Examples are Gatsby (which was popular a few years ago but is now in low-activity maintenance), and MkDocs (which was popular for years but went into maintenance mode in 2025).</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-what-are-your-requirements">4. What are your requirements?<a href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs#4-what-are-your-requirements" class="hash-link" aria-label="Direct link to 4. What are your requirements?" title="Direct link to 4. What are your requirements?" translate="no">​</a></h2>
<p>Be intentional and objective when thinking through what you need the static-site generator to support. For example, you may want it to support:</p>
<ul>
<li class=""><strong>AI workflows</strong>: Can the tool output clean Markdown or structured data? These are critical for consumers like LLMs and AI chatbots.</li>
<li class=""><strong>API docs</strong>: Is the audience of your site primarily developers? What kind of API documentation do you need to publish? For example <a href="https://dotnet.github.io/docfx/index.html" target="_blank" rel="noopener noreferrer" class="">DocFX</a> supports .NET API documentation.</li>
<li class=""><strong>Certain search requirements</strong>: Does the search run in the browser, or does it need an outside service like Algolia?</li>
<li class=""><strong>Integration with an existing app</strong>: Will you need to integrate your documentation site with a software product? You may want a static-site generator built on the same framework.</li>
<li class=""><strong>Contributions from end users</strong>: Will end users contribute to your docs-as-code workflow? Some tools ship with a <em>Change this doc</em> link (or something similar) at the bottom of articles that takes users directly to a public GitHub repo, where they can add or change articles and submit a pull request.</li>
<li class=""><strong>Contributions from non-technical authors</strong>: Will authors not comfortable with Git and Markdown contribute to the documentation? You may want support for an open-source headless CMS like <a href="https://tina.io/" target="_blank" rel="noopener noreferrer" class="">TinaCMS</a>, which allows you to put a familiar visual editor on top while still storing the content as Markdown in Git.</li>
<li class=""><strong>Content reuse</strong>: Will you need to use some structured authoring in your body of content? While Markdown and docs-as-code tooling is probably not the best approach for that (look into XML and CCMSes), some tools support it to a degree.</li>
<li class=""><strong>Customizations</strong>: How painless is it to add custom features that may not be offered by the tool, like paragraph anchors or feedback forms at the bottom of articles? Are themes available that allow you to add things like sidebars, version switches, and search? Are plugins or extensions offered (like in the <a href="https://docusaurus.community/plugindirectory" target="_blank" rel="noopener noreferrer" class="">Docusaurus plugin directory</a>)?</li>
<li class=""><strong>Translation</strong>: If not now, will you need to ship the documentation website in two or more languages?</li>
<li class=""><strong>Product versioning</strong>: Will users need to navigate between docs for different product versions?</li>
<li class=""><strong>Moving content later</strong>: How tied into a tool are you willing to be? For example, Markdown moves easily between tools, but MDX or RST may not. Tool-specific shortcodes or components can also make a future shift complex.</li>
<li class=""><strong>Certain hosting options</strong>: Does it work with GitHub, Netlify, Vercel, or another service your company prefers?</li>
<li class=""><strong>Accessibility</strong>: What are your requirements for accessibility?</li>
<li class=""><strong>Automated deployment pipelines</strong>: How hard will it be to wire it up with linting tools like Vale or link checkers, or automated testing of code samples in CI?</li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-who-can-help-you-when-things-break">5. Who can help you when things break?<a href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs#5-who-can-help-you-when-things-break" class="hash-link" aria-label="Direct link to 5. Who can help you when things break?" title="Direct link to 5. Who can help you when things break?" translate="no">​</a></h2>
<p>Will you be the primary owner of the docs-as-code workflow? If you're not an engineer or highly technical, this is huge. At least in fast-moving startups, time with engineers is precious - you likely want to use whatever time you can get with one to learn more about how the products work, not asking for help to customize the site, update dependencies, or upgrade a framework.</p>
<p>But once in a blue moon, you may run into an issue so far above your head that you will need to beg for engineering help. To prepare for times like that, you may not want to choose a Python-based tool if the engineering department spends most of their days programming in another language.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="in-summary">In summary<a href="https://www.marlasowards.com/blog/how-to-choose-open-source-ssgs#in-summary" class="hash-link" aria-label="Direct link to In summary" title="Direct link to In summary" translate="no">​</a></h2>
<p>When you narrow down on two or three options, run mini POCs with real content. This will give you a great feel for the tool and what it would be like working with it.</p>
<p>This post is based on a requirement for open-source tooling, but consider hosted platforms if it's right. Tools like Mintlify, GitBook or Fern have a lot to offer if the custom configuration and maintenance of an open-source approach doesn't fit your needs.</p>]]></content>
        <author>
            <name>Marla Sowards</name>
        </author>
        <category label="Docs-as-code" term="Docs-as-code"/>
    </entry>
</feed>