<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Blog on Kevin R. Kuhl</title>
    <link>https://www.kevinrkuhl.com/blog/</link>
    <description>Recent content in Blog on Kevin R. Kuhl</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 09 Mar 2026 13:31:00 -0400</lastBuildDate><atom:link href="https://www.kevinrkuhl.com/blog/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Paul Osmon: &#34;Building the Web&#34;</title>
      <link>https://www.kevinrkuhl.com/blog/2026/03/building-the-web/</link>
      <pubDate>Mon, 09 Mar 2026 13:31:00 -0400</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/03/building-the-web/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://paulosman.me/&#34;&gt;Paul Olson&lt;/a&gt; is a software engineer with a background in platform engineering and observability, and is working on an engineer&amp;rsquo;s &lt;a href=&#34;https://paulosman.me/2026/03/05/building-the-web-a-history-of-web-architecture/&#34;&gt;history of web architecture&lt;/a&gt;. Here&amp;rsquo;s how he describes the project:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;The years spanning from 1993 to 2015 were extraordinary. Linux and FreeBSD became mainstream server operating systems, the NCSA httpd project was released, it begat the Apache HTTP server, which in turn inspired projects like nginx. The world saw the birth of a global network for information exchange and its evolution into the substrate of our everyday lives. We went from editing files and placing them in directories on a server to shipping fully containerized applications through complex pipelines. Client-server architecture became three-tiered architecture, eventually morphing into the microservice death star diagrams shared in conference talks as humble brags about the amount of infrastructure required to run large sites. Most of this innovation was done in the open, often by people collaborating across organizational and geographic boundaries. I owe my career to this time period and to the people who shaped it. The amount of knowledge sharing and learning, between practitioners figuring things out the hard way, that has happened during this time period is staggering.&lt;/p&gt;
&lt;p&gt;I’m writing a book detailing the major shifts in web architecture that happened during this time period. Things continued to happen, of course, and 2015 is admittedly a bit arbitrary &amp;mdash; but I chose this timeline because we had containerization and orchestration cemented. Much work that has happened since has been focused on ML / AI, which is out of scope for this project. I’m writing the book because it’s important to illustrate the connective tissue between these developments. It’s also important to appreciate how these contributions were made by practitioners working in specific contexts under specific constraints, and how their innovations compounded &amp;mdash; sometimes unexpectedly. I want to dive into how the industry evolved from stateless web servers serving static documents through the C10K problem, through developments in caching reverse proxies, improvements to OS kernels, experiments with new programming models, infrastructure like CDNs, and beyond. I’ll treat security as a common thread that runs through each chapter, with each innovation addressing some challenges and introducing new attack surface area for others.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;I think these kinds of projects are immensely valuable. Building an account of why things are the way they are, from the perspectives of people working in the trenches can leverage insights that are valuable for future projects. For those of us working in software engineering today, understanding this perspective is a form of architectural forensics. You can&amp;rsquo;t truly understand why a system is complex until you understand the problem it was originally designed to solve.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also valuable for people outside of the world of software &amp;mdash; while Osman&amp;rsquo;s intended audience is engineers, academics really benefit from this sort of undertaking, we can better understand the shape the web is taking when we understand that technologies aren&amp;rsquo;t inevitable, but responses to specific problems.&lt;/p&gt;
&lt;p&gt;The book will be released progressively at &lt;a href=&#34;https://buildingtheweb.dev&#34;&gt;buildingtheweb.dev&lt;/a&gt;, and you can following along by signing up at the site, or using your RSS reader of choice.&lt;/p&gt;
&lt;p&gt;Quick aside &amp;mdash; I’m planning to ramp up the frequency of these posts. There are some big (and very positive) changes in the works professionally. Expect a bit of an adjustment period, followed by a lot more technical deep-dives and interesting links!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Generating Event Feeds with Hugo</title>
      <link>https://www.kevinrkuhl.com/blog/2026/02/generating-events-with-hugo/</link>
      <pubDate>Tue, 10 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/02/generating-events-with-hugo/</guid>
      <description>&lt;p&gt;While I&amp;rsquo;ve been looking for my next professional thing, I&amp;rsquo;ve been working on a community organization side project. The idea is to support a community group with recurring events, allowing people to come together to share skills, knowledge, and build relationships. Ordinary human being stuff.&lt;/p&gt;
&lt;p&gt;But if you&amp;rsquo;ve been following my blog, you know that I have an opinionated view on social media. I&amp;rsquo;m begrudgingly planning on using Instagram to reach people, but I think that organizers and communicators should build things that are independent of major platforms. This lets you pick up and take the resources elsewhere if you need to. And when it comes to distributing information, I like platforms where people can subscribe and control how they get updates &amp;mdash; where users &lt;em&gt;pull&lt;/em&gt; rather than &lt;em&gt;receive&lt;/em&gt;. This means I&amp;rsquo;m not responsible for adding or removing subscribers. You&amp;rsquo;re responsible for subscribing and filtering as a user.&lt;/p&gt;
&lt;p&gt;Meetup is not my favorite platform, though it&amp;rsquo;s widely used. Luma is pretty widespread in the tech community in my area. Eventbrite is also a possibility.&lt;/p&gt;
&lt;p&gt;But I enjoy using Hugo, and I&amp;rsquo;ve already built a script that lets me syndicate blog posts to Bluesky and Mastodon. Building an events calendar in a Hugo site is a natural next step.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Caution!&lt;/strong&gt; This is written for an intermediate Hugo user. You don&amp;rsquo;t have to be an expert, but I&amp;rsquo;m going to move through some details without explaining everything at a beginner level. I&amp;rsquo;m hoping that this will land with people who like building with static site generators. If there&amp;rsquo;s interest for an intro to Hugo post, let me know?&lt;/p&gt;&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;static-site-generators-and-icalendar&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Static site generators and iCalendar
  &lt;a href=&#34;#static-site-generators-and-icalendar&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; is a static site generator. It takes markdown files (with metadata stored as &amp;ldquo;front matter&amp;rdquo; before the content) and generates folders, HTML, and XML that make up your website. It&amp;rsquo;s inexpensive to host and deploy the website, since a visitor is only requesting text and image assets when they visit your site (and maybe some JavaScript). It&amp;rsquo;s quick and (relatively) simple. Most importantly for this project you can define custom output formats that pull data from the front matter of your markdown files.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;iCalendar&lt;/strong&gt; (&lt;a href=&#34;https://en.wikipedia.org/wiki/ICalendar&#34;&gt;Wikipedia&lt;/a&gt; and &lt;a href=&#34;https://icalendar.org&#34;&gt;the spec&lt;/a&gt;) is a standard format for calendar entries. Like most things on computers, &lt;code&gt;.ics&lt;/code&gt; files can be viewed in calendar apps or as plain-text files. Hugo supports the ability to build to custom output formats. Using Google Calendar, Outlook, Thunderbird, or the MacOS calendar app, you can subscribe to URLs that regularly post events. It&amp;rsquo;s kind of like RSS in this respect.&lt;/p&gt;
&lt;p&gt;Using Hugo, I can post all of the following things whenever I plan an event:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A blog post with key event details.&lt;/li&gt;
&lt;li&gt;A corresponding &lt;code&gt;.ics&lt;/code&gt; file so attendees can download the event information and add it to their calendar.&lt;/li&gt;
&lt;li&gt;A corresponding &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2026/02/rss-syndication-and-the-future-of-the-web/&#34;&gt;RSS feed&lt;/a&gt; for my calendar posts, so followers can know when new events are added to the website.&lt;/li&gt;
&lt;li&gt;A corresponding &lt;code&gt;.ics&lt;/code&gt; calendar file, so people can subscribe to the calendar and receive updates in their personal calendars.&lt;/li&gt;
&lt;li&gt;Bluesky and Mastodon posts, using my POSSE script.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a low cost way of getting one-to-many communication where users can opt in and out without having to worry about maintaining a mailing list. If I&amp;rsquo;m using Canva for promotional images for Instagram, I can store the instagram text and images in the same project folders (Hugo &lt;a href=&#34;https://gohugo.io/content-management/page-bundles/&#34;&gt;page bundles&lt;/a&gt;). The website becomes the source of truth for everything I&amp;rsquo;m doing to coordinate events. When I want to promote the event, I can share a QR code for the individual event pages.&lt;/p&gt;
&lt;p&gt;The only part it&amp;rsquo;s missing is tracking attendance and interest. This is not something a static site is particularly well suited to doing. My plan for this is to use some kind of third party form service and monitor engagement with social media accounts. Keeping data collection minimal means that it&amp;rsquo;ll be easier for me as an organizer &amp;mdash; no user accounts or mailing lists to maintain.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;some-technical-details&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Some technical details
  &lt;a href=&#34;#some-technical-details&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hugo uses Go as its templating language. I wouldn&amp;rsquo;t consider myself a Go developer, but the syntax isn&amp;rsquo;t that difficult. We&amp;rsquo;re mostly going to be referencing variables in template files. This lets Hugo build output from your markdown content.&lt;/p&gt;
&lt;p&gt;There are a couple of important technical details that we need to keep in mind about the ICS spec before building this out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Whitespace is structurally significant:&lt;/strong&gt; In Hugo, it&amp;rsquo;s tempting to strip all the whitespace in files to keep things small. In iCal files, properties like &lt;code&gt;BEGIN:VEVENT&lt;/code&gt; have to start on fresh lines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Timezones&lt;/strong&gt;: Calendar apps expect timezones in UTC (with the Z suffix), so when I&amp;rsquo;m setting up the templates and creating event content, I will want to add a validation script that ensures I have valid date-times.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stable UIDs&lt;/strong&gt;: Hugo has a value called &lt;code&gt;.File.UniqueID&lt;/code&gt; that lets me call the UID based on the content file. This way, when I rebuild the calendar, subscribers won&amp;rsquo;t end up with duplicates for each rebuild.&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;implementation-details&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Implementation details
  &lt;a href=&#34;#implementation-details&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;That&amp;rsquo;s the big picture, now I&amp;rsquo;m going to get into the details, starting with how I plan on structuring content for the website, defining site level configuration features, and the custom elements that are necessary to make this work.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;content-structure&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Content structure
  &lt;a href=&#34;#content-structure&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;First, I needed to create a dedicated branch in my content directory. I used a branch bundle (&lt;code&gt;_index.md&lt;/code&gt;) file to apply specific metadata across the entire section, including my new output type:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-YAML&#34; data-lang=&#34;YAML&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Upcoming Events&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;outputs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	- &lt;span style=&#34;color:#ae81ff&#34;&gt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	- &lt;span style=&#34;color:#ae81ff&#34;&gt;RSS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	- &lt;span style=&#34;color:#ae81ff&#34;&gt;ICS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By default, Hugo can output RSS for sections of your site, but it doesn&amp;rsquo;t have templates or resources for creating ICS files. To do this, we&amp;rsquo;ll have to add the output type to the site level configuration, and create template files.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;custom-outputs-and-configs&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Custom outputs and configs
  &lt;a href=&#34;#custom-outputs-and-configs&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Your sitewide configuration is typically handled in &lt;code&gt;hugo.toml&lt;/code&gt; or &lt;code&gt;config.yaml&lt;/code&gt;. To add ICS:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;outputFormats&lt;/span&gt;] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	[&lt;span style=&#34;color:#a6e22e&#34;&gt;outputFormats&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ICS&lt;/span&gt;] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text/calendar&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;baseName&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;events&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;isHTML&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;outputs&lt;/span&gt;] 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;section&lt;/span&gt; = [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;HTML&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;RSS&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ICS&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[&lt;span style=&#34;color:#a6e22e&#34;&gt;minify&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;tdmt&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text/calendar&amp;#34;&lt;/span&gt; = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The media type format is important! This &lt;code&gt;[outputFormats.ICS]&lt;/code&gt; block tells Hugo to build the file with metadata in a way that won&amp;rsquo;t confuse browsers. You need to add the &lt;code&gt;baseName&lt;/code&gt; to ensure that the format picks up the right resources. I also added a line to my config to prevent &lt;a href=&#34;https://ops.tips/blog/minifying-and-bundling-assets-using-hugo/&#34;&gt;minification&lt;/a&gt; for the ICS type. Minification reduces the size of files to make things more streamlined for machines, but this can cause problems with the ICS file type&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;archetypes&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Archetypes
  &lt;a href=&#34;#archetypes&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Archetypes are used by Hugo as a template for new content files in a category. If I add an &lt;code&gt;events.md&lt;/code&gt; file to my &lt;code&gt;archetypes&lt;/code&gt; folder in the project directory, the &lt;code&gt;hugo new events/{event-name}/index.md&lt;/code&gt; command will generate a markdown file from that archetype.&lt;/p&gt;
&lt;p&gt;This lets me standardize the metadata for new event posts to my website, and start filling in the content for an event page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;title: &amp;#34;QFC {{ replace (replace .Name &amp;#34;-&amp;#34; &amp;#34; &amp;#34;) &amp;#34;qfc&amp;#34; &amp;#34;&amp;#34; | title }}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: {{ .Date }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;event_date: {{ .Date }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;event_end: {{ .Date }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;location: &amp;#34;TBD&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;is_virtual: false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;### Event Details
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* **When:** {{ .Date | dateFormat &amp;#34;Monday, Jan 2, 2006&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* **Where:** {{ .Params.location | default &amp;#34;TBD&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the title parameter, I have a replacement block that&amp;rsquo;s using the acronym for the project that I have in mind. The other parameters are filler that will be generated by Hugo. After running the &lt;code&gt;hugo new events/{title}.md&lt;/code&gt; command, I&amp;rsquo;ll need to change the &lt;code&gt;event_date&lt;/code&gt; and &lt;code&gt;event_end&lt;/code&gt; values to those for my event, since currently I&amp;rsquo;m filling that with the current date. As I noted, it is important to handle timezones carefully! When updating the date fields, we need to be sure to include my timezone offset &lt;code&gt;-05:00&lt;/code&gt;, so I can handle that with the Hugo build process.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If I write a validation script, I can specify my timezone, and check both &lt;code&gt;event_date&lt;/code&gt; and &lt;code&gt;event_end&lt;/code&gt; for proper formatting.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The other big thing to bear in mind is whether it is currently daylight savings time. My timezone shifts (&lt;code&gt;-05:00&lt;/code&gt; or &lt;code&gt;-04:00&lt;/code&gt;). Depending on whether it&amp;rsquo;s currently DST. Maybe this is something I can handle with the archetype, but for now, it might be something I&amp;rsquo;d add to the validation script. I&amp;rsquo;m a big fan of using a Python script for local checks before I deploy my Hugo site to the web, so this is something I can tailor around my own needs.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;layouts&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Layouts
  &lt;a href=&#34;#layouts&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Layouts control how Hugo renders different formats when building the site (when you run the &lt;code&gt;hugo&lt;/code&gt; command for your project). To do this, we&amp;rsquo;ll have two separate layouts added to my custom folder.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;calendar-feeds&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Calendar feeds
  &lt;a href=&#34;#calendar-feeds&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;ICS entries have a fairly simple structure. There&amp;rsquo;s an initial block of front matter:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ics&#34; data-lang=&#34;ics&#34;&gt;BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//{Your Name or Org}//Hugo//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME: {Your Calendar Name}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which covers the information about the calendar as a whole &amp;mdash; the product that builds it, scale, it&amp;rsquo;s name, and timezone.&lt;/p&gt;
&lt;p&gt;For individual events, we will want to instruct the layout to build the following for each page in the section:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ics&#34; data-lang=&#34;ics&#34;&gt;BEGIN:VEVENT
UID:
DTSTAMP:
DTSTART:
DTEND:

SUMMARY:
LOCATION:
DESCRIPTION:
URL:
END:VEVENT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And signal the file-end with:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ics&#34; data-lang=&#34;ics&#34;&gt;END:VCALENDAR
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since I&amp;rsquo;m not worried about having a particular place in my site structure for building the ICS files, I&amp;rsquo;m going to define my layout in the &lt;code&gt;_default&lt;/code&gt; folder. This way I could build a calendar for any section. As a Hugo layout (&lt;code&gt;_default/list.ics&lt;/code&gt;), this looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- $pages := .Pages -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BEGIN:VCALENDAR
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VERSION:2.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PRODID:-//Your Name or Org//Hugo//EN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CALSCALE:GREGORIAN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;METHOD:PUBLISH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X-WR-CALNAME:{{ .Site.Title }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ range $pages -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- if .Params.event_date }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BEGIN:VEVENT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UID:{{ .File.UniqueID }}@{{ $.Site.Title | urlize }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DTSTAMP:{{ now.Format &amp;#34;20060102T150405Z&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DTSTART:{{ (time .Params.event_date).UTC.Format &amp;#34;20060102T150405Z&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ with .Params.event_end_date -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DTEND:{{ (time .).UTC.Format &amp;#34;20060102T150405Z&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SUMMARY:{{ .Title | replaceRE &amp;#34;([,;])&amp;#34; &amp;#34;\\$1&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- with .Params.location }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LOCATION:{{ . | replaceRE &amp;#34;([,;])&amp;#34; &amp;#34;\\$1&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DESCRIPTION:{{ .Summary | plainify | htmlUnescape | replaceRE &amp;#34;\n&amp;#34; &amp;#34;\\n&amp;#34; | replaceRE &amp;#34;([,;])&amp;#34; &amp;#34;\\$1&amp;#34; | chomp }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;URL:{{ .Permalink }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;END:VEVENT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- end }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{ end -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;END:VCALENDAR
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve set the calendar name to pull directly from the site title. One of the most critical pieces for a reliable subscription feed is the &lt;strong&gt;UID&lt;/strong&gt;; by using &lt;code&gt;{{.File.UniqueID}}&lt;/code&gt; and programmatically appending the site title, I can ensure that every single entry maintains the same ID across every build. This prevents your calendar app from getting confused and creating a mess of duplicate entries every time I push an update.&lt;/p&gt;
&lt;p&gt;The timezone shift is where things get a bit &amp;ldquo;crunchy.&amp;rdquo; Using &lt;code&gt;DTSTART:{{ (time .Params.event_date).UTC.Format &amp;quot;20060102T150405Z&amp;quot; }}&lt;/code&gt;, the template grabs the date from the front matter and forces it into the &amp;ldquo;Zulu&amp;rdquo; format that general calendar apps expect. This means a timestamp like &lt;code&gt;13:00:00-05:00&lt;/code&gt; gets converted into a computer-readable format, so everyone sees the correct local time regardless of where they are. &lt;code&gt;DTSTAMP&lt;/code&gt; is set to the time that the file was created, so handling is a bit easier.&lt;/p&gt;
&lt;p&gt;I’ve also baked in some filters to handle characters like commas and semicolons, which act as delimiters in ICS files. By automatically adding a backslash to escape them, we prevent the data from being cut off mid-sentence. Similarly, I’m using &lt;code&gt;plainify&lt;/code&gt; to strip out any HTML tags that Hugo might normally generate, keeping the event description simple and in plain text.&lt;/p&gt;
&lt;p&gt;Finally, the layout is very intentional about whitespace. I’ve used hyphens inside the code blocks to surgically strip away extra whitespace and empty lines where they don&amp;rsquo;t belong, while leaving them off structural lines where a fresh newline is required by the spec. A quick &lt;code&gt;chomp&lt;/code&gt; at the end clears out any trailing newlines in the description, ensuring the final output is as lean and spec-compliant as possible.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;events-pages&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Events pages
  &lt;a href=&#34;#events-pages&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hugo uses layouts to also build the default HTML for a list of pages, and the individual pages within the category, we add a similar layout for the individual pages to generate an &lt;code&gt;.ics&lt;/code&gt; file unique for each event.&lt;/p&gt;
&lt;p&gt;The single page layout looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- $event_time := time .Params.event_date -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- $end_time := ($event_time.Add (time.ParseDuration &amp;#34;1h&amp;#34;)) -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- with .Params.event_end_date -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {{- $end_time = time . -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{- end -}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BEGIN:VCALENDAR
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VERSION:2.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PRODID:-//Your Name or Org//Hugo//EN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CALSCALE:GREGORIAN
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;METHOD:PUBLISH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;X-WR-CALNAME:{{ .Title }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BEGIN:VEVENT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UID:{{ .File.UniqueID }}@{{ (urls.Parse .Site.BaseURL).Host }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DTSTAMP:{{ now.UTC.Format &amp;#34;20060102T150405Z&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DTSTART:{{ $event_time.UTC.Format &amp;#34;20060102T150405Z&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DTEND:{{ $end_time.UTC.Format &amp;#34;20060102T150405Z&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SUMMARY:{{ .Title | replaceRE &amp;#34;([,;])&amp;#34; &amp;#34;\\$1&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;LOCATION:{{ (.Params.location | default &amp;#34;TBD&amp;#34;) | replaceRE &amp;#34;([,;])&amp;#34; &amp;#34;\\$1&amp;#34; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;DESCRIPTION:{{ .Summary | plainify | htmlUnescape | replaceRE &amp;#34;\n&amp;#34; &amp;#34;\\n&amp;#34; | replaceRE &amp;#34;([,;])&amp;#34; &amp;#34;\\$1&amp;#34; | chomp }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;URL:{{ .Permalink }}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;END:VEVENT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;END:VCALENDAR
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The biggest change is that I handle the event time using variables. I wanted to include a fall back: by default events will last one hour without a specific end-time. The template tells Hugo to override this default, if it finds a value in the front matter. Why? This ensures that events have the data that some calendar apps expect.&lt;/p&gt;
&lt;p&gt;Otherwise, things are pretty similar to the calendar feed &amp;mdash; since it&amp;rsquo;s for a single page, it doesn&amp;rsquo;t have to loop through the pages that are available in the section.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-not-h-events&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why not h-events?
  &lt;a href=&#34;#why-not-h-events&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The IndieWeb standard for events is &lt;code&gt;h-events&lt;/code&gt;. The central idea is that these are series of standard HTML and CSS elements that allow for interoperability between sites. It&amp;rsquo;s a cool idea &amp;mdash; but it&amp;rsquo;s dependent on people in my target community working with IndieWeb &lt;a href=&#34;https://microformats.org/wiki/h-event&#34;&gt;tools and standards&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Basically you could handle things like RSVPs through &amp;ldquo;web mentions&amp;rdquo;, which enable automatically listing attendees, or these events could appear on IndieMap. It&amp;rsquo;s very cool, but also a little more techy than my target audience. If this was a developer skill-share, where my audience was already a bit more IndieWeb savvy, this would make sense. If I really wanted to do this, I&amp;rsquo;d add this to the layout for the HTML page generated by Hugo.&lt;/p&gt;
&lt;p&gt;The idea of going to an &lt;code&gt;ics&lt;/code&gt; feed is important for reaching people with the devices they have at hand &amp;mdash; they can add the event to their calendar apps.  Extending this to include the &lt;code&gt;h-events&lt;/code&gt; elements in my sites HTML wouldn&amp;rsquo;t be too hard, but it&amp;rsquo;s not necessary for my audience. We&amp;rsquo;re prioritizing connecting with people in an immediate region who use phones, and Outlook and Google Calendar.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-workflow&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The workflow
  &lt;a href=&#34;#the-workflow&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now when I want to add an event to this groups calendar, I do the following things:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hugo new events/qfc-001-welcome-to-qfc/index.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And fill out the relevant details, such as the date, time, venue, etc. I&amp;rsquo;ll also go to my form service to generate an RSVP form so i have a sense for the numbers of attendees and any needs or requests.&lt;/p&gt;
&lt;p&gt;Then I run my build script:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;python build.py
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which builds and deploys the site to its hosting service. Having a build script brings together several command line steps, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clearing the public directory&lt;/li&gt;
&lt;li&gt;Building the site&lt;/li&gt;
&lt;li&gt;Deploying the site to my server&lt;/li&gt;
&lt;li&gt;Running my &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/&#34;&gt;POSSE tools&lt;/a&gt; to syndicate the event to Mastodon and Bluesky&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll still have to promote the event on Instagram, but this way the event is published to my site, including calendar and RSS feeds. Members of the community can add the feed to their calendar apps on their phone, and the event details will be there for them.&lt;/p&gt;
&lt;p&gt;The resulting file directory will look like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├─ public/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|	└── events/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|	   ├─ index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|	   ├─ events.ics            # &amp;lt;--- This is the feed. 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|	   └── qfc-001-welcome-to-qfc/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|	  		├─ index.html
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|	  		└── events.ics          # &amp;lt;--- This is the single event.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you really want to get into content modelling with Hugo, you can define section specific layouts for pages within your calendar (the list and the section page) that include UI elements which link to your calendar. In my project, these live at &lt;code&gt;./layouts/events/list.html&lt;/code&gt; and &lt;code&gt;./layouts/events/single.html&lt;/code&gt; Using the &lt;code&gt;webcal://&lt;/code&gt; protocol for the calendar feed link (instead of &lt;code&gt;https://&lt;/code&gt;)  will prompt users to subscribe to the calendar feed, and they&amp;rsquo;ll receive updates when their calendar app refreshed the feed from your website.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how this is looking in my proof of concept:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2026/02/generating-events-with-hugo/test-event-page.png&#34;
    alt=&#34;A card element from a website, with event details following from emoji, buttons prompting the user to add this event to their calendar, and a text description for a workshop on backpacking&#34; width=&#34;70%&#34;&gt;
&lt;/figure&gt;

&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;repeatability&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Repeatability?
  &lt;a href=&#34;#repeatability&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The initial build out took about an afternoon of playing around and I think it&amp;rsquo;s pretty powerful. Refining it took a bit more time, but I&amp;rsquo;m pretty happy with the results. There&amp;rsquo;s a real problem with event organizers primarily relying on Instagram and Discord in my area, so hopefully more and more folks will look to tooling like Hugo or Ghost to maintain a presence for their groups and events.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re comfortable with building in Hugo, please feel free to use these layouts in your own site. I&amp;rsquo;ve tested it with Thunderbird, Google Calendar, and MacOS applications. If there&amp;rsquo;s enough interest, I can set up a repository that includes templates for an events section on typical Hugo sites.&lt;/p&gt;
&lt;p&gt;One thing I&amp;rsquo;m considering doing with this is creating a &lt;em&gt;playbook&lt;/em&gt;: how to create your own blog and event feed for community organizations. Hugo is a little technical, but I think I could make this repeatable for community organizations. If you couple it with Decap/Static/TinaCMS (as a kind of CMS or even Obsidian and Github Desktop), and Github Actions, this becomes a pretty powerful way to run a community site. I still think it might be a bit too technical in the long run, but I&amp;rsquo;d really like a vibrant collection of local websites that I can tap into using browsers, calendar apps, and RSS readers to distribute information.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re trying to implement this and want to talk about the details, please &lt;a href=&#34;https://www.kevinrkuhl.com/contact/&#34;&gt;reach out to me&lt;/a&gt;!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>RSS, Syndication, and the Future of the Web</title>
      <link>https://www.kevinrkuhl.com/blog/2026/02/rss-syndication-and-the-future-of-the-web/</link>
      <pubDate>Tue, 03 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/02/rss-syndication-and-the-future-of-the-web/</guid>
      <description>&lt;p&gt;My love of RSS is something I&amp;rsquo;m not shy about. I think it&amp;rsquo;s a pretty excellent one-to-many communication tool. But what&amp;rsquo;s interesting is if you look at its history, it had one major flaw (that&amp;rsquo;s also partly why I love it). And in many people&amp;rsquo;s minds, RSS is a dead technology.&lt;/p&gt;
&lt;p&gt;This blog post came directly from a slack discussion with the local tech scene that went a little something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NewsletterAuthor: I&amp;#39;ve migrated my newsletter to Ghost! Here&amp;#39;s the new URL.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Kevin: Oh cool! For those of us using RSS readers, here&amp;#39;s the new feed URL.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;OtherUser: Wait, didn&amp;#39;t Google kill RSS?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, this post is going to be a bit of a &amp;ldquo;what is RSS?&amp;rdquo;, &amp;ldquo;is RSS really dead?&amp;rdquo;, and &amp;ldquo;what&amp;rsquo;s going on with syndication on the internet anyways?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I think we&amp;rsquo;re at an interesting inflection point between a couple of different directions, and we could progress in a way that returns a lot of power to content creators. The pendulum is swinging back to a &lt;strong&gt;utility based economy&lt;/strong&gt; from an &lt;strong&gt;attention based economy&lt;/strong&gt;, and this is a &lt;em&gt;good thing&lt;/em&gt;, even if we&amp;rsquo;re in a moment that&amp;rsquo;s painful for the ad-revenue based paradigm of the 2005-2025 world.&lt;/p&gt;
&lt;p&gt;This post is my potted history of communication technology, and why I think things are improving for individual creators.&lt;/p&gt;
&lt;p&gt;This is a deep dive. Here&amp;rsquo;s the tl;dr:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;RSS isn&amp;rsquo;t dead; it just became the invisible plumbing that powers the entire podcast ecosystem. We &amp;ldquo;killed&amp;rdquo; text RSS because it abstracted away the ads and revenue for blogs and news, but audio RSS was baked in due to bandwidth limits and how listening let creators bake ads into the media (unlike blogs).&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re seeing a migration from walled gardens (Substack) to owned platforms (Ghost) driven by &amp;ldquo;Subscriber RSS&amp;rdquo; &amp;mdash; that lets readers support creators directly while still reading their work in your app of choice (shout out to &lt;a href=&#34;https://www.404media.com&#34;&gt;404 Media&lt;/a&gt; for nailing this).&lt;/p&gt;
&lt;p&gt;The future isn&amp;rsquo;t just humans subscribing, though. With the rise of &amp;ldquo;agentic browsing,&amp;rdquo; AI bots don&amp;rsquo;t look at ads. Instead, they’ll likely use protocols like HTTP 402 to pay micropayments for access to data (or subscription to content APIs or MCPs). The internet is moving from an &lt;em&gt;attention economy&lt;/em&gt; (ads) back to a &lt;em&gt;utility economy&lt;/em&gt; (paid delivery), and protocols are the only way that works.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;what-is-rss&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What is RSS?
  &lt;a href=&#34;#what-is-rss&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;RSS stands for &lt;em&gt;really simple syndication&lt;/em&gt;.  The &lt;a href=&#34;https://en.wikipedia.org/wiki/RSS&#34;&gt;wikipedia article&lt;/a&gt; is a really nice historical introduction to the concept, that goes into the history more carefully. But I want to introduce the concept and a bit of history.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how the internet works, in a really simple kind of lens:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You have a computer, which has a piece of software known as a web browser.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re publishing content to a website, you typically do so in a format for a web browser. It&amp;rsquo;s published as HTML and Javascript (and likely talks to some computers elsewhere for images and other things), which is collected together and rendered as a formatted experience inside of Chrome, Edge, Firefox, Opera, etc. In this case, what&amp;rsquo;s curated for you is the visual experience of a website.&lt;/p&gt;
&lt;p&gt;When I want to see what content you have published on your website, I start up my computer, and I open my browser, and type the address on your website. My browser makes a request to your server, and it returns HTML and Javascript for your website which displays as a page. How this appears is determined by files that describe the overall style of the content (CSS).&lt;/p&gt;
&lt;p&gt;Both of us have the costs of running our computers (electricity, hardware), and costs for sending and retrieving data over the internet.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;But what matters to me as a reader isn&amp;rsquo;t really how you&amp;rsquo;ve chosen to style your writing. In fact, rather than going about making requests to a bunch of servers myself, it&amp;rsquo;d be much nicer for me as a human being if I had an application that would make those requests for me, and I could view the bits that I want, all inside of that app, with uniform styling. If there was a uniform way of building content that apps could read, that would help readers consume content.&lt;/p&gt;
&lt;p&gt;It was an attractive idea back in 1995. But it has evolved a bit over time. The fundamental idea is that you can markup the essential elements of a site using XML and plain text, build that into a feed, which can be retrieved by a separate application or portal. Originally, This was built for use in Netscape, but with Netscape&amp;rsquo;s acquisition by AOL, it has an interesting history of parties trying to revive and maintain the standard.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This history is why Atom, a different standard, similar to RSS was created.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;But basically, as of about 2005, RSS was an initial syndication standard for mainstream technical blogs. Companies like Google were releasing applications that allowed you to save and access lists of RSS feeds viewing content from multiple websites in a single portal, arranged chronologically.&lt;/p&gt;
&lt;p&gt;It became a vital part of how I used the web, reading web comics, blogs, and more. With an RSS reader, I can open up a single page, and see news and posts from multiple sources, organized in a way that lets me direct my attention without distractions.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-murder-of-rss&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The &amp;ldquo;Murder&amp;rdquo; of RSS
  &lt;a href=&#34;#the-murder-of-rss&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I put &amp;ldquo;murder&amp;rdquo; in quotes, since I think RSS survived. More on that later. But a few factors lead to the decline of RSS in the 2010s.&lt;/p&gt;
&lt;p&gt;Google Reader was the most popular RSS reader. It was added to the Google graveyard in 2013. I was using it heavily. But I was also hitting the point where I was seeing too much content in my feed. for  it to be something I could stay on top of. There was definitely a saturation point for blog content.&lt;/p&gt;
&lt;p&gt;So, how does a website make money? After all, it costs money to run a server, and send HTML to all those browsers visiting your pages. The answer was advertisements. By embedding advertisements on your website, you can get paid based on the amount of traffic you have for your website.&lt;/p&gt;
&lt;p&gt;At the same time, social media was rapidly expanding. We were viewing feeds of content about the lives of our friends and family. And that would include news and eventually community pages for people who were trying to build a following. If you ran a media company, you could pay to get traffic directed to your site, but you were also hoping that things you posted would go viral. Traffic would come to your site, and you&amp;rsquo;d be paid based on the number of people who spent time on your site, or clicked on blog posts.&lt;/p&gt;
&lt;p&gt;Marketing was the vehicle which funded content creation and content creators were leveraging social media platforms to get their content to their readers. Cory Doctorow talks about this as the &amp;ldquo;&lt;a href=&#34;https://pluralistic.net/2023/01/21/potemkin-ai/&#34;&gt;enshittification&lt;/a&gt;&amp;rdquo; of platforms.&lt;/p&gt;
&lt;p&gt;Where did this leave RSS and Atom? if your ads were served in Javascript powered widgets on your website, they wouldn&amp;rsquo;t easily be loaded in your content. So maybe you start to truncate the content that makes it into your RSS feed to drive traffic to your website. Or maybe you rely on merchandise sales to support your webcomic or your blog. Gradually speaking, the utility of your RSS reader decreases from a place to read content to a place to drive traffic. Your time is better spent on your social media strategy since social media is getting more and more attention.&lt;/p&gt;
&lt;p&gt;This was the main attack on RSS from companies. Largely one driven by financial incentives, where companies tried to maximize the capture of attention to sell ads and drive revenue growth based on a non-paying user base.&lt;/p&gt;
&lt;p&gt;A major blow was when Google retired &lt;a href=&#34;https://www.theverge.com/2023/6/30/23778877/google-reader-death-2013-rss-social-media&#34;&gt;Google Reader&lt;/a&gt;. There were other readers available, but they often operated on a subscription model to get more fully powered features that let you keep up with scale. Meanwhile, algorithms were getting stronger on Twitter and Facebook, so both discovery and delivery would occur on those platforms. Advertising supported platforms like Feedly, but it wasn&amp;rsquo;t able to grab a significant portion of the user base of Google Reader. Self-hosting was not as popular and RSS became more and more of a curiosity.&lt;/p&gt;
&lt;p&gt;For many people, if they have an RSS feed at all for their website, it&amp;rsquo;s vestigial and they&amp;rsquo;re barely aware it exists. Or you were a bit of a weird legacy tech nerd trying to reach other tech nerds. This was exactly the dynamic that inspired writing this post!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;what-about-audio&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What about audio?
  &lt;a href=&#34;#what-about-audio&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Podcasts are a cool technology. It&amp;rsquo;s interesting to think a bit about why podcasts are the way they are, while other forms of media didn&amp;rsquo;t go this direction.&lt;/p&gt;
&lt;p&gt;The biggest piece of this puzzle is how people were consuming audio vs. text and bandwidth limitations. Back in the days of lower data caps it was common to have a separate device (mp3 player) to listen to music, lectures, or other kinds of long-form audio content. Because your cable or high-speed internet provider had larger data limits than your phone, you could download more audio without running into the hard limits on your smart phone.&lt;/p&gt;
&lt;p&gt;iTunes was a nascent marketplace for music, but there were also people publishing audio content to various websites. RSS readers let you collect updates from those websites. By having an excellent MP3 player, RSS became a way to get an excellent ecosystem of content onto that device, without Apple having to build their own marketplace/database.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://internationalpodcastday.com/podcasting-history/&#34;&gt;RSS and iTunes 4.9&lt;/a&gt; were the key to unlocking this idea. Basically an intermediary app became the way to deliver audio content to your device. Instead of checking for updates, these would be automatically loaded to your device whenever you were charging it via USB at your computer.&lt;/p&gt;
&lt;p&gt;If you wanted your audio to be available to people on their iPods, RSS became an easy way to access that market. It was also easy enough to adapt as mobile internet caught up to delivering audio.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s kind of wild is that podcasting emerged and stabilized largely because of bandwidth concerns. Audio is relatively cheap - hosting and delivering 60 minutes of audio (~50 MB) to 10,000 users is manageable for a server. But 5 minutes of video is 200 MB and the costs of video going viral could bankrupt a company. &amp;ldquo;Vodcasting&amp;rdquo; was almost a thing, but Youtube and Google really altered the trajectory here. That&amp;rsquo;s another story.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also worth remarking on the behavioural differences between audio and video too - video requires visual attention, while podcasts can be listened to on the commute, while on a run, or while doing dishes.&lt;/p&gt;
&lt;p&gt;In a way, audio was perfect for RSS syndication because of its mode of communication, the size of the files, and the variety of devices that could play these files.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-do-podcasts-work-when-blogs-dont&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why do podcasts &amp;ldquo;work&amp;rdquo; when blogs don&amp;rsquo;t?
  &lt;a href=&#34;#why-do-podcasts-work-when-blogs-dont&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a couple of reasons.&lt;/p&gt;
&lt;p&gt;At first glance, it&amp;rsquo;s very tempting to attribute it to attention. When you listen to a podcast, it&amp;rsquo;s more difficult to skip past promotional content.  You listen to the podcast from start to finish.&lt;/p&gt;
&lt;p&gt;The monetization between blogs and podcasts is strikingly similar though. You have the following options really:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Advertisements
&lt;ol&gt;
&lt;li&gt;Paying for views/clicks&lt;/li&gt;
&lt;li&gt;Referral link payout&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Subscriptions&lt;/li&gt;
&lt;li&gt;Sales of merchandise or other services.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;And I&amp;rsquo;ve seen this play out in both blogs and larger podcasting services. I think the biggest reason why podcasts work while blogging fell apart has to do with the portability of attention. Reading a blog post requires visual attention while listening to a podcast can be done on the go.&lt;/p&gt;
&lt;p&gt;if you have to spend time visually attending to your RSS reader and Facebook to get information, and Facebook has teams of PMs, developers, and UX designers building a system to maximize your attention for ad revenue. On the other hand, RSS readers fundamentally abstract away from revenue generating mechanisms, syndication for text was fundamentally doomed.&lt;/p&gt;
&lt;p&gt;The big thing is that in these environments algorithms shape what content is presented to users, and these algorithms are built to maximize ad revenue, which is secured by keeping people on the platform. External links get downgraded, unless it&amp;rsquo;s a service that could be paid for, but then people only really engage with advertisements that are well targeted to them. Basically monetization by advertising revenue could be maximized in an environment where companies could control what you see. And multimedia is a way of grabbing attention.&lt;/p&gt;
&lt;p&gt;Gradually the expansion of multimedia as a means of grabbing attention reduced the share of blogging. These platforms, driven largely by advertising as a means of monetization, began to choke out websites as an economically viable thing. Browsers and operating systems began to have news items baked into the interface, trying to bake attention and advertisements into how you access the web. And news media continued to maintain websites, but they gradually cut off RSS to focus on systems and sources where they could maintain revenue, which was dwindling rapidly. Capital began to aggregate news providers, and quality declined. Generally speaking, things looked pretty grim for people in media.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The actual story is a bit more complicated of course. Microblogging (Twitter/X, followed by Mastodon and Bluesky) was another form of Web2.0 that cut into the world of blogging, and Instagram also played a part. That and TikTok. The relationship of short form video to attention, marketing, and media consumption is a massive topic, but I&amp;rsquo;m going to try and limit this post to talking about writing. After all, I&amp;rsquo;m a writer and blogger.&lt;/p&gt;
&lt;p&gt;Also, I&amp;rsquo;m just going to note that many podcast syndication services now insert ads into audio files based on information from the podcast app being used. Advertising on podcasts is a cool topic in and of itself!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Some countries (notably Australia and Canada) realized that this was pretty bad for the media ecosystem and made attempts to legislate that the social media giants and web platforms contributed to regional media ecosystems.&lt;/p&gt;
&lt;p&gt;This backfired and there were interesting results like garbage collection companies becoming de facto local news, posting short videos and getting engagement on social media. As a Canadian, it&amp;rsquo;s an interesting media landscape. Some of the strongest sources of local news come from perspectives not attached to my local newspaper.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;subscriptions-and-media&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Subscriptions and media
  &lt;a href=&#34;#subscriptions-and-media&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Ok, so newsrooms are failing, bloggers have moved to Instagram, Twitter and Facebook, and social media is thriving on advertisement revenue. There&amp;rsquo;s a bunch of talented writers who are displaced and can build a following, but need to monetize long-form content.&lt;/p&gt;
&lt;p&gt;RSS/Atom are fundamentally ways of syndicating content that emphasizes delivering it to people who want to opt-in. But if you&amp;rsquo;re a creator looking to control who has access to content, they&amp;rsquo;re fundamentally open. If I post an RSS feed to my website, anyone with that URL can add it to their reader.&lt;/p&gt;
&lt;p&gt;But if I build a website that allows me to collect the email addresses of paying subscribers, send them content on a regular basis, and control access to the content, I can get paid and distribute content. This is pretty great. I also get pretty solid analytics on subscriber numbers and readership rates (which helps with selling advertising, if I&amp;rsquo;m doing that). Some people picked up on the viability of offering this as a service to writers who didn&amp;rsquo;t have the technical chops to put together this kind of service (basically gluing together a CMS, payment service, and emailing platform), and recommending similar pieces of writing to grow the audience and subscription base, and voila, we have platforms like &lt;em&gt;Medium&lt;/em&gt; and &lt;em&gt;Substack&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;These platforms can use their aggregated audiences and consumers to drive profitability, paying and supporting star writers, and subsidizing the service for smaller writers. They&amp;rsquo;re an interesting revival of monetized blogging, and are probably the most popular/widespread means of sharing writing for journalists.&lt;/p&gt;
&lt;p&gt;Since writers need to build audiences, they use these newsletter platforms for syndication and subscription management, while building the audience through microblogging services, podcasts, and video media. &lt;a href=&#34;https://disconnect.blog/ghosting-substack/&#34;&gt;Here&amp;rsquo;s Paris Marx talking about his journey with finding a provider for his newsletter&lt;/a&gt; (hoping that there would be network effects) and why he left (due to association with less politically savory folks and &amp;ldquo;profit pressure&amp;rdquo; making the environment less friendly to creators). We&amp;rsquo;ll come back to Ghost, but I think it&amp;rsquo;s really important to note that there are both platforms and self-hosted tools that let you build newsletters&lt;/p&gt;
&lt;p&gt;The core tension is this: email isn&amp;rsquo;t really a preferred way to read long form articles, and accessing a site through log-in can be a bit of a pain for users. So authors need a way to control access to their content, while users want an easy pipeline to consume content. Newsletters let authors syndicate and manage. Feed readers and email providers become the way we choose to consume the content.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s interesting to watch, currently, how podcasting is faring in this current technological landscape. Spotify is an audio streaming platform that has started to pay high profile podcasters to get their audience onto the platform. Some podcasters monetize by offering premium subscription tiers with bonus content. Others form into networks or rafts of related podcasts to share advertising revenue.&lt;/p&gt;
&lt;p&gt;In a real sense, the challenges of monetization for podcassts are the same that are being faced by bloggers. Which is why we see similar kinds of things happening to podcasters as in the latter days of blogging. Blog networks, subscription-based content, and membership communities are all strategies to build that revenue in ways that close the ecosystem off.&lt;/p&gt;
&lt;p&gt;This tension will likely shape the media to come. So I want to talk about three trends that are breaking away from this landscape and where I think we&amp;rsquo;re headed.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;three-trends&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Three trends
  &lt;a href=&#34;#three-trends&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I think there&amp;rsquo;s three main trends for how the internet is evolving after Web 2.0 (I&amp;rsquo;m not going to talk about &lt;a href=&#34;https://en.wikipedia.org/wiki/Web3&#34;&gt;Web3&lt;/a&gt; because of &lt;a href=&#34;https://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;rct=j&amp;amp;opi=89978449&amp;amp;url=https://www.web3isgoinggreat.com/&amp;amp;ved=2ahUKEwjkpuLq3LORAxXPDjQIHcrCK4QQFnoECCYQAQ&amp;amp;usg=AOvVaw1hJXeD2PRXtPMlUdGithJx&#34;&gt;reasons&lt;/a&gt;):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Paid syndication outside of email &amp;mdash; 404, Aftermath, and self-hosted newsletters.&lt;/li&gt;
&lt;li&gt;Algorithmic choice and federated social media &amp;mdash; Bluesky and Mastodon.&lt;/li&gt;
&lt;li&gt;Paid access for crawlers &amp;mdash; Cloudflare and generative AI-powered browsers.&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;a-look-at-breaking-away-from-platforms-404-media-and-paid-rss&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;A look at breaking away from platforms: 404 Media and paid RSS
  &lt;a href=&#34;#a-look-at-breaking-away-from-platforms-404-media-and-paid-rss&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So platform subscription services are falling victim to the usual profitability pressures. Here&amp;rsquo;s what I think is a useful model going forward: It&amp;rsquo;s becoming easier and easier to host and publish your own content to the web. While I use a fairly technically hands-on stack, it&amp;rsquo;s entirely possible to self-host a newsletter service for something comparable to paid hosting services. The overall challenge is balancing the cost of hosting against revenue coming in. And if I were trying to monetize this blog, I wouldn&amp;rsquo;t want to use invasive advertising. I&amp;rsquo;d either move to a platform that could handle subscription payments, or I&amp;rsquo;d look at some kind of passive sponsorship from a very specific sort of advertiser (rather than using traditional Web2 ad markets). Rather than rely on a network, I&amp;rsquo;d keep it at its own URL. Maybe it wouldn&amp;rsquo;t be successful, but if I have to enter into an agreement, I want it to reflect my brand the whole way down.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://ghost.org/&#34;&gt;Ghost&lt;/a&gt; is a newsletter platform/CMS that is free-to-use. Many of it&amp;rsquo;s themes are optimized for newsletters, but you can easily use it to run something between a blog and newsletter. You&amp;rsquo;ll need to deploy a server and DNS, but in theory, you can use it without paying the creators directly. If you don&amp;rsquo;t want to muck about with that, you can also use their hosting (which has multiple paid subscription tiers based on the size of your audience). Either way, you own your own content, and can use your own domain name. As a newsletter service, you can break your content into publicly available, and available to subscribers. Posts can be sent to subscribers. And by default, it has RSS feeds enabled.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.404media.co/&#34;&gt;404 Media&lt;/a&gt; is a collective of tech journalists that previously worked for companies like Vice Media. They do high quality reporting on technology and society. And when Vice began to contract, they got together to create a small, independently owned site driven by subscriber access.  Since they have an audience that is engaged and technologically focused, they had readers that use RSS readers to consume news from a variety of sources, and that forcing paying subscribers to log into a website is a poor user experience.&lt;/p&gt;
&lt;p&gt;The solution is &lt;a href=&#34;https://www.404media.co/404-media-now-has-a-full-text-rss-feed/&#34;&gt;a &amp;ldquo;tokenized&amp;rdquo; RSS feed&lt;/a&gt;. When you subscribe to 404 Media, you get a unique, private RSS URL (e.g., &lt;code&gt;404media.co/feed/unique_token_123&lt;/code&gt;). This feed delivers full-text articles bypassing the paywall because the URL &lt;em&gt;is&lt;/em&gt; the key. If you cancel your subscription, they stop posting the feed to the URL.&lt;/p&gt;
&lt;p&gt;This stack uses Ghost, plus a stack that handles subscriptions and the management of tokenized feeds. And it&amp;rsquo;s cool to see this approach spreading to other collectives of journalists, such as &lt;a href=&#34;https://aftermath.site/&#34;&gt;Aftermath&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s great about this model is that it respects the users choice of reading environment, while protecting creator revenue. It treats the RSS reader as a first class citizen, not a pirating tool. As a user, this feels good. I know that I&amp;rsquo;m paying the creators directly for their content, but it&amp;rsquo;s quiet. I can review and see all the content from the site in an environment I have control over. It determines my pace of consumption and access, and I can rave and review things without the noise and intrusion of notifications from a social media interface.&lt;/p&gt;
&lt;p&gt;It also allows the platform to own or control more of the stack. They decide which authors are publishing within the site (unlike Medium or Substack). It is a bit of an epicycle on the idea of subscription content, but I think it moves the needle forward for both readers and creators.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;bluesky-and-algorithmic-choice&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Bluesky and algorithmic choice
  &lt;a href=&#34;#bluesky-and-algorithmic-choice&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If RSS is &amp;ldquo;build my own subscription algorithm&amp;rdquo; and Twitter/X is &amp;ldquo;consume what the algorithm feeds me&amp;rdquo;, Bluesky &lt;a href=&#34;https://bsky.social/about/blog/3-30-2023-algorithmic-choice&#34;&gt;tries to find the middle ground&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Under the hood, Bluesky runs on &lt;a href=&#34;https://atproto.com/&#34;&gt;ATProto&lt;/a&gt;, which shares an outlook with RSS. It&amp;rsquo;s an open data standard for social media posts. On Twitter/Instagram/Facebook, your feed is a black box optimized to make you buy things. On Bluesky, the &amp;ldquo;algorithm&amp;rdquo; is just another feed that you can subscribe to. People build and maintain feeds with names like &amp;ldquo;Tech News&amp;rdquo;, &amp;ldquo;Cat Photos&amp;rdquo; or &amp;ldquo;Mutuals Only&amp;rdquo;. An open standard lets different federated servers share content, so in theory, you could have a separate app talk with Bluesky and you could access content from other services on Bluesky itself. It&amp;rsquo;s a seriously cool break from platform lock-in.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s possible to define your own feeds and lists, and switch between them. I&amp;rsquo;m subscribed to a local posters feed for the Waterloo Region.  But the core idea is that curation is in your hands as a user, while you can still access a firehose of general content structured via ATProto. It&amp;rsquo;s syndication, with a customizable filter on top.&lt;/p&gt;
&lt;p&gt;In addition to syndication, it&amp;rsquo;s possible to have your own servers which integrate with other publicly available ATProto servers. Mastodon is similar in scope and provision, with ActivityPub playing a similar role to ATProto, and a more diverse range of servers available for users to post on.&lt;/p&gt;
&lt;p&gt;The catch with Bluesky or Mastodon is that it they are emerging frameworks: to get up to speed with using either (or developing on ATProto/ActivityPub) is more involved than traditional Web2.0 use.  Still, it&amp;rsquo;s open and not too hard to work with. I&amp;rsquo;ve built a syndication script for this site, and found creating a client and making a post is straightforward. The development hurdles for LinkedIn, Reddit, or Twitter have all become more difficult (rate limiting, stricter auth requirements, and limited development programs etc.).&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;cloudflare-ai-and-paid-access&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Cloudflare, AI, and paid access
  &lt;a href=&#34;#cloudflare-ai-and-paid-access&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If I look at the traffic for this site, it&amp;rsquo;s overwhelmingly from Ireland. Maybe I have a dedicated readership from there, but I think it&amp;rsquo;s much more likely that web crawlers accessing my site are hosted in data centres in Ireland (If I&amp;rsquo;m wrong, shout out to my Irish audience &amp;mdash; you&amp;rsquo;re one of my favourite Eurovision countries). The rise in web crawler traffic driven by the proliferation of generative AI shapes the fundamental economics of running high traffic websites.&lt;/p&gt;
&lt;p&gt;I pay pennies per month for hosting this site, but for higher traffic sites, this becomes as much of a cost/bandwidth issue as video was for RSS. If social media discovery killed ad revenue for news sites, the expansion of machines crawling their content will be even worse. Crawlers increase traffic, but don&amp;rsquo;t generate meaningful ad revenue.&lt;/p&gt;
&lt;p&gt;And this is just the early days of machine driven interaction with sites. I don&amp;rsquo;t know whether &amp;ldquo;generative AI-powered browsers&amp;rdquo; will take off, but the idea is that generative AI-powered tools will browse the web for us, acting like an interface for the content posted on websites. They don&amp;rsquo;t look at ads, they don&amp;rsquo;t buy merchandise (or at least I don&amp;rsquo;t want AI doing that for me). They extract information and present it to readers in a way that is more focused than the noisy world of Web2. It&amp;rsquo;s natural to prefer the experience of a focused chain of messages with an LLM over the noisy clutter of Twitter or Facebook. It&amp;rsquo;s part of why I like RSS!&lt;/p&gt;
&lt;p&gt;If the web is funded by ads and the &amp;ldquo;users&amp;rdquo; incurring costs ignore ads, the economic model collapses.&lt;/p&gt;
&lt;p&gt;Enter &lt;code&gt;HTTP:402: Payment Required&lt;/code&gt; (&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/402&#34;&gt;It&amp;rsquo;s an old idea!&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;This is an old mostly unused web standard that companies are talking about reviving. The idea is simple. When a crawler hits your site, instead of blocking it, or showing ads that won&amp;rsquo;t reach a human, your server asks for a micro-payment. Basically it says &amp;ldquo;If you want to scrape this blog post to summarize it for a user, please pay me a $0.01&amp;rdquo;. This payment is transferred via a digital wallet, and the server delivers the content in a machine readable format (typically JSON/Markdown).&lt;/p&gt;
&lt;p&gt;In a sense, this is an evolution of paid RSS. The idea is that my hosting service provides content to the consuming service for a fee, with no ad-tech middlemen.  It&amp;rsquo;s being heavily discussed and implemented by providers like &lt;a href=&#34;https://blog.cloudflare.com/introducing-pay-per-crawl/&#34;&gt;Cloudflare&lt;/a&gt;. Also, I could build an MCP for interacting with my site that includes rate limits and subscription requirements for access to my content. When an agent attempts to interface with the site through the MCP, they&amp;rsquo;re rejected without a subscription. The question really becomes one of scale, utility, and access.&lt;/p&gt;
&lt;p&gt;There are difficulties and problems for this route, and there are risks of technological capture by providers like Cloudflare. It also leaves me wondering about whether this is closing off the old ideas of the open web, but we also have to navigate handling costs for hosting and creating content.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;summary&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Summary
  &lt;a href=&#34;#summary&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;It has been an interesting historical moment. Not just because of the massive social and political upheavals that are going on, but because we&amp;rsquo;re reaching the breaking point of the Web 2.0 paradigm.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve spent 20 years trying to fund the web with human attention and we ended up with a surveillance economy that feels unsustainable. I think the future consists of a mix of tools for discovery and paying for the content that you want to support or use, and I think we&amp;rsquo;ll see a mixture of self-funded projects supported by 402 payments for machine access, tokenized RSS feeds, and self-owned newsletter services.&lt;/p&gt;
&lt;p&gt;If we&amp;rsquo;re drifting away from the fully open web, I&amp;rsquo;m okay with that. I&amp;rsquo;d much rather an honest, utility driven system of communication. We should give more power to creators and consumers of media, that preserves our attention.&lt;/p&gt;
&lt;p&gt;And best of all, it&amp;rsquo;s going to be built on plumbing that works.*&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Ok, there&amp;rsquo;s a lot of messy, competing protocols here and I&amp;rsquo;m being a little optimistic. But I do think that there&amp;rsquo;s a fighting chance for the internet at the moment.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Anil Dash: &#34;How Markdown Took Over the World&#34;</title>
      <link>https://www.kevinrkuhl.com/blog/2026/01/dash-how-markdown-took-over/</link>
      <pubDate>Mon, 12 Jan 2026 14:01:16 -0500</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/01/dash-how-markdown-took-over/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://daringfireball.net/projects/markdown/&#34;&gt;Markdown&lt;/a&gt; is pretty cool. It&amp;rsquo;s flexible, comes in different flavours, and it&amp;rsquo;s everywhere. Anil Dash goes into the history of markdown and blogging (and some of my problems with CMSes) in &lt;a href=&#34;https://www.anildash.com/2026/01/09/how-markdown-took-over-the-world/&#34;&gt;his latest post&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;Because sometimes those writers would inspire us to make a new feature in the publishing tools, and sometimes they would have hacked up a new feature all by themselves in between typing up their new blog posts.&lt;/p&gt;
&lt;p&gt;A really clear, and very simple, early example of how we learned that lesson was when we changed the size of the box that people used to type in just to create the posts on their sites. We made the box a little bit taller, mostly for aesthetic reasons. Within a few weeks, we’d found that posts on sites like Gawker had gotten longer, mostly because the box was bigger. This seems obvious now, years after we saw tweets get longer when Twitter expanded from 140 characters to 280 characters, but at the time this was a terrifying glimpse at how much power a couple of young product managers in a conference room in California would have over the media consumption of the entire world every time they made a seemingly-insignificant decision.&lt;/p&gt;
&lt;p&gt;The other dirty little secret was, typing in the box in that old blogging app could be… pretty wonky sometimes. People who wanted to do normal things like include an image or link in their blog post, or even just make some text bold, often had to learn somewhat-obscure HTML formatting, memorizing the actual language that’s used to make web pages. Not everybody knew all the details of how to make pages that way, and if they made even one small mistake, sometimes they could break the whole design of their site. It made things feel very fraught every time a writer went to publish something new online, and got in the way of the increasingly-fast pace of sharing ideas now that social media was taking over the public conversation.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;Anyways, there&amp;rsquo;s some interesting context with things I&amp;rsquo;ve been mulling over (for another blog post that I&amp;rsquo;m revising, but should be out soon), including Aaron Schwarz, RSS, podcasts, etc.&lt;/p&gt;
&lt;p&gt;Dash&amp;rsquo;s entire post is a strong reminder that the literal skeleton that defines modern AI infrastructure, started as a conversation between a blogger and a teenager. Powerful tools are built for humans, by humans.&lt;/p&gt;
&lt;p&gt;But I do think what&amp;rsquo;s really powerful is this section:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;The people who make the real Internet and the real innovations also don’t look for ways to hurt the world around them, or the people around them. Sometimes, as in the case of Aaron, the world hurts them more than anyone should ever have to bear. I know not everybody cares that much about plain text files on the Internet; I will readily admit I am a huge nerd about this stuff in a way that maybe most normal people are not. But I do think everybody cares about some part of the wonderful stuff on the Internet in this way, and I want to fight to make sure that everybody can understand that it’s not just five terrible tycoons who built this shit. Real people did. Good people. I saw them do it.&lt;/p&gt;
&lt;p&gt;The trillion-dollar AI industry&amp;rsquo;s system for controlling their most advanced platforms is a plain text format one guy made up for his blog and then bounced off of a 17-year-old kid before sharing it with the world for free. You&amp;rsquo;re welcome, Time Magazine&amp;rsquo;s people of the year, The Architects of AI. Their achievement is every bit as impressive as yours.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;If you love the internet, the whole piece is an excellent read (including the 10 reasons markdown was successful). It&amp;rsquo;s also worth following John Gruber over at &lt;a href=&#34;https://daringfireball.net/&#34;&gt;Daring Fireball&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Thoughts on Designing Automation</title>
      <link>https://www.kevinrkuhl.com/blog/2026/01/thoughts-on-designing-automation/</link>
      <pubDate>Mon, 12 Jan 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/01/thoughts-on-designing-automation/</guid>
      <description>&lt;p&gt;Automations are great.  It&amp;rsquo;s pretty cool to explore building them. And it&amp;rsquo;s exhillarating when it works.&lt;/p&gt;
&lt;p&gt;This is the appeal behind &lt;a href=&#34;https://factorio.com/&#34;&gt;Factorio&lt;/a&gt;, a game entirely about building and optimizing supply chains. It&amp;rsquo;s addictive watching your expanding world of conveyor belts, resource extraction, and processing facilities. Building the &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/&#34;&gt;POSSE script&lt;/a&gt; for this website has felt similar.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easier than ever for workers in the knowledge economy to build automation into their workflows. As knowledge workers, we often build automations to save time, but without intentional design we inadvertently build systems that make demands on &lt;em&gt;us&lt;/em&gt;. When you propose some kind of automation, people will respond to it based on how that system can be deployed in a context where it&amp;rsquo;s used to accelerate and coordinate work. This post is a call to consider the human element when we&amp;rsquo;re building and promoting automation.&lt;/p&gt;
&lt;p&gt;I have no training in automation or design theory, but I think there&amp;rsquo;s two properties that can frame how we think of building automations: &lt;em&gt;legibility&lt;/em&gt; and &lt;em&gt;intrusion&lt;/em&gt;. I&amp;rsquo;ll talk about some design patterns along the way &amp;mdash; trying to illustrate ways in which these features matter for &lt;em&gt;human experience&lt;/em&gt;. And I&amp;rsquo;ll conclude with why this is important for our current moment: discussions about improving efficiency are dominated by &lt;em&gt;tinkerers&amp;rsquo; tunnel vision&lt;/em&gt;. Building things can be so exciting that we forget that we&amp;rsquo;re building systems and shaping practices and expectations for how we work.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;centaurs-and-reverse-centaurs&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Centaurs and reverse centaurs
  &lt;a href=&#34;#centaurs-and-reverse-centaurs&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Cory Doctorow has a helpful framing of automation in terms of &lt;a href=&#34;https://pluralistic.net/2025/12/05/pop-that-bubble/#u-washington&#34;&gt;centaurs and reverse centaurs&lt;/a&gt;. The basic idea is that some automations &lt;em&gt;assist&lt;/em&gt; humans, and the experience of using them is empowering or thrilling. You function as a human head on a tireless machine body, and you&amp;rsquo;re able to do more, move more quickly. A reverse centaur is the opposite &amp;mdash; a technology or system that demands (or controls) human inputs to produce optimized outputs. In this situation, the experience is reversed. You are dragged along, trying to keep up at the pace or quality of outputs that the system demands.&lt;/p&gt;
&lt;p&gt;His most helpful example is in terms of &lt;em&gt;assistive driving technologies&lt;/em&gt;. They can aid with driving more safely or efficiently (e.g., blind spot detection, cruise control). But they can also treat the driver as something to be &lt;em&gt;measured&lt;/em&gt; and &lt;em&gt;optimized&lt;/em&gt;, like monitoring a driver&amp;rsquo;s eyes and deducting points from their rating if the driver doesn&amp;rsquo;t pay attention on the road. On the reverse-centaur model, human effort is something to be modified by the system, while on the centaur model, the driver is augmented by the device.&lt;/p&gt;
&lt;p&gt;These categories are about the relationship of the automation to the person. Is it aiding their tasks, or demanding and shaping their effort in a particular way? We can distill these models to two design patterns&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Centaurs&lt;/strong&gt;: An automation that lets you complete a task more quickly. It &lt;strong&gt;accelerates&lt;/strong&gt; your velocity when working on tasks, you are a human &lt;strong&gt;augmented&lt;/strong&gt; by the machine.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reverse Centaurs&lt;/strong&gt;: An automation where the machine treats human effort as a demand/input for accelerated output. It &lt;strong&gt;generates&lt;/strong&gt; demands that users &lt;strong&gt;must conform&lt;/strong&gt; to, and the &lt;strong&gt;human&lt;/strong&gt; augments the &lt;strong&gt;system&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Design patterns are ways that automations can be shaped. One of the lessons from the assistive driving technology example is that this shape isn&amp;rsquo;t about the immediate things that the technology offers to users, but about the ways that they can be embedded in broader social systems. Part of the experience is about how automations treat the humans using them.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;legibility-and-intrusion&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Legibility and intrusion
  &lt;a href=&#34;#legibility-and-intrusion&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I think there are two key properties of automations that shape our experience with them. If I create a bash script, I’m immediately familiar with its logic and in full control of when it runs. If I’m working in Salesforce or a complex system of Zaps, I might be completely unfamiliar with the definitions and conditions of flows that generate notifications or tasks for me to complete. These examples differ in terms of the legibility of the automations and how intrusive they are for me. My script is extremely legible: I wrote and determined its logic. But it’s also intrusive: I have to run the script in my terminal. The background flows which send an email are the opposite: their logic is hidden and it’s minimally intrusive. I may not even be aware that someone is notified.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what I mean by these two terms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Legibility&lt;/strong&gt;: Can the user see the &amp;ldquo;Why&amp;rdquo; and the &amp;ldquo;How&amp;rdquo; behind the automation? Does the user have the ability to adjust those elements, or incorporate this into their approach for the task?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intrusion&lt;/strong&gt;: Does the system force a stop or change in the user&amp;rsquo;s path? Does it demand effort as an input before the output can proceed?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I want to stress that degree of control over the system is part of its &lt;em&gt;legibility&lt;/em&gt; and &lt;em&gt;intrusion&lt;/em&gt; is a measure of the effort and quality of how the system intrudes on a user’s experience or flow.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of legibility: A &lt;em&gt;continuously variable transmission&lt;/em&gt; (CVT) in a car engine is low legibility and low intrusion. It transforms mechanical energy and simulates shifts, but you only need to put the car into drive before you stop thinking about it in operation. It is background mechanical infrastructure. A bicycle&amp;rsquo;s gearing system is both high legibility (you can literally see the parts) and higher intrusion (users must select the gear), even though it has a similar function. It feels like a tool that you need to use and efficient use requires &amp;ldquo;how-to&amp;rdquo; knowledge. Both systems are &lt;em&gt;empowering&lt;/em&gt; &amp;mdash; they enable users to effectively transform mechanical energy. Where they differ is in terms of legibility.&lt;/p&gt;
&lt;p&gt;For a system to be centaur-like, the intrusiveness of the system must function in a way that&amp;rsquo;s engineered to empower the user. Low intrusion systems are more likely to be centaur-like. Cruise control eliminates the cognitive load for managing your velocity. Blind-spot assist is intrusive in a way that prevents drivers from making errors of judgment. Driver rating systems are intrusive in a way that allows managers/insurance companies to use incentives to encourage conformance. The scores and their impact on employment/prices are intrusive in much deeper ways than a blind-spot alert and they are often low legibility (especially with regard to how and what is being monitored). Reverse-centaurs are organized in a way that structures the end result without regard for how people enter into the system.&lt;/p&gt;
&lt;p&gt;We can think about this in terms of a two by two matrix:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Low Legibility&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;High Legibility&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Low Intrusion&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Background infrastructure.&lt;/strong&gt; Background processes that just work.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Assistive Aids.&lt;/strong&gt; Systems that provide signal, adjust outputs, etc. without force or effort.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;High Intrusion&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Reverse-centaurs.&lt;/strong&gt; Systems that demand increased outputs or compliance with opaque rules.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Tools, Frameworks.&lt;/strong&gt; Systems that require effort but offer control and clear insight into their logic.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If a system is highly intrusive but low legibility, it feels like a &lt;em&gt;demand&lt;/em&gt;. If it’s high intrusion with high legibility (like the bike gears), it can feel like a &lt;em&gt;tool&lt;/em&gt; or &lt;em&gt;framework&lt;/em&gt;.  The difference is whether the user understands the &amp;lsquo;why&amp;rsquo; behind the friction. If it&amp;rsquo;s low legibility and low intrusion, it feels like &lt;em&gt;background infrastructure&lt;/em&gt;. If it&amp;rsquo;s high legibility and low intrusion it feels like an &lt;em&gt;aid&lt;/em&gt;.  Fundamentally, reverse-centaurs are lower legibility, high intrusion &amp;mdash; when an automation demands a higher standard or an accelerated pace of work, that harms its legibility. Centaurs can occupy a range of other spaces: but most often, they&amp;rsquo;re high legibility and low intrusion.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;types-of-automation&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Types of automation
  &lt;a href=&#34;#types-of-automation&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If we think of work as getting a bunch of tasks to be done with specific outputs, we can begin to think of automations as things that help us identify tasks, schedule and perform those tasks, clean-up after tasks, and alert us to when things are done. The ways we build and design these things can vary in the legibility/intrusion dimensions.&lt;/p&gt;
&lt;p&gt;In this model, there are two fundamental types of automation:&lt;/p&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;&lt;strong&gt;Gates&lt;/strong&gt;: Prevent work from going out unless they meet some kind of condition or standard, they can also prevent the reverse centaurs from swamping you. They can also filter or limit inputs into the work process. Gates provide &lt;strong&gt;prevention&lt;/strong&gt; and &lt;strong&gt;control&lt;/strong&gt;. Gates range in intrusiveness and legibility, but generate intrusion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cogs&lt;/strong&gt;: Work inside of a machine, smoothing out friction without intruding on the user experience directly. They can transform energy, change a thing, or generate new output. Cogs are the &lt;strong&gt;engine&lt;/strong&gt; that maintains velocity or acceleration. Typically, cogs are lower intrusion, and range in legibility.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These are similar to the basic elements of a programming language: &lt;strong&gt;functions&lt;/strong&gt; and &lt;strong&gt;control statements&lt;/strong&gt;. You can build arrangements of gates and cogs to perform more complex functions. Bash, Python, Salesforce Flows, n8n, are all pretty much the same in this respect. As design patterns, they are the basic atoms that let us build more complex systems.&lt;/p&gt;
&lt;p&gt;Some of the more complex systems include:&lt;/p&gt;
&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;&lt;strong&gt;Sentinels&lt;/strong&gt;: Put a cog after a gate so that something happens when a condition is met. The basic idea behind this is a notification system. Sentinels provide warnings. They may or may not prevent the machine from running off course. If the end goal of a sentinel is adjusting human behaviour, it&amp;rsquo;s higher intrusion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gardeners&lt;/strong&gt;: Run on a schedule or condition to delete, prune, archive, or organize. They prevent cogs and reverse-centaurs from overwhelming you (a script that cleans up my screenshots). Think pruning shears. They might have moderate to high legibility, but lower intrusion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bridges&lt;/strong&gt;: Transform information, data, tasks, or other inputs between forms. (Pandoc or ETL scripting). Typically lower intrusion and variable legibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Distillers&lt;/strong&gt;: Take a feed or stream of information and provide summaries that are useful for users. Reports and dashboards are the main examples. They extract signals from noise. Low intrusion, high legibility.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Squires&lt;/strong&gt;: Perform set up before you start a task. Package managers, tools to create virtual environments environments, etc. Typically lower intrusion, high legibility.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These aren&amp;rsquo;t exhaustive, but I think they&amp;rsquo;re helpful for getting an idea of how far this metaphor can run. One thing that&amp;rsquo;s important is that these metaphors all have an element of responsibility &amp;mdash; this comes from the idea of the task having a functional goal. In my own approach to docs-as-code, I have &lt;em&gt;distillers&lt;/em&gt; (spellcheck, Vale), &lt;em&gt;gardeners&lt;/em&gt;, &lt;em&gt;sentinels&lt;/em&gt;, and &lt;em&gt;squires&lt;/em&gt; squished into a build and deploy script, and the static site generator functions as a &lt;em&gt;bridge&lt;/em&gt; between markdown and published HTML.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the thing I&amp;rsquo;m going to argue for in this post. We can build automations out of gates and cogs, it tells us nothing about where we fall on the centaur/reverse-centaur axis. This is because I believe that technology has a fundamentally social aspect to it &amp;mdash; technology (including automations) requires that we coordinate and prescribe tasks between human beings.&lt;/p&gt;
&lt;p&gt;We often think about building automations in isolation. There is a task that I&amp;rsquo;m doing and the automation I&amp;rsquo;ve created eliminates performing that task for myself.  Since it accelerates what I&amp;rsquo;m doing, it&amp;rsquo;s exciting and good. This is what I&amp;rsquo;m calling &lt;em&gt;tinkerer&amp;rsquo;s tunnel vision&lt;/em&gt;. It can lead to a range of results, some good, some bad. Let’s use Vale as an example.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;implementing-vale&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Implementing Vale
  &lt;a href=&#34;#implementing-vale&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href=&#34;https://vale.sh/&#34;&gt;Vale&lt;/a&gt; uses syntactic pattern matching to check whether HTML or markdown conforms to a style guide. You can define and extend sets of rules and check for things like passive voice, common misspellings or typographic errors, and whether or not you&amp;rsquo;ve used title case or sentence case for headings. It&amp;rsquo;s catnip for technical writers who want to ensure that their articles meet certain quality standards and are happiest working in a docs-as-code environment. You can tinker with regex to generate suggestions, warnings, and errors.&lt;/p&gt;
&lt;p&gt;It can be run in the command line and a really common way of using it is as a &lt;em&gt;gate&lt;/em&gt;. As part of the process for deploying your site, you require that a branch passes the relevant checks. You can also run the command whenever you work on a file in your command line interface. And there&amp;rsquo;s &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=ChrisChinchilla.vale-vscode&#34;&gt;an extension for VS Code&lt;/a&gt; that gives you live feedback as you work.&lt;/p&gt;
&lt;p&gt;Is it a tool that makes you a centaur or a reverse-centaur? Well, that depends. Though I think it largely feels like a centaur. Consider these three ways you can use Vale:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The empowered contributor&lt;/strong&gt;. Vale is implemented as a CI/CD gate and the writer is able to use the VS Code extension while they work to get live feedback as they write. It will be rare that they submit any pull requests to be merged with style guide violations since it&amp;rsquo;s available both as a final check and as an assistive tool.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The demanding oracle&lt;/strong&gt;. Contributors may be aware of the style guide, but they are responsible for meeting the Vale check, but they are not provided the relevant style files or assistive tools aside from the CI/CD check, and instead must adapt their behaviour to conform to the style guide based on their ability to learn the system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The sorcerer’s apprentice&lt;/strong&gt;. An automation is set up that generates Jira tickets based on Vale output. We set up a new style guide, and run the script for every page on our site. This generates a massive backlog of content that must be brought into alignment with the new style guide.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The demanding oracle isn&amp;rsquo;t a good way to implement the tool: it&amp;rsquo;s a fundamentally flawed approach to developer experience or a culture of trust. It isn&amp;rsquo;t a good experience precisely because of how the &lt;em&gt;social organization&lt;/em&gt; around the tool is structured. That is, the demanding oracle is a perfect example of how a &lt;em&gt;gate with low legibility&lt;/em&gt; functions as a &lt;em&gt;reverse centaur demanding quality&lt;/em&gt;. Similarly, if you implement Vale in the manner of the &lt;em&gt;sorcerer’s apprentice&lt;/em&gt;, it is a &lt;em&gt;sentinel with high intrusion&lt;/em&gt;. Without a policy and plan for how to pace work through the backlog, this implementation quickly becomes a &lt;em&gt;reverse centaur demanding quantity&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In the empowered contributor model, writers have access to the tool as an &lt;em&gt;assistive technology&lt;/em&gt; and as a &lt;em&gt;quality control gate&lt;/em&gt; on the final product. They know the standards and have &lt;em&gt;distillers&lt;/em&gt; in their authoring process guiding them on how to meet those standards. And they determine the pace of their output. This becomes more &lt;em&gt;centaur-like&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Interestingly, part of why skilled writers are valuable is precisely because of their ability to write about the subject matter and &lt;em&gt;within constraints about the quality of their output&lt;/em&gt;. Good judgment for writers involves internalizing this knowledge and having a practice that enables them to achieve the level of output. Being that sort of writer involves dedicated practice and expertise, knowledge of how to use assistive technologies to produce quality docs is &lt;em&gt;valuable&lt;/em&gt;. In a model where the legibility of Vale isn’t equally distributed, we might have increased demand for labour that can meet the quality standards.&lt;/p&gt;
&lt;p&gt;Implementing Vale also imposes a new layer of work. Maintaining and updating the style guide is something that needs to be done. Adding Vale to the CI/CD and maintaining the CI/CD flow is something that requires work. Coordinating new style guide rules and propagating that knowledge to marketing or comms teams is also social work. Automated tooling can elevate the standards and quality of your work, but these things are embedded in a larger context of effort.&lt;/p&gt;
&lt;p&gt;Whether or not we perceive Vale as a &lt;em&gt;centaur&lt;/em&gt; or &lt;em&gt;reverse centaur&lt;/em&gt; fundamentally depends on legibility and intrusion.  And these things are fundamentally about how a human being perceives and works with the automation. It&amp;rsquo;s about arrangements of cogs and gates in ways that help, hinder, intrude, and expedite work.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-human-element-of-automation&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The human element of automation
  &lt;a href=&#34;#the-human-element-of-automation&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So! When we discuss automation, you might wonder why people don&amp;rsquo;t respond as favorably to some approaches as others. I think this is often because of the fact that something that might be &lt;em&gt;empowering&lt;/em&gt; for one model of work might be &lt;em&gt;demanding&lt;/em&gt; for another.&lt;/p&gt;
&lt;p&gt;What I take from the Vale example is that we can view this kind of disagreement as arising from how your proposed automation treats people. Think about whether that person is being treated as a disposable element of the machine or being protected or empowered by an arrangement of cogs, distillers, gates, and sentinels. Are they visible? Intrusive? Where is friction generated by the demands of the system? What is the person left to do in your system?&lt;/p&gt;
&lt;p&gt;A system that only produces outputs to be validated treats the user as legs for the reverse-centaur. A system that helps you develop quality work and leaves you to exercise your judgment at key choice points is one that treats the user as a centaur.  It&amp;rsquo;s easy to have a solipsistic view of the tools that you develop for yourself, but working in software is a &lt;em&gt;communal effort&lt;/em&gt;. When we deploy an automation, whether we&amp;rsquo;re a consultant, individual contributor, or a manager, we&amp;rsquo;re coordinating tasks and trying to ensure quality of outputs.&lt;/p&gt;
&lt;p&gt;What might seem like an &lt;em&gt;empowering assistive tool&lt;/em&gt; to one individual could leave another individual at the whims of a &lt;em&gt;demanding oracle&lt;/em&gt;. The same assistive technologies that enable me to drive more safely, when plugged into a system of labour relations and measurement, can require the Amazon driver to have to perform at a level that&amp;rsquo;s beyond their human endurance.&lt;/p&gt;
&lt;p&gt;Ursula Franklin&amp;rsquo;s notion of prescriptive technologies (from &lt;em&gt;The Real World and Technology&lt;/em&gt;) is helpful here, which she defines as:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&amp;hellip;specialization by process [&amp;hellip;] Here, the making or doing of something is broken down into clearly identifiable steps. Each step is carried out by a separate worker, or group of workers, who need to be familiar only with the skills of performing that one step. (20)&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;Prescriptive technologies are &lt;em&gt;means of coordination&lt;/em&gt;, and they require that individuals comply with a standard or process in the course of producing output:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&amp;hellip;the process itself has to be prescribed with sufficient precision to make each step fit into the preceding and the following steps. Only in that manner can the final product be satisfactory. The work is orchestrated like a piece of music — it needs the competence of the instrumentalists, but it also needs strict adherence to the score in order to let the final piece sound like music. Prescriptive technologies constitute a major social invention. In political terms, prescriptive technologies are &lt;em&gt;designs for compliance&lt;/em&gt;. (23)&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Demanding oracles&lt;/em&gt;, then, are a kind of prescriptive technology that lacks legibility. Working with a standard that is opaque, or not legible, is frustrating. It&amp;rsquo;s even more reverse-centaur-like if we build &lt;em&gt;sorcerer’s apprentice scenarios&lt;/em&gt; where the system demands increased effort in terms of quantity, without regard for the current state of the system.&lt;/p&gt;
&lt;p&gt;I want to caution us from concluding that prescriptive technologies are inherently wrong. &lt;em&gt;Style guides&lt;/em&gt; are a perfect example of a prescriptive technology. They are tools for making the writing of groups of people look like it was written by a single person: coordinating human effort to produce a uniform quality of output. By using Vale as a &lt;em&gt;gate&lt;/em&gt; and &lt;em&gt;distiller&lt;/em&gt; we empower users to meet a higher quality of output.&lt;/p&gt;
&lt;p&gt;Software automation fits a range of design patterns. Franklin defines &lt;em&gt;holistic technologies&lt;/em&gt; as being associated with craft &amp;mdash; allowing skilled workers to have control over their work from start to finish. But useful tools for craftspeople can easily become prescriptive standards for those who want to coordinate labour. And coordination &lt;em&gt;is important&lt;/em&gt; when communal effort for single outputs are required. We don&amp;rsquo;t get to build software, airplanes, buildings, etc. without coordination. When we have powerful holistic technologies, it&amp;rsquo;s very easy to get into tinkerer&amp;rsquo;s tunnel vision: we get focused on the power of the cool systems of cogs and gates we can build. Being a skilled craftsperson, piloting a centaur, it &lt;em&gt;feels good&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I think this does more to expalin the gap between adopters and resisters. It&amp;rsquo;s very easy to use generative AI to build an automation: typically, generative AI is &lt;strong&gt;low legibility&lt;/strong&gt; and &lt;strong&gt;high intrusion&lt;/strong&gt;. The internal logic of the chatbot is masked, but we can treat it as a &lt;em&gt;gate&lt;/em&gt;, &lt;em&gt;cog&lt;/em&gt; or &lt;em&gt;source of tasks&lt;/em&gt;. If a writer or programmer has to review mountains of AI generated output, it feels like something has gone wrong. But for some ways of working, this is a success. Since the implementations, expectations, and use cases aren&amp;rsquo;t uniform, the conversations break down.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re in a social moment where people expect generative AI to accelerate the output of work. I hope that I&amp;rsquo;ve demonstrated that automations in the workplace involve both machines, people, and systems of coordination. I didn&amp;rsquo;t mention LLMs, generative AI, or agents until this section, because in a way, this isn&amp;rsquo;t a problem unique to artificial intelligence systems in 2026 &amp;mdash; the issues are fundamentally about &lt;em&gt;system design&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;System design is something that often occurs organically or top-down at organizations and individual contributors often have little agency over the systems they find themselves in. Generative artificial intelligence provides a range of implementation possibilities, some of which are low legibility and high intrusion, but we don&amp;rsquo;t have to design systems like this. The &lt;em&gt;intern model&lt;/em&gt; adopted in copilots and assistive technologies increases the legibility to operators and moderates the intrusion. Agents &amp;mdash; construed as markdown files governing contributions to a codebase from an LLM &amp;mdash; reduce intrusion (for operators) and moderate the legibility (for operators). The extent to which we build &lt;em&gt;sorcerer&amp;rsquo;s apprentice&lt;/em&gt; or &lt;em&gt;demanding oracle&lt;/em&gt; situations for ourselves is a matter of design and management.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re excitedly talking about the automation that you&amp;rsquo;ve built, consider whether it is treating &lt;em&gt;people&lt;/em&gt; as &lt;em&gt;pilots&lt;/em&gt; or as &lt;em&gt;gears&lt;/em&gt; that need to keep pace with an accelerated system. The experience of being empowered to make your own choices as a craftsperson is different from having an increased backlog of automatically generated PRs to review.&lt;/p&gt;
&lt;p&gt;If we fundamentally view promoting automation and efficiency gains in terms of systems of trust, responsibility, and coordination, we can build better tools, cultures, and results as technologists. By building systems in the lens of &amp;ldquo;squires&amp;rdquo; and &amp;ldquo;gardeners&amp;rdquo; instead of &amp;ldquo;demanding oracles&amp;rdquo; we can build cultures of craft, which seems like a better way to work.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Drew Bruenig: &#34;Why I Write&#34;</title>
      <link>https://www.kevinrkuhl.com/blog/2026/01/bruenig-why-i-write/</link>
      <pubDate>Tue, 06 Jan 2026 15:22:16 -0500</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/01/bruenig-why-i-write/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s &lt;a href=&#34;https://www.dbreunig.com/2025/12/27/why-i-write.html&#34;&gt;a really nice piece&lt;/a&gt; from &lt;a href=&#34;https://www.dbreunig.com/&#34;&gt;Drew Bruenig&lt;/a&gt; about why you should write. These reasons are definitely part of why I&amp;rsquo;m writing this blog (and why I link blog). It&amp;rsquo;s also why I&amp;rsquo;m happy to see more technical writers joining the &lt;a href=&#34;https://caseyrfsmith.github.io/webring/&#34;&gt;technical writing webring&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;I think writing is one of the most valuable things you can do, and I recommend everyone try it. Here’s why:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;It makes you a better thinker and communicator.&lt;/strong&gt; Writing is a muscle. The more you write, the easier it gets, and your ability improves. You’ll learn to make clearer arguments, crisper explanations, and better empathize with your audience. These skills are applicable to everything.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You’ll get feedback that makes you a better writer.&lt;/strong&gt; Feedback exposes weak arguments and strengthens the good ones. Plus, learning to listen to feedback is another skill that is universally applicable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You’ll meet people interested in the same things you are.&lt;/strong&gt; Looking through my correspondence, it’s amazing how many of my favorite people to chat with I met through writing online. (BTW, this goes both ways. If you read something that resonates with you online, write them a note thanking them and telling them what you liked!)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your past thinking will be archived and searchable.&lt;/strong&gt; This is more valuable than you think. If you invest time to hone a piece, you’ll turn back to it more often than you’d expect. Further, reviewing old pieces and threads over time will reveal what worked and what didn’t while making your progress tangible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The value of your writing compounds.&lt;/strong&gt; The value &lt;em&gt;to you&lt;/em&gt;, that is. I don’t think my pieces from 6 years ago are improving anyone’s life, but the contacts I’ve made and pieces I’ve crafted have grown into a foundation I get to leverage everyday.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Writing gives you a license to explore and organize your thoughts.&lt;/strong&gt; This is the fun bit. Chasing down an idea that interests you, forming questions and then investigating them; it’s a joy. The second most common question I get about my writing is, “How do you motivate yourself to write?” This is the answer. There are so many drafts that live, dormant in my draft folder. So many times I start a piece and lose interest. And then: something will &lt;em&gt;click&lt;/em&gt; and I’ll draft, investigate, and finish a piece in an hour (here’s &lt;a href=&#34;https://www.dbreunig.com/2025/12/19/how-model-use-has-changed-in-2025.html&#34;&gt;two&lt;/a&gt; &lt;a href=&#34;https://www.dbreunig.com/2025/10/20/speeds-and-swarms.html&#34;&gt;examples&lt;/a&gt;). These aren’t always the most substantive pieces, but they keep the practice going and the momentum up.&lt;/li&gt;
&lt;/ol&gt;&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;But I think this really a key part of doing blogging:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;strong&gt;Be okay with bad writing.&lt;/strong&gt; Most writing isn’t great! If my hit rate is 1 out of 5, I’m thrilled. Get comfortable publishing things that aren’t perfect. I know many people who wait too long to publish and, well, never do. They do this for years. If they’d gotten the ball rolling back then, they’d be better writers today. It’s weird: you’d think regular private writing would be sufficient to get better. But it isn’t. There’s no stakes. No feedback. The only way to get better is to ship. Some people worry about the risk of bad writing. I think the biggest risk comes from being an asshole (so don’t be an asshole!) But the actual risks are quite low: most bad writing is neutral, it remains unread.&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;One thing I struggle with is keeping my posts simple and short. If you have a similar perspective, I&amp;rsquo;d consider giving &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/10/why-link-blog/&#34;&gt;link blogging&lt;/a&gt; a try. It helps you build the habit and stay engaged with your blog. It also encourages me to &lt;em&gt;read in an engaged way&lt;/em&gt; and take notes about what I&amp;rsquo;m reading. Also! I think reading is a key way to build writing skills. Find writers you enjoy and see how they approach writing a blog post (or book, newsletter or whatever!). The main point is to build the muscle and find what works for you.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My Guidelines for Writing About AI</title>
      <link>https://www.kevinrkuhl.com/blog/2026/01/my-guidelines-for-writing-about-ai/</link>
      <pubDate>Tue, 06 Jan 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2026/01/my-guidelines-for-writing-about-ai/</guid>
      <description>&lt;p&gt;Writing about AI &lt;em&gt;was&lt;/em&gt; hard.&lt;/p&gt;
&lt;p&gt;I was once a TA for a philosophy course where students were encouraged to write about AI, back before the advent of ChatGPT and generative AI. It was difficult giving feedback even when navigating a reading list I was familiar with &amp;mdash; students came from a range of backgrounds in philosophy, cognitive science, computer science, etc. I&amp;rsquo;m glad I&amp;rsquo;m not TAing for the same course now, since writing about AI feels even &lt;strong&gt;harder&lt;/strong&gt; these days, for a variety of reasons.&lt;/p&gt;
&lt;p&gt;To be honest, I feel kind of paralyzed when trying to write about AI. It&amp;rsquo;s incredibly easy to mean one thing, be heard saying another, and accidentally trigger a conflict you didn&amp;rsquo;t intend.  I&amp;rsquo;ve been thinking about principles that could guide how I blog about generative AI in a way that&amp;rsquo;s &lt;em&gt;responsible&lt;/em&gt; and &lt;em&gt;precise&lt;/em&gt;.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-problems&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The problems
  &lt;a href=&#34;#the-problems&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The biggest reason for this linguistic minefield is that &amp;ldquo;AI&amp;rdquo; is a shortcut for a range of phenomena that are better discussed with more precise terms.&lt;/p&gt;
&lt;p&gt;If I write a blog post about &amp;ldquo;AI&amp;rdquo; today, I could mean:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The general concept of human-like machine intelligence.&lt;/li&gt;
&lt;li&gt;Generative AI, by which I mean the broader space of tools using machine learning techniques to generate text, audio, images, and video.&lt;/li&gt;
&lt;li&gt;Specific apps like ChatGPT, Gemini, Claude, etc.&lt;/li&gt;
&lt;li&gt;Specific technologies behind the apps, like LLMs and system prompts, transformer architecture, etc.&lt;/li&gt;
&lt;li&gt;Specific applications of these apps for productivity.&lt;/li&gt;
&lt;li&gt;Machine learning applications that used complicated statistics to determine models of phenomena that have nothing to do with general purpose computing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ambiguity gets even worse when you use general summary verbs. Think about the multiple meanings that could come into play for the phrase &amp;ldquo;using AI&amp;rdquo;: If I tell a junior writer they should learn to use AI, do I mean that they should interact with a chatbot during the writing process? Learn how to create scripts and tooling to enhance their workflows? Learn how to create entire drafts through prompts? Learn how to use Code Wiki instead of talk with developers? The verb &amp;ldquo;use&amp;rdquo; is incredibly ambiguous, on top of the ambiguity of &amp;ldquo;AI&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The ambiguity in these discussions is a mile wide and deep. And it makes it very easy for two people to think they are arguing about values when they aren&amp;rsquo;t even agreeing about the meaning of the words. Things that might look neutral are incredibly value laden: &amp;ldquo;productivity&amp;rdquo;, &amp;ldquo;quality&amp;rdquo;, &amp;ldquo;ownership&amp;rdquo; are all tied to worth in various ways in western culture and internalized by individuals. A remark about what is the most productive way of doing something or what someone should do quickly becomes an evaluation of worth.&lt;/p&gt;
&lt;p&gt;And the problem compounds as our brains are primed for confirmation bias, political allegiances, and internalized norms. I&amp;rsquo;m not immune to this. I don&amp;rsquo;t think there&amp;rsquo;s an actual view from nowhere that we can occupy. So, for me at least, writing about AI is like navigating a linguistic minefield.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;my-goals&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;My goals
  &lt;a href=&#34;#my-goals&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s something I remarked in conversation with other technical writers regarding writing about AI:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve struggled with writing about it [AI] too. I want to stake out a &amp;ldquo;aware, cautious, and critical&amp;rdquo; space. But this kind of writing is just extremely difficult, since the broader space is heavily value-laden.&lt;/p&gt;
&lt;p&gt;If you say &amp;ldquo;I use it to write scripts to enhance my productivity&amp;rdquo;, that reads as whole hearted endorsement, since we occupy a professional world that values productivity. The reality is leadership expects us [technical writers] to ship faster because of these tools (that&amp;rsquo;s what they were sold after all!). We should have a good response (&amp;ldquo;I can do x, y, and z. But u, v, and w are productivity theatre. Here&amp;rsquo;s my evidence.&amp;rdquo;), and that involves engaging with the tools so we can discern what is what.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;And I fully acknowledge that in some way, playing this game (writing about how AI can be used) normalizes the political, ethical, ecological, and economic frameworks that make this technology so controversial. But at the end of the day, this is a complicated collective action problem, and the technology is here, along with leadership has expectations about how it should change my workflows.&lt;/p&gt;
&lt;p&gt;As someone who works in software, this is a conversation that&amp;rsquo;s happening around me, so I should participate. If my employers expect me to be aware of how I can use these things, I should be engaging with those things.&lt;/p&gt;
&lt;p&gt;And I&amp;rsquo;m someone who has a deep drive for clarity driven by a career in philosophy and strives to be a critically engaged lover of technology. Isolating ideas is something that comes naturally to me. I love the things we can do with computers. But I also want to be sensitive to questions of the value of human labour and creativity. So I try to be aware of a wide range of perspectives on AI. I found &lt;a href=&#34;https://buildcognitiveresonance.substack.com/p/who-and-what-comprises-ai-skepticism&#34;&gt;this post on AI skepticism&lt;/a&gt; really helpful for identifying different ways of thinking and writing about generative AI. My goals are to be aware of what I&amp;rsquo;m saying and how others might take it. To be precise and informed in a way that avoids conflict where I don&amp;rsquo;t intend it. Essentially, I really want to fall close to the informed critics part of this group &amp;mdash; and enjoy reading posts by folks like &lt;a href=&#34;https://simonwillison.net/&#34;&gt;Simon Willison&lt;/a&gt;, &lt;a href=&#34;https://colin-fraser.net/&#34;&gt;Colin Fraser&lt;/a&gt;, and &lt;a href=&#34;https://www.dbreunig.com/&#34;&gt;Drew Bruenig&lt;/a&gt;.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-personal-guidelines&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why personal guidelines?
  &lt;a href=&#34;#why-personal-guidelines&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Ok, because of all this difficulty in the language surrounding AI, it makes the topic intimidating to write about. And I enjoy blogging and thinking about technology. By formalizing my feelings and thoughts into a set of principles and guidelines, I can assess my own writing and check myself before posting things. Basically, this is a personal &lt;em&gt;style-guide&lt;/em&gt; for blogging about AI.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t a hard and fast set of rules for everyone. If it doesn&amp;rsquo;t work for you, that&amp;rsquo;s fine. And the technology will change, so I&amp;rsquo;m sure these guidelines will have to adapt as well.&lt;/p&gt;
&lt;p&gt;Each point is an imperative. They&amp;rsquo;re reminders of what I need to do to achieve the goal that I laid out in the first section: avoid confusion and harm, prioritize accuracy, and remember that this topic is heavily laden with values and norms.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;my-personal-guidelines&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;My personal guidelines
  &lt;a href=&#34;#my-personal-guidelines&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;These ten guidelines are how I want to approach writing about AI. Each point includes a bit of explanation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Be as specific as practicable.&lt;/strong&gt; If a more specific term can be substituted into my sentence, use that term instead of AI. If I&amp;rsquo;m really talking about an &lt;em&gt;LLM&lt;/em&gt;, then I shouldn&amp;rsquo;t use &lt;em&gt;AI&lt;/em&gt; or even &lt;em&gt;generative AI&lt;/em&gt;. If I&amp;rsquo;m talking about an &lt;em&gt;app&lt;/em&gt; or a &lt;em&gt;specific feature&lt;/em&gt;, I should say that instead of the LLM. Grok is a feature in Twitter/X and there is a model Grok 4.1, Gemini is an app but Gemini 3 Flash is a model.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch your verbs and pronouns&lt;/strong&gt;. Avoid anthropomorphizing AI by employing verbs as a shortcut. Avoid &amp;ldquo;the AI thinks&amp;rdquo;, &amp;ldquo;understands&amp;rdquo;, &amp;ldquo;knows&amp;rdquo;, &amp;ldquo;decides&amp;rdquo;, &amp;ldquo;hallucinated&amp;rdquo;. Use &amp;ldquo;the model calculates&amp;rdquo;, &amp;ldquo;predicts&amp;rdquo;, &amp;ldquo;outputs&amp;rdquo; or &amp;ldquo;processes&amp;rdquo;. This is doubly true for pronouns. Using personal pronouns (&amp;ldquo;you&amp;rdquo;) for these things is part of the illusion that we need to resist.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remember humans read your writing&lt;/strong&gt;. People are primed for polarization. Both &lt;em&gt;for&lt;/em&gt; and &lt;em&gt;against&lt;/em&gt; and that includes myself. Readers arrive with pre-existing fears of job loss or hype fueled optimism. Regardless of my intent, writing about AI means trying to navigate an explosive minefield. Be humble and own up to errors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remember your audience.&lt;/strong&gt; Don&amp;rsquo;t assume that other people have similar pressures on how they interact with, or understand, technology. As a technologist, I have curiosity and a professional responsibility to be aware of how the technology works that other people don&amp;rsquo;t. When I write about it, I may need to spend more words to get them on the same page. As a recovering philosopher, I have been trained to be &lt;em&gt;painfully&lt;/em&gt; clear in a way that people might find frustrating.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be aware of background values&lt;/strong&gt;. Saying that AI enhances productivity is a value laden statement, or is easy to interpret as value laden given our culture of capitalism. Being neutral is difficult and I should be cautious about the normative aspects of what I&amp;rsquo;m writing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be aware of background injury.&lt;/strong&gt; I don&amp;rsquo;t depend on the value of my intellectual property for my livelihood as much as other professionals. A photographer or illustrator has a different relationship to content scraping, which can be a direct harm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Center the human operator&lt;/strong&gt;. It&amp;rsquo;s easy to omit people from the picture if AI is an automation, but people are ultimately responsible for the automations they create, the outputs they accept, and the affordances a feature provides. For example, &amp;ldquo;The summary is generated by the AI&amp;rdquo; is passive, &amp;ldquo;The AI summarizes the text&amp;rdquo; attributes agency to the AI, and &amp;ldquo;I used the app to generate a draft summary&amp;rdquo; centers the operator (it also reinforces that the &lt;strong&gt;app&lt;/strong&gt; is used instead of the model!).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remember the parts that make the whole&lt;/strong&gt;. In generative AI, many components are presented as a simple thing. Awareness of those parts helps build clarity. The model is a complex blob of linear algebra. The system prompt mediates interaction with the model. The chatbot app is filtered by additional prompts and context. Web search is a separate component from the model. The UX conspires to hide these things. Clarity is important and difficult, but valuable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remember your perspective&lt;/strong&gt;. I don&amp;rsquo;t have the skills or knowledge to assess every aspect of generative AI, let alone AI. I can contribute to a conversation as one voice, with my perspective. Other people have other skills and knowledge, and I should strive to be charitable in interpreting their perspective.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Demand clarity, but be open to generalizations.&lt;/strong&gt; Communication is hard. We use lossy abstractions to quickly convey ideas. It&amp;rsquo;s important to get on the same page, but remember that others may have deeper or shallower understanding of the same topic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;rsquo;m not sure if these guidelines will satisfy everyone. But I know that these guidelines keep me from off the cuff posting about what&amp;rsquo;s a sensitive and difficult topic. We&amp;rsquo;re all in this together and trying to figure it out. I plan on posting a short series of posts about AI and the technical writing profession in 2026, so getting these principles out here is an important part of framing what I&amp;rsquo;m trying to achieve.&lt;/p&gt;
&lt;p&gt;One last note: It’s important to distinguish between writing about AI and the act of &lt;em&gt;documenting AI products&lt;/em&gt;. The latter is a specific technical challenge where the architecture of the product dictates the shape of the writing. Documenting a &lt;em&gt;foundational model&lt;/em&gt; (focusing on context windows and tokenization) is fundamentally different from documenting an &lt;em&gt;MCP (Model Context Protocol)&lt;/em&gt; implementation, an &lt;em&gt;agentic workflow&lt;/em&gt;, or a simple &lt;em&gt;AI-powered feature&lt;/em&gt;. Each of these &amp;ldquo;products&amp;rdquo; requires a different level of abstraction and has different audiences with different backgrounds and needs. While these guidelines help me stay responsible when blogging, they are the foundation for the precision required when I’m actually in the trenches documenting these distinct architectures.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>POSSE for Hugo: Part Two - The Product</title>
      <link>https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt2/</link>
      <pubDate>Fri, 12 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt2/</guid>
      <description>&lt;p&gt;In my &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/&#34;&gt;previous post&lt;/a&gt;, I explained the theory behind the Publish on your Own Site, Syndicate Elsewhere (POSSE) script I&amp;rsquo;ve been working on for this blog. POSSE is a strategy for managing and distributing your writing. Since this Hugo site is my home base on the web, adding an automated syndication script would be a fun and powerful project.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a public repository for the script on Github: &lt;a href=&#34;https://github.com/kevinrkuhl/hugo-posse/&#34;&gt;hugo-posse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s available under the MIT license, and free for anyone to use or modify. The plan for this post is to talk about how I use it with my site, and what&amp;rsquo;s next for improving this site.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;setup-and-configuration&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Setup and configuration
  &lt;a href=&#34;#setup-and-configuration&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;For this site, &lt;code&gt;posse.py&lt;/code&gt; lives in the top level of the project directory along with some other helper Python scripts. This is the easiest way for me to call them, whether they help backup images or build and deploy the site. The &lt;a href=&#34;https://github.com/kevinrkuhl/hugo-posse/blob/main/README.md&#34;&gt;README&lt;/a&gt; includes detailed installation instructions.&lt;/p&gt;
&lt;p&gt;The script relies on several libraries, most notably &lt;code&gt;atproto&lt;/code&gt; and &lt;code&gt;mastodon.py&lt;/code&gt;, so these are included in a &lt;code&gt;requirements.txt&lt;/code&gt; file. You can use &lt;code&gt;pip&lt;/code&gt; and this file to quickly install these libraries.&lt;/p&gt;
&lt;p&gt;To securely store your credentials, I&amp;rsquo;ve opted to include a &lt;code&gt;.env&lt;/code&gt; file in the root of my Hugo site project. My site configuration is stored in Github, which means it isn&amp;rsquo;t suitable for holding keys or passwords. I instruct Git to ignore this file (in my &lt;code&gt;.gitignore&lt;/code&gt;). If you plan on using this script, I highly recommend doing the same.&lt;/p&gt;
&lt;p&gt;The most complicated part of setting this up is getting credentials from Bluesky and Mastodon, but this is well documented in the scripts &lt;a href=&#34;https://github.com/kevinrkuhl/hugo-posse/blob/main/README.md&#34;&gt;README&lt;/a&gt; file.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;testing&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Testing
  &lt;a href=&#34;#testing&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Honestly, coding with Gemini as an assistant made this go very quickly. I have some Python knowledge, so basically this was &amp;ldquo;centaur-like&amp;rdquo; development, where I had a very effective intern pushing this project to completion. With a bit of the planning in place, I was able to use Gemini to come up with strategies for handling TOML/YAML pretty easily along with loops and structures to handle leaf bundles vs. individual files in the parsing and execution logic.&lt;/p&gt;
&lt;p&gt;I wanted to include the ability to do a dry-run before actual runs, which is flagged through the &lt;code&gt;--dry-run&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;The one unexpected element was a compatibility conflict between &lt;code&gt;atproto&lt;/code&gt; and Pydantic. When I ran tests I&amp;rsquo;d get a blob of warning text:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...\pydantic\_internal\_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The &amp;#39;default&amp;#39; attribute with value None was provided to the `Field()` function, which has no effect in the context it was used. &amp;#39;default&amp;#39; is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  warnings.warn(
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This warning doesn&amp;rsquo;t have any effect on the finished script, so I&amp;rsquo;ve decided to suppress this in the import block for script. This is a bit of technical debt, which I&amp;rsquo;ll keep in a note in Obsidian for maintenance for this project.&lt;/p&gt;
&lt;p&gt;Also, in order for this to work, you have to have strong markdown file &lt;em&gt;hygiene&lt;/em&gt;. An extra hard return at the start of the file can result in the parser skipping the file. But the way it&amp;rsquo;s structured is that it detects front matter at line one of the site. Better parsing is also in the list of to-dos for this project.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-workflow&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The workflow
  &lt;a href=&#34;#the-workflow&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Ok! So the workflow is pretty simple. The goal is to make syndication feel like writing, not like managing or repeatedly copy and pasting everywhere.Here&amp;rsquo;s how this plays out in writing:&lt;/p&gt;
&lt;p&gt;When I draft my Hugo content, I can decide whether I want to syndicate the post. If I do, I add two standard elements to the front matter for that post: &lt;code&gt;syndicate_to&lt;/code&gt; (a list of strings for syndication targets) and &lt;code&gt;microblog_content&lt;/code&gt; (the post for Bluesky/Mastodon). If I don&amp;rsquo;t want to syndicate the content, I don&amp;rsquo;t. In the &lt;code&gt;microblog_content&lt;/code&gt; field, I add a summary of what I say in the blog post and a couple of hashtags.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s nothing that ties me to writing inside of the social media apps, which lets me stay focused on finishing a quality blog post, without the noise and distraction of social media.&lt;/p&gt;
&lt;p&gt;When I&amp;rsquo;m ready to publish, I go through my build/deploy process. I&amp;rsquo;ve decided to automate that, but for manually building and deploying my Hugo blog, it looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -r -fo public
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hugo build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsutil -m rsync -r -n public gs://example-project
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I wait a bit for the changes to hit my site, followed by running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python posse.py content/blog --dry-run
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s the result of doing a dry run with a single post ready to syndicate:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt2/POSSE_Hugo_Dry.png&#34;
    alt=&#34;A command line log confirming that 1 post was found to be syndicated to Bluesky and Mastodon.&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;This lets me preview the manifest and actions that the script would perform. If I&amp;rsquo;m happy, I run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python posse.py content/blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here&amp;rsquo;s the successful feedback:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt2/POSSE_Hugo_Logging.png&#34;
    alt=&#34; A command line log showing a successful run, including authenticating with bluesky, and lines indicating successful posts to Bluesky and Mastodon using check mark icons. A final line indicates successfully writing the syndicated equals true flag into the file for the blogpost.&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;Since there&amp;rsquo;s a check on the &lt;code&gt;syndicated: true&lt;/code&gt; boolean flag first, I don&amp;rsquo;t have to worry about posting duplicate content. After syndicating a post, the script will automatically add &lt;code&gt;syndicated: true&lt;/code&gt; to the post. Between the &lt;code&gt;--dry-run&lt;/code&gt; argument and the &lt;code&gt;syndicated: true&lt;/code&gt; check, I really tried to prioritize security over spamming my social media feeds.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;minding-the-gap&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Minding the gap
  &lt;a href=&#34;#minding-the-gap&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s one problem I have with this approach and my stack of &lt;strong&gt;Hugo&lt;/strong&gt; &amp;gt; &lt;strong&gt;Google Cloud Services Bucket&lt;/strong&gt; &amp;gt; &lt;strong&gt;Cloudflare&lt;/strong&gt; (for DNS/HTTPS/caching). I alluded to it in my first post: if I run &lt;code&gt;posse.py&lt;/code&gt; too soon, the posts won&amp;rsquo;t be live, and the script aborts syndication. This is a condition where two processes are in a race to complete.&lt;/p&gt;
&lt;p&gt;I came up with three solutions for handling this race condition:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Manually wait before executing the script.&lt;/li&gt;
&lt;li&gt;Add this to a build/deploy script and use &lt;code&gt;sleep 30&lt;/code&gt; command to try and let my deployment finish.&lt;/li&gt;
&lt;li&gt;Write a small loop to poll the URL on small intervals until I can syndicate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I talked about manually working through the commands in the previous section, but here&amp;rsquo;s how the build/deploy script and sleep would work as a bash script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 1. Clean and build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf public
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hugo --minify
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 2. Sync to GCS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gsutil -m rsync -r -d public gs://example-project
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 3. The pause&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Waiting 30 seconds for Cloudflare propagation...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sleep &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 4. Attempt to syndicate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;python posse.py content/blog
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m toying around with a Python script handling build and deploy operations (apologies if I&amp;rsquo;ve accidentally doubled posts in your RSS reader). The thought is it can pull together some of my other utilities written in Python (like a script which backs up screenshots, since I don&amp;rsquo;t store them in Github) into a build, deploy, syndicate, and clean-up process.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how a polling loop would look in Python:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#Other libraries&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; time
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; requests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#Other methods&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;check_url_with_retry&lt;/span&gt;(url, max_retries&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;, delay&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; attempt &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; range(max_retries):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; requests&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;get(url, timeout&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;status_code &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;URL not ready (&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;response&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;status_code&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;). Retrying in &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;delay&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;s...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;except&lt;/span&gt; requests&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;RequestException:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Connection error. Retrying in &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;delay&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;s...&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        time&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sleep(delay)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Main execution loop:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; check_url_with_retry(url):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    logging&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;error(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Skipping &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;title&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;: URL not accessible after retries.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;future-directions&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Future directions
  &lt;a href=&#34;#future-directions&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As I&amp;rsquo;ve gone through this, I&amp;rsquo;ve been keeping note of various improvements that I can make for the script:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My first test turned up something I missed during my Bluesky research, namely how Bluesky handles hashtags. Bluesky requires hashtags to be parsed and added as metadata when creating a post. On Mastodon, hashtags are plain text. Adding a separate method to parse and extract hashtags for Bluesky is a high-priority fix for now.&lt;/li&gt;
&lt;li&gt;Better handling for parsing front matter (cf. the issue with a hard return before the front matter).&lt;/li&gt;
&lt;li&gt;Writing links to Mastodon and Bluesky back into the front matter for the post.&lt;/li&gt;
&lt;li&gt;Hugo is one SSG among others, I&amp;rsquo;m not sure about compatibility. But it might be fun to modify or extend this script to support other blogging  platforms. The biggest barrier is that I&amp;rsquo;ve hardcoded the &lt;code&gt;content&lt;/code&gt; folder structure into this script. It might not be too big of a lift to make that an argument for the script, but I&amp;rsquo;ve got some ideas to work around this.&lt;/li&gt;
&lt;li&gt;Posts without linking back to this site &amp;mdash; This gets me really close to using this site as a headless content management system for my social media. The idea is to add a folder to my Hugo project where I can write a short post, and syndicate that to the microblogging services, without publishing the post to the website and linking back to it. This Hugo site becomes my authoring environment for social media posts.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://obsidian.md&#34;&gt;Obsidian&lt;/a&gt; is a note taking app that I enjoy using. It has a similar structure to Hugo (file directory of markdown files with front matter) If I support posts without linking back to this site, this is a very cool extension of the idea outside of blogging and into note-taking. You could use Obsidian as a weird headless CMS for social media.&lt;/li&gt;
&lt;li&gt;Expanding to other social media platforms. If I&amp;rsquo;m really all about this site as a headless CMS for all my professional social media, then LinkedIn is a natural next step. So is Twitter/X.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While I want to get back on my writing, I&amp;rsquo;ll probably work through these issues and continue to blog about developing and improving this script. Maybe I&amp;rsquo;ll even have to rename the repository if I go far enough down the &amp;ldquo;SSG agnostic&amp;rdquo; route.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;conclusion&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Conclusion
  &lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This has been a surprisingly fun rabbit hole to go down.&lt;/p&gt;
&lt;p&gt;It combines practical coding with trying to find a better way to use the internet, built around my needs for writing and focus. If you&amp;rsquo;re feeling like you don&amp;rsquo;t have a lot of agency when it comes to your publishing pipeline, I hope this inspires you to try and build something similar. I can retain my focus while writing and easily share my content with more people (RSS, Bluesky, and Mastodon are all ways to follow this blog). While I don&amp;rsquo;t think I&amp;rsquo;ll syndicate shorter link blog posts, I&amp;rsquo;m excited to share more of my original pieces.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been balancing working on this with several ideas for long-form content for this blog. But I really wanted to get all this working before I started making those posts. There was a bit of back and forth as I got more into those ideas. But I&amp;rsquo;m glad this is in a usable and sharable state.&lt;/p&gt;
&lt;p&gt;Expect a flurry of content before the end of the year. I&amp;rsquo;ve got some really interesting ideas about AI and automation for technical writers simmering on the back burner. After I clear that backlog, I&amp;rsquo;ll probably gravitate back towards a balance of link blogging content, long form posts, and technical projects that feels sustainable and aligns with my mood. If you&amp;rsquo;re reading this on social media, let me know what you&amp;rsquo;d be most interested in.&lt;/p&gt;
&lt;p&gt;But I&amp;rsquo;m enjoying what this site is becoming and looking forward to continuing to blog and build it outwards.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>POSSE for Hugo: Part One - Theory</title>
      <link>https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/</link>
      <pubDate>Thu, 11 Dec 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/</guid>
      <description>&lt;p&gt;I like the &lt;a href=&#34;https://indieweb.org/&#34;&gt;IndieWeb&lt;/a&gt;; it&amp;rsquo;s an idea and emerging set of standards for how to build independent websites that can talk to one another. I&amp;rsquo;m gradually building this website towards that ideal. One of the underlying ideas is &lt;a href=&#34;https://indieweb.org/POSSE&#34;&gt;POSSE&lt;/a&gt; (Publish on your Own Site, Syndicate Elsewhere) or COPE (Create Once, Post Everywhere).&lt;/p&gt;
&lt;p&gt;The basic idea behind POSSE is that content should be posted to my own site first then syndicated elsewhere, with links connecting back to my original post. Why do I prefer this approach?&lt;/p&gt;
&lt;p&gt;My site already does some syndication: I have an RSS feed for my blog, which is a stripped down feed of my posts. You can use a dedicated app (RSS reader) to subscribe to that feed. Your app will regularly check my site for  new posts and present them to you without you having to come here. RSS does syndication brilliantly, but it has its limitations: for example, you have to know about the existence of the feed and use an app to subscribe.&lt;/p&gt;
&lt;p&gt;Social media sites are a great environment for sharing and interacting with other users. You contribute to shared feeds of content, and can share posts to people connected with you. If RSS is &lt;em&gt;one-to-many&lt;/em&gt; communication, social media is &lt;em&gt;many-to-many&lt;/em&gt;. The problem with traditional social media is that you end up locked in. You can request your post data from Facebook or LinkedIn, but you&amp;rsquo;ll end up with a massive JSON file that&amp;rsquo;s unwieldy to use. By syndicating content from my site to social media, I can write in a central place and share my thoughts and ideas in community spaces. I own the content, in a format I can work with, and can take it anywhere. It&amp;rsquo;s backed up on Github and my hard drives. It&amp;rsquo;s a way of treating my writing as something I own.&lt;/p&gt;
&lt;p&gt;POSSE is a &lt;em&gt;practice&lt;/em&gt;, so you could do it manually. But, if I plan on syndicating the same post to Mastodon, Bluesky, Twitter/X, and LinkedIn, I would be adjusting a summary and pasting links into forms on each social media site. And if you repeat the same step enough times, it looks like an opportunity to automate with a script.&lt;/p&gt;
&lt;p&gt;This post is a write-up of the ideas behind the script. The process was a little more creative and messy, working with docs and LLM assistants to build out something that met my needs. I&amp;rsquo;ll talk about the final script and using it in my next post in this series.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;targets-tools-and-research&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Targets, tools, and research
  &lt;a href=&#34;#targets-tools-and-research&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This site is built using &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;. Hugo is a static site generator, and it &lt;em&gt;builds&lt;/em&gt; HTML from markdown files stored locally on my computer (version controlled with Git/GitHub).  Information about the post (metadata) is stored as &lt;a href=&#34;https://gohugo.io/content-management/front-matter/&#34;&gt;front matter&lt;/a&gt;: YAML or TOML before the markdown content. The front matter can include labels, descriptions, whether the post is a draft, etc. Some of these terms are reserved by Hugo, but you can define other kinds of metadata. So I&amp;rsquo;ll create a post, with metadata, and build the website using the post metadata.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve used various scripts to take care of various command line checks, cleanups, and repeated commands for working with markdown and this site. After I build the site, I use the command-line to &lt;em&gt;deploy&lt;/em&gt; it to my hosting service.&lt;/p&gt;
&lt;p&gt;The POSSE script runs after I build and deploy this site to &lt;em&gt;syndicate&lt;/em&gt; the content. I decided to focus in particular on micro-blogging social networks, so I will author a single short summary or description for the post (including hashtags). By keeping the post close to the blogpost, I can write the &amp;ldquo;tweet&amp;rdquo;/&amp;ldquo;skeet&amp;rdquo;/&amp;ldquo;toot&amp;rdquo; as I write and publish new blog posts.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Aside:&lt;/em&gt; Mentions (using the &lt;code&gt;@&lt;/code&gt; symbol) pose a wrinkle that I don&amp;rsquo;t want to tackle at this early stage. Especially in federated services, where a Mastodon handle is different from a Bluesky handle. The easiest way is to log in and leverage mentions directly.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s the core logic for the script:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Scan a directory of content from my site for posts that I want to syndicate.&lt;/li&gt;
&lt;li&gt;If a post contains appropriate front matter (character length, whether I want to syndicate the post), add the post to a manifest (dictionary or list) of things to syndicate, and reconstruct the URL for the equivalent post (each entry is a post + link).&lt;/li&gt;
&lt;li&gt;Verify that manifest links are live on my hosting service (ping the URL, receive a &lt;code&gt;200 OK&lt;/code&gt; response).&lt;/li&gt;
&lt;li&gt;Create a session with the target service(s).&lt;/li&gt;
&lt;li&gt;Send posts to those services including a link to my original content.&lt;/li&gt;
&lt;li&gt;Update the front matter to prevent the script from posting the same content multiple times.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For now, I&amp;rsquo;m only to targeting federated social media: Bluesky and Mastodon. Why these two services? They&amp;rsquo;re the easiest to interact with via scripts. Twitter/X&amp;rsquo;s API is significantly more locked down than it used to be. LinkedIn has a very different kind of post structure that performs better and I don&amp;rsquo;t really want to deal with managing OAuth (yet). But ATProto and ActivityPub are open standards for developing and working with social media. The more closed ecosystems could be future goals for this project.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;implementation-considerations&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Implementation considerations
  &lt;a href=&#34;#implementation-considerations&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Here are a couple of technical considerations I had to keep in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Since I use Cloudflare, there&amp;rsquo;s a time gap between running the commands that deploy my site, and the content becoming available. I have to account for this when I run the script or combining the build, deploy, and syndicate steps into a larger script.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you&amp;rsquo;re really gung-ho about CI/CD, then there&amp;rsquo;s ways of doing this via GitHub Actions or Hugo Pipes. This feels like over-engineering for this site. The difference between merging a branch and running my build/deploy scripts locally is negligible for me.&lt;/p&gt;&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dependency management was another factor. Since I script in the most recent version of Python (3.13.2), I needed to be mindful of potential library conflicts or version mismatches in the environment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To securely handle keys and other credentials, I needed to be mindful of my Hugo site structure and Github.  Rather than store these keys in my site configuration, the script uses a &lt;code&gt;.env&lt;/code&gt; file, which I explicitly tell Git to ignore.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hugo uses the base URL for your site, individual markdown file names, leaf bundles, and metadata to set the URL of pages. I needed to accommodate this as well.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;bluesky&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Bluesky
  &lt;a href=&#34;#bluesky&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I&amp;rsquo;ve talked a little bit about learning about &lt;a href=&#34;https://atproto.com/&#34;&gt;ATProto&lt;/a&gt; in &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/08/guide-to-atproto/&#34;&gt;the past&lt;/a&gt;, which is the protocol that Bluesky is built on. There is an &lt;a href=&#34;https://atproto.blue/en/latest/&#34;&gt;SDK for Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The core thing to know for this implementation is the &lt;code&gt;client&lt;/code&gt; object, that lets you interact with the Bluesky programmatically. In order for your application/script to authenticate with the Bluesky server, you need to generate an &lt;a href=&#34;https://lifehacker.com/tech/why-you-should-be-using-bluesky-app-passwords&#34;&gt;application password&lt;/a&gt;. After authenticating and creating a client, you can use the &lt;code&gt;send_post(...)&lt;/code&gt; method to create a post.&lt;/p&gt;
&lt;p&gt;Bluesky posts have a &amp;ldquo;link card&amp;rdquo;, which requires a specific data structure called an &lt;em&gt;Embed&lt;/em&gt;. Embeds include a &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt;, and &lt;code&gt;thumb&lt;/code&gt;. Here&amp;rsquo;s how this looks on Bluesky itself:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/POSSE_Bluesky_Embed.png&#34;
    alt=&#34;Post on Bluesky. Forbes discusses a the limited success of recent a book launch with a card linking to their news story.&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;As nice as thumbnail images are, they are optional. So for simplicity, I omitted the &lt;code&gt;thumb&lt;/code&gt; field in my implementation. This meant my link cards will end up looking blank, but an option is having some kind of logo for my personal brand and using that as a default, which I might implement later.&lt;/p&gt;
&lt;p&gt;A key thing to note is that post content is limited in character length. For Bluesky, this is 300 characters, so we&amp;rsquo;ll want to be aware of this when scripting.&lt;/p&gt;
&lt;p&gt;After creating the embed from my metadata, I use the &lt;code&gt;send_post(...)&lt;/code&gt; method mentioned above. This method can return the URL and content ID for the post. Right now, I&amp;rsquo;m not doing anything with what&amp;rsquo;s returned, but I might want to write it to custom metadata for the post. So there&amp;rsquo;s two future features for this script!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;mastodon&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Mastodon
  &lt;a href=&#34;#mastodon&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Mastodon also has a &lt;a href=&#34;https://mastodonpy.readthedocs.io/en/stable/&#34;&gt;Python library&lt;/a&gt;, and you can create a client (using an access token generated in the application). In a sense, it&amp;rsquo;s easier to work with the Mastodon library in that their servers handle the construction of the link cards/previews on the app. The library provides a similar &lt;code&gt;client&lt;/code&gt; object. The &lt;code&gt;client.status_post(...)&lt;/code&gt; lets you provide a &lt;code&gt;status&lt;/code&gt; (body text, including the URL) and &lt;code&gt;visibility&lt;/code&gt; (whether the post should be public, unlisted, or private).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of what a linked post looks like on Mastodon:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/12/posse-for-hugo-pt1/POSSE_Mastodon_Link.png&#34;
    alt=&#34;Post on Mastodon. A box contains user text explaining their blog post introducing users to working with yuno host, and a card appears beneath the post with a link and summary text.&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;Again, it&amp;rsquo;s possible to post images/media to Mastodon, but my goal is quick syndication, so this isn&amp;rsquo;t something I want to handle with the script.  Similar to Bluesky, the method returns a dictionary that includes the post ID and URL. Again, a stretch goal is to write this to the post metadata.  Finally, Mastodon has a longer character limit of 500 characters &amp;mdash; however, I don&amp;rsquo;t feel like I lose anything by forcing myself to stick to the 300 character limit from Bluesky. Also, the URL is part of the post in Mastodon (something to keep in mind if you&amp;rsquo;re developing on your own!).&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;structure-and-setup&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Structure and setup
  &lt;a href=&#34;#structure-and-setup&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When I was programming in high school, I thought pseudocode was kind of silly. But it really helps to map out the overall logic and methods I&amp;rsquo;ll need to keep myself organized. And it speeds up developing with Gemini or ChatGPT if you already have a sense for the core logic. If I start with a plan for the script&amp;rsquo;s logic, going to an LLM lets me finish the project much more quickly.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s a mockup, using some templates from other scripts I&amp;rsquo;ve used to work with markdown, YAML, or TOML. It translates the concepts from the steps I wrote earlier into blocks for methods, loops, and if statements:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Import block - need to add atproto/mastodon, probably other libraries. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Configuration block - constants, retrieving keys, logging etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Methods&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;# Content handlers YAML, TOML.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;# Syndication functions, create sessions, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;#0. Use argparse for input. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;# Need directory to crawl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;# Optional testing mode.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# Mode for testing clients?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;#1. Create clients (Bluesky, Mastodon)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;#2. Parse directories&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;# Walk through directories, find each markdown file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#75715e&#34;&gt;# If applicable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;#   Extract front matter, &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;#   Add to manifest.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;# else end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;#3. Execute steps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;# Loop through manifest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#75715e&#34;&gt;# Extract URL and ping&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#75715e&#34;&gt;# Syndication/Test output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#75715e&#34;&gt;# Update front matter to indicate as syndicated. &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; __name__ &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I wanted the script to be agnostic on YAML or TOML (Hugo supports both for front matter), which means that the content handling logic needs to process both. That&amp;rsquo;ll complicate the method structure a little bit. Just like the leaf bundle vs. markdown filename point.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;One realization I&amp;rsquo;ve had while writing this up is that it would be relatively easy to build something that doesn&amp;rsquo;t use links. I could add a &lt;code&gt;posts&lt;/code&gt; directory to my site, and point this script at that directory to publish posts. These could be backed up on Github, left with &lt;code&gt;draft: true&lt;/code&gt; and syndicated without being posted to my website.&lt;/p&gt;
&lt;p&gt;It would also be a short hop to use this script with a tool like &lt;a href=&#34;https://obsidian.md/&#34;&gt;Obsidian&lt;/a&gt;, which makes use of markdown and front matter for note-taking. This lets you write and plan posts from your note-taking app, and Obsidian could become a home base for sharing and posting to multiple social media sites. Applications like this are why coding is &lt;em&gt;fun&lt;/em&gt; and &lt;em&gt;empowering&lt;/em&gt;!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;On the topic of front matter it&amp;rsquo;s easy to map out new fields: I need a way to indicate which targets the script should syndicate to, what the content should be, and whether the post has been syndicated. While targets was my first choice, Hugo reserves the &lt;code&gt;target&lt;/code&gt; keyword for link attributes (like &lt;code&gt;target=&amp;quot;_blank&amp;quot;&lt;/code&gt;). Using &lt;code&gt;syndicate_to&lt;/code&gt; avoids any potential namespace collisions and makes the intent of the field explicit.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what my proposed front matter looks like in YAML:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Syndication System Test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;date&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;2024-01-01T12:00:00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;draft&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;slug&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;stealth-test-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;syndicate_to&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bluesky&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mastodon&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;microblog_content&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Testing my new syndication script. 🤖&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;syndicated&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next up, we&amp;rsquo;ll set up the &lt;code&gt;.env&lt;/code&gt; file. I&amp;rsquo;m going to include the &lt;code&gt;BASE_URL&lt;/code&gt; for my site here, so I don&amp;rsquo;t need to load both the &lt;code&gt;.env&lt;/code&gt; and Hugo &lt;code&gt;config.toml&lt;/code&gt;. This might be a little sloppy, but I don&amp;rsquo;t anticipate changing domains any time soon:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Site Configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#No trailing slash!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BASE_URL&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;https://www.yoururl.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Bluesky Credentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use an App Password, not your main login password!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Settings -&amp;gt; Privacy &amp;amp; Security -&amp;gt; App Passwords&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BSKY_HANDLE&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;handle.bsky.social&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BSKY_PASSWORD&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;xxxx-xxxx-xxxx-xxxx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Mastodon credentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;MASTODON_API_BASE&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;https://mastodon.social&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;MASTODON_ACCESS_TOKEN&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;long-string-of-characters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally I told Git to ignore the &lt;code&gt;.env&lt;/code&gt;, adding the following block to my site&amp;rsquo;s &lt;code&gt;.gitignore&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Environments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;.env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;.venv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;env/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;venv/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;__pycache__/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;conclusion&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Conclusion
  &lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is a good stopping point for this post &amp;mdash; I wanted to give a bit of the theory before publishing the final project. Coding can be kind of mysterious, and it&amp;rsquo;s helpful to show how you can get a good structure going for your ideas.&lt;/p&gt;
&lt;p&gt;This script already works, and this is the first post I&amp;rsquo;ve syndicated using this approach. My next post will talk about some of the difficulties that emerged in building the script and a link to a github repo to so that you can use it with your own website. Hopefully this inspires you to work on something cool yourself!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sarah Moir: AI and Tech Writing Strategy</title>
      <link>https://www.kevinrkuhl.com/blog/2025/11/smoir_ai_and_tech_writing_strategy/</link>
      <pubDate>Fri, 21 Nov 2025 15:37:16 -0500</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/11/smoir_ai_and_tech_writing_strategy/</guid>
      <description>&lt;p&gt;Over at &lt;a href=&#34;https://thisisimportant.net&#34;&gt;This is important&lt;/a&gt;, Sarah Moir has &lt;a href=&#34;https://thisisimportant.net/posts/ai-strategy-for-documentation/&#34;&gt;an excellent discussion of AI strategy&lt;/a&gt; for technical writers and documentation teams.&lt;/p&gt;
&lt;p&gt;In particular, I really agree with her on this:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;You can invest in building a chatbot with a tool like &lt;a href=&#34;https://fin.ai/&#34;&gt;Fin&lt;/a&gt;, &lt;a href=&#34;https://inkeep.com/&#34;&gt;Inkeep&lt;/a&gt;, or &lt;a href=&#34;https://www.kapa.ai/&#34;&gt;Kapa&lt;/a&gt;. But I don’t recommend placing the chatbot on the documentation site.&lt;/p&gt;
&lt;p&gt;When you build your own chatbot and provide it on your docs, you create uncertainty for your customers and readers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the response going to contain accurate and trustworthy information?&lt;/li&gt;
&lt;li&gt;Is this chatbot going to be more reliable than ChatGPT or Claude?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Documentation is perceived as an authoritative source of information. If the official documentation provides a way to get inaccurate or misleading information, readers might lose trust in the documentation itself, and ask: &lt;a href=&#34;https://thisisimportant.net/posts/are-ai-chatbots-docs/&#34;&gt;Are AI chatbots docs?&lt;/a&gt; (No.)&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/10/thinking-strategically-about-documentation/&#34;&gt;role of docs as an authoritative source of information&lt;/a&gt; means that we shouldn&amp;rsquo;t to using AI as the main interface for docs. The risk of error undermines that function.&lt;/p&gt;
&lt;p&gt;However, we should think of ways to meet the users with the interfaces they choose to use (browsers, in-app elements that direct to docs). Balancing this tension and having users understand the risk is really something we need to have in mind as technical writers.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s definitely something I&amp;rsquo;ve been thinking about lately. I&amp;rsquo;m currently finalizing a series of posts that act as a &amp;ldquo;snapshot of where we&amp;rsquo;re at&amp;rdquo; regarding generative AI and technical writing. I&amp;rsquo;ll be framing my posts around how generative AI might contribute to our practice, how it impacts how people access docs, and how we might need to change our practices for documenting generative AI solutions. It&amp;rsquo;s an interesting set of problems and opportunities and it&amp;rsquo;s great to have posts like Moir&amp;rsquo;s to help elevate the discussion.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fabrizio Ferri Benedetti: Documentation Theatre as a Service</title>
      <link>https://www.kevinrkuhl.com/blog/2025/11/ffb-documentation-theatre-as-service/</link>
      <pubDate>Sat, 15 Nov 2025 13:50:03 -0500</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/11/ffb-documentation-theatre-as-service/</guid>
      <description>&lt;p&gt;Google just announced &lt;a href=&#34;https://codewiki.google/&#34;&gt;Code Wiki&lt;/a&gt;. The timing of this is kind of personally frustrating, since I was deep into a post about where AI tooling and software documentation is at in the year 2025. Now that post is going to get a couple of extra paragraphs.&lt;/p&gt;
&lt;p&gt;The copy is certainly striking, using phrases like, &amp;ldquo;Stop documenting&amp;rdquo;, &amp;ldquo;No more stale docs. Ever.&amp;rdquo; Understandably, this hits close to home for &lt;em&gt;technical writers&lt;/em&gt;. After all, we&amp;rsquo;re in the business of producing &lt;em&gt;docs&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;What the tool does is kind of provide a seemingly &amp;ldquo;complete&amp;rdquo; set of documentation in a web interface, along with an instance of Gemini that you can chat with. The main mode is descriptive, explaining the architecture of the repository, which makes sense if you&amp;rsquo;re trying to understand the project as a &lt;em&gt;codebase&lt;/em&gt;. Most of us aren&amp;rsquo;t working with libraries at that level. It&amp;rsquo;s impressive, but kind of weird. I really recommend pointing it at a repository you&amp;rsquo;re familiar with, and comparing the structure of the output to the official docs (a good example is &lt;a href=&#34;https://codewiki.google/github.com/flutter/flutter&#34;&gt;Code Wiki&amp;rsquo;s approach to Flutter&lt;/a&gt; and &lt;a href=&#34;https://docs.flutter.dev/&#34;&gt;Flutter&amp;rsquo;s docs&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Calling it a wiki is particularly strange &amp;mdash; wikis center &lt;em&gt;collaboration&lt;/em&gt;. The promise is that the service will &lt;em&gt;own&lt;/em&gt; documentation. While this is probably a nod to these tools having a superficial appearance to GitHub&amp;rsquo;s wiki feature, it&amp;rsquo;s really different in spirit.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://passo.uno&#34;&gt;Fabrizio Ferri Benedetti&lt;/a&gt; has a &lt;a href=&#34;https://passo.uno/ai-wikis-docs-teather-as-a-service/&#34;&gt;spirited rejoinder&lt;/a&gt; that is really worth reading:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;These tools &lt;em&gt;[Code Wiki and DeepWiki]&lt;/em&gt; can fulfill the role of project summarization. They’re helpful when trying to explore poorly documented codebases and get a sense of how the pieces fit together, but they stop short of anything that could be called “docs” (and perhaps that’s why they shyly chose “wiki” instead). I would describe their output as byproducts of an LLM digestion process (yes, blergh).&lt;/p&gt;
&lt;p&gt;It’s impressive for the first ten seconds, but as you start reading, you begin to notice that for most complex projects, the wiki is at best dry reference, at worst a dumpster fire of hallucinations, &lt;a href=&#34;https://en.wikipedia.org/wiki/M._C._Escher&#34;&gt;Escherian&lt;/a&gt; information architecture, and subtly wrong facts and diagrams. This is not a lazy dismissal: read the &lt;a href=&#34;https://news.ycombinator.com/item?id=45002092&#34;&gt;comments on Hacker News&lt;/a&gt; to get an idea of how dismal their results can be.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;As is unfortunately common in this moment, the hardest part of our job is aligning with people who don&amp;rsquo;t understand the function or role of docs:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;What makes me furious with the heat of a thousand Suns is the fact that some devs could be lured into thinking that this sort of ersatz manuals can check the docs box at all. That some could find these self-inflicted wikis a valid replacement of human-made docs shows the same kind of ignorance (or cynicism) about technical writing that folks display when praising art made by AI.&lt;/p&gt;
&lt;p&gt;Docs are a product. They require sustained and intelligent effort over a long period of time, as well as a strong community &lt;a href=&#34;https://passo.uno/docs-contribution-journey/&#34;&gt;ready to contribute&lt;/a&gt;. Docs are the mirror and lore of your code and design, instruments that help you think about what you are architecting and developing. Docs serve &lt;a href=&#34;https://passo.uno/seven-action-model/&#34;&gt;purposes and needs&lt;/a&gt;. Great docs explain, guide, help, and illustrate. They’re deeply flawed and human. They must be.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href=&#34;https://passo.uno/ai-wikis-docs-teather-as-a-service/&#34;&gt;whole post&lt;/a&gt; is great, but in particular, this conclusion:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;Let’s draw the line: docs generated entirely by AI should never ship to users. You can &lt;a href=&#34;https://passo.uno/ai-docs-policy-contributions/&#34;&gt;use AI judiciously&lt;/a&gt; to audit your docs for gaps, to spot inconsistencies, to generate first drafts that you’ll edit later. But the moment you let any LLM have the final word on what users will read, you’ve abandoned the basic contract of docs: that someone who understands the system has taken responsibility for explaining it truthfully.&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;This last sentence is a powerful encapsulation of the value of docs, regarding &lt;em&gt;user expectations&lt;/em&gt;, &lt;em&gt;responsibility&lt;/em&gt;, and serving as an &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/10/thinking-strategically-about-documentation/&#34;&gt;authoritative source of knowledge&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tim Berners-Lee: Podcasts, AI, and the Future of the Web</title>
      <link>https://www.kevinrkuhl.com/blog/2025/11/tim-berners-lee-podcasts-ai/</link>
      <pubDate>Thu, 13 Nov 2025 15:37:16 -0500</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/11/tim-berners-lee-podcasts-ai/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been posting a lot about technical writing recently, but I also like thinking about the Internet. This is a really nice interview with &lt;a href=&#34;https://www.theverge.com/podcast/814552/tim-berners-lee-world-wide-web-ai-future-interview&#34;&gt;Tim Berners Lee on Decoder&lt;/a&gt; (the Verge&amp;rsquo;s podcast).&lt;/p&gt;
&lt;p&gt;First up, on podcasts&amp;hellip;&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;They always try to persuade you to use the app, because then they have more control, they can track you better. But also with podcasts particularly, I use a podcast program, a generic podcast app, that I can listen to any podcast with.&lt;/p&gt;
&lt;p&gt;For me, that’s the web as it should be. You could send me a link to a podcast, or I can search for it and I can keep track of all the hundreds of podcasts I’m interested in. It is a bit like keeping bookmarks on the first original browser. So, to a certain extent, podcasts work well. But if people end up on the app and then are tracked and not using the podcast app, then not so. All that tension is huge right now for the web, yes.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;Which echoes a lot of what I love about &lt;em&gt;podcasts&lt;/em&gt; and &lt;em&gt;blogging&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;But really, there&amp;rsquo;s very insightful discussion about where the web is at now, and where things are going in the age of LLMs:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;&lt;strong&gt;At the beginning of the web, you made a lot of people with a lot of power agree to participate in some standards. You made them agree to participate in browser standards. There was a ferocious competition among browsers at that time.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It seems like we’re about to enter a period of ferocious competition in browsers again, which I want to come to. But at that time, at the beginning of the web, there was a lot of competition in browsers. Microsoft was brought to heel in an antitrust case, because there was such ferocious competition among browsers.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did you go about convincing all of those companies and all of those people to adopt your standards and say, “We actually have to be good stewards of the collective”? Because that doesn’t seem like a thing that could happen today, but you were able to do it at the outset of the web. How’d you do it?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By persuading them that one web was going to be really good. If you have just one web, it would take off exponentially. If we had many little webs, they would each die. People realized that and they managed to persuade the governance within their platforms, their managers and their boards, to make this one web. They knew that if they fought over incompatible versions of HTML, then the web would not take off, like it would if they made one web. If they made one web, then one web would take off and become huge, and then their part of that web would be itself huge.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Could you make that argument today? And what technology would you make it about?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A lot of people would wonder whether you can make it with AI. There is no World Wide Web Consortium (W3C) for AI, which is bringing everybody together in one room. Some people have suggested there should be something like a CERN (The European Organization for Nuclear Research) for AI, some big high-energy physics lab in some big international lab that develops AI. That way you can really optimize both the development of AI, but also prevent the thing running away, so you can build containers around it, for example.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;Also worth thinking about is how AI is changing how we consume and access the Internet. Major companies race to implement new browsers, whether governance and new standards will emerge, and companies like Cloudflare work to monetize AI access to your website&amp;rsquo;s content. It&amp;rsquo;s a good discussion, and I will definitely be looking into picking up the memoir.&lt;/p&gt;
&lt;p&gt;As much as I&amp;rsquo;m leery about the prospects of Perplexity&amp;rsquo;s Comet browser, using an RSS reader is kind of like using a headless browser, and AI is becoming another form of interface for content on the web. The financial incentives shaping popular sources of content are definitely going to shape how we communicate both personally and professionally. If you produce web content (docs, marketing, etc.), it&amp;rsquo;s worth being aware of these structures and how they&amp;rsquo;re changing.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>KCS and Technical Writing</title>
      <link>https://www.kevinrkuhl.com/blog/2025/11/kcs-and-technical-writing/</link>
      <pubDate>Thu, 13 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/11/kcs-and-technical-writing/</guid>
      <description>&lt;p&gt;In &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/10/thinking-strategically-about-documentation/&#34;&gt;a recent post&lt;/a&gt;, I covered various knowledge resources and docs-sites, including a brief discussion about knowledge bases. A common practice for building a knowledge base is &lt;strong&gt;Knowledge Centred Service (KCS)&lt;/strong&gt;. If you&amp;rsquo;re a technical writer, you&amp;rsquo;ve likely encountered it&amp;mdash;and maybe felt uneasy. KCS involves service team members creating articles that look a &lt;em&gt;lot&lt;/em&gt; like your documentation. This can feel redundant, or worse, a &lt;em&gt;threat to your value&lt;/em&gt; as a technical writer.&lt;/p&gt;
&lt;p&gt;My goal for this post is to explain how KCS and traditional technical writing (i.e., writing comprehensive guides for a product or service) differ and, in fact, powerfully supplement one another.&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;&lt;strong&gt;Warning: This is a deep dive!&lt;/strong&gt; If you&amp;rsquo;re a leader or Technical Writer trying to figure out how to have product docs work alongside Knowledge Centered Service (KCS), this post is for you. Here is the TL;DR:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The overlap is a myth:&lt;/strong&gt; Traditional documentation and KCS articles are &lt;em&gt;distinct magisteria&lt;/em&gt; (separate domains) that complement each other.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docs are proactive:&lt;/strong&gt; Technical Writers create the foundational &lt;strong&gt;&amp;ldquo;shared language&amp;rdquo;&lt;/strong&gt; (guides, reference) that users and support staff need to even discuss a product issue.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;KCS is reactive:&lt;/strong&gt; The Solve Loop is a bottom-up process, driven by support teams fixing &lt;em&gt;specific user failures&lt;/em&gt;. Docs should be linked and validated, just like KCS articles. Technical Writers shouldn&amp;rsquo;t be the authors for KCS articles or the bottleneck on publication.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Strategic Value:&lt;/strong&gt; Technical writers are well positioned to contribute to KCS in the evolve loop as a &lt;em&gt;strategic partner&lt;/em&gt;. They can help define the process and templates for KCS, and use the performance data from the Evolve Loop to proactively improve the official product documentation.&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;what-is-kcs&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What is KCS?
  &lt;a href=&#34;#what-is-kcs&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;KCS is a practice for service teams. A service team responds to issues from customers (internal or external). This practice has been developed by the &lt;a href=&#34;https://www.serviceinnovation.org/&#34;&gt;Consortium for Service Innovation&lt;/a&gt;, a non-profit coalition dedicated to excellence in customer engagement.&lt;/p&gt;
&lt;p&gt;What is KCS meant to solve? Organizations without explicit frameworks for capturing and communicating knowledge struggle to scale. Tacit knowledge, held by key members of the community is tied to that individual. While that individual is a valuable resource, they can become swamped &amp;mdash; they are only one person after all! Worse, if that individual leaves an organization, the organization suffers as a whole, since their knowledge goes with them. The goal is to engineer ways of working that transform implicit knowledge into explicit artifacts or resources (capture).&lt;/p&gt;
&lt;p&gt;Additionally, even if you successfully capture knowledge, it then runs the risk of becoming stale, or out of date. So knowledge management frameworks typically involve some kind of process for validating or maintaining your knowledge. Stale or out of date resources need to be validated, updated, or removed.&lt;/p&gt;
&lt;p&gt;The promise is that KCS lets teams answer questions quickly with the latest collective knowledge, optimize self-service for known issues, and drive data-driven improvements for products and services.&lt;/p&gt;
&lt;p&gt;KCs proposes that service focused organizations structure their workflows around two loops for building and evolving knowledge resources:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The Solve Loop&lt;/li&gt;
&lt;li&gt;The Evolve loop&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;rsquo;ll briefly explain both, and talk about how you might interact with them as a technical writer. Note: I&amp;rsquo;m not certified, but I&amp;rsquo;ve had exposure to the methodology, and I&amp;rsquo;ve been considering working towards certification. You can view detailed resources on CSI&amp;rsquo;s &lt;a href=&#34;https://library.serviceinnovation.org/KCS&#34;&gt;library detailing KCS v6&lt;/a&gt;.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-solve-loop&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;The Solve Loop
  &lt;a href=&#34;#the-solve-loop&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Here&amp;rsquo;s the key insight: customer support teams function based on knowledge. A customer experiences an issue with a product, and the support team is equipped with the knowledge to identify the cause and work towards a resolution. When they achieve that resolution, hopefully they have that knowledge in case a similar issue arises. In resolving the problem, the support team is building and validating their understanding of a product. KCS proposes that support teams leverage that moment for two specific knowledge management tasks: &lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/030/010&#34;&gt;capture&lt;/a&gt; and &lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/030/030&#34;&gt;validation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Capture occurs if the team don&amp;rsquo;t have any existing knowledge resources that solve the issue. In this case, the support team does what support does best: investigate the issue and move towards a resolution. As they&amp;rsquo;re doing this, they create an article that identifies relevant background features, the source of the problem, and the steps they take to resolve the problem. After verifying that the article is complete and records the solution, it is published to the knowledge base, ready to be reused the next time a similar issue arises. This knowledge base can be internal or externally facing.&lt;/p&gt;
&lt;p&gt;To facilitate capture, KCS suggests a basic content model of an article, and to use &lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/030/020&#34;&gt;simple templates&lt;/a&gt; with a consistent structure. This helps simplify writing and reading articles. Articles are typically stored in a database and retrieved through search. Because content is generated on a per-issue basis, building a navigable information architecture isn&amp;rsquo;t a priority in KCS implementations. The point isn&amp;rsquo;t to build a resource that is easily traversed by a human in a browser, but to capture and retrieve knowledge. This is a pretty serious perspective shift from how technical writers approach content design &amp;mdash; often by thinking about user needs and coverage for a range of topics.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an &lt;a href=&#34;https://help.salesforce.com/s/articleView?id=001120666&amp;amp;type=1&#34;&gt;example of a KCS resolution article from Salesforce&amp;rsquo;s Help Center&lt;/a&gt;:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/11/kcs-and-technical-writing/help-article.png&#34;
    alt=&#34;An image of an article with the title ACM User Fails to Display or Edit Client Applications, with a structured article body including headers for Resolution, Symptom, Original Description and text describing a user issue.&#34;&gt;
&lt;/figure&gt;

&lt;blockquote&gt;
&lt;p&gt;As a brief aside, some work with LLM-powered chatbots suggest that this kind of clear structure is beneficial for reuse via LLM as well. Continuing to use Salesforce as an example, their Agentforce chatbot is the primary way for users to discover these help articles.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;A key point in KCS is that &lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/030/040/020&#34;&gt;reuse is review&lt;/a&gt;. Validation is the process of confirming the quality of existing resources. A well functioning KCS team searches existing articles to see if the problem has a known solution. If there is an article containing the solution, they validate that the article is complete and correct. During the validation step, they may make minor improvements, and they link the article to the customers tickets. If the article is incorrect, then the article is updated in line with the same steps as in the Capture path. The process is one of &lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/030/040&#34;&gt;continual improvement&lt;/a&gt;, which limits the need for costly comprehensive audits.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a flow chart detailing the process, including steps for more complex solutions or articles that need improvement. If the knowledge base is leveraged for self-service (customers resolving their own issues), an additional step can be added to validate that the article meets standards before being made available to customers:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/11/kcs-and-technical-writing/solve.svg&#34;
    alt=&#34;A flow chart, with branches corresponding to capture, validation, and a flow loop, illustrating the process in the paragraph above.&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s important to note that there&amp;rsquo;s &lt;em&gt;no sense&lt;/em&gt; in which KCS is complete. Knowledge is constantly evolving and created in response to new needs. The methodology is fundamentally bottom-up and focused on continuous improvement of a growing collection of articles.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-evolve-loop&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;The Evolve Loop
  &lt;a href=&#34;#the-evolve-loop&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The solve loop occurs at the event level, where knowledge is produced and used. The evolve loop is a collection of organizational practices meant to ensure the overall health of your knowledge practices and organizational buy-in to KCS. While it sounds like big picture thinking, the evolve loop also involves practices at the article, contributor, and management involvement levels.&lt;/p&gt;
&lt;p&gt;The evolve loop is broken down into four key practices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Assessing content health&lt;/li&gt;
&lt;li&gt;Process integration&lt;/li&gt;
&lt;li&gt;Performance assessment&lt;/li&gt;
&lt;li&gt;Leadership and communication.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Assessing &lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/040/010&#34;&gt;content health&lt;/a&gt; involves using techniques that might be relatable to you as a technical writer. It involves reviewing content to ensure that it meets the structure, and assessing the state of individual articles. It also involves things like defining content standards and ensuring that people are aware of these standards. As the solve loop is bottom-up it says nothing about when to retire articles, so as part of the evolve loop, you will want to set up processes for archiving old articles and cleaning up legacy data (if you&amp;rsquo;ve ever maintained an internal wiki, you&amp;rsquo;ll know how important this task is!).&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/040/020&#34;&gt;Process integration&lt;/a&gt; is about aligning tools and behaviour to ensure that the solve loop is low friction. It involves ensuring that the ticketing tool or CRM and the knowledge management tools are closely aligned. Lowering friction is vital to the success of a KCS program: you need to focus on how issues are individuated and knowledge is retrieved and created in the flow of work. Ways for managers to ensure adherence to KCS methodology are also vital &amp;mdash; while contribution will be varied across a team, it&amp;rsquo;s important to coach support team members as a whole and build skills. This includes building habits while working to retrieve information from your docs site and knowledge base.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I feel like this point is a more significant stumbling block for orgs than they tend to think! If teams are building both a docs site and a knowledge base, then cross-publishing, content duplication, and search are significant risks of failure when implementing KCS.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/040/030&#34;&gt;Performance assessment&lt;/a&gt; focuses on measuring contributions and the success of the program. It involves carefully defining goals, ensuring that there aren&amp;rsquo;t game-able incentives for contributors, and facilitating leadership. It also involves defining roles and ensuring that people who have demonstrated competency and awareness of the knowledge framework and standards are enabled to contribute or provide validation. Competency is key, some service representatives might need to demonstrate core knowledge framework competencies before they can fully contribute or validate content.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://library.serviceinnovation.org/KCS/KCS_v6/KCS_v6_Practices_Guide/030/040/040&#34;&gt;Leadership and communication&lt;/a&gt; is about making the process understood by the organization as a whole. People need to understand how the initiative relates to strategic goals and ways in which they can contribute or relate to the business as a whole. It involves developing and articulating a vision for the KCS process as a whole and ways of promoting and encouraging participation. The KCS practices surrounding leadership heavily discusses metrics, but I do think they take a holistic view noting that it carries throughout the org. Strong KCS leadership involves building collaboration with over teams.&lt;/p&gt;
&lt;p&gt;Both loops are continuous processes, driving the knowledge culture at an organization. The solve loop generates content, and the evolve loop reinforces and improves the content and practices as a whole.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;how-does-it-relate-to-technical-writing&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;How does it relate to technical writing?
  &lt;a href=&#34;#how-does-it-relate-to-technical-writing&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Lets come back to that original complaint:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So all of my support staff are now going to be writing on top of all of their ordinary duties, while over on the product or engineering team, we have a perfectly good technical writer. This all seems to be going very wrong! My support team is writing rather than solving problems and the technical writer output isn&amp;rsquo;t solving customer problems.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Or alternately, from a more strategic perspective, it might look like the technical writer is producing significantly less content than the KCS team. Building and maintaining two platforms that look very similar makes the team that is less directly tied to revenue look more expensive or less productive. And the unfortunate truth is that support has a much easier time tying their initiatives to churn, CSAT, and deflection rates, since this is data about customers.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a couple of points to say about this kind of confusion, which I want to end my post on:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Technical writers have skills to contribute to the KCS ecosystem, but need to be brought in &lt;em&gt;carefully&lt;/em&gt;. They are ill-suited to author articles. And there are opportunity costs and multiple models for contribution.&lt;/li&gt;
&lt;li&gt;Docs and knowledge base articles (as construed by KCS) are distinct, but supplemental worlds. Docs are proactive and foundational, while KCS is reactive and contextual. And these are both resources people need!&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;technical-writers-can-contribute-to-kcs&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Technical writers can contribute to KCS
  &lt;a href=&#34;#technical-writers-can-contribute-to-kcs&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Doing KCS is a lift &amp;mdash; it&amp;rsquo;s difficult and ongoing, requires organizational buy-in, a lot of training, and external factors need to align. In many ways, the processes, practices, and standards it suggests are &lt;em&gt;aspirational&lt;/em&gt; for a company, the north star that guides support operations.&lt;/p&gt;
&lt;p&gt;The mistake is to think that the technical writer should be authoring at the &lt;em&gt;level of the KCS article&lt;/em&gt;. Technical writers aren&amp;rsquo;t engaged in the same interactions that drive the solve loop. They do, however, have expertise in the kind of writing that KCS aspires to, and in fact, a technical writer can be a valuable asset as part of the assessment and editing flow in the solve loop.&lt;/p&gt;
&lt;p&gt;There is, however, a concern with this model: this can diminish both technical writer velocity and KCS velocity by introducing a bottleneck on publication. There are often more support agents than technical writers and technical writers are already busy keeping pace with your engineering team’s output.&lt;/p&gt;
&lt;p&gt;My suggestion for this kind of workflow is to view the technical writer as a coach, rather than as a check or valve &amp;mdash; they should champion writing standards to the contributing team and they are experts in automated tools should be used to help ensure the quality of content in KCS articles.&lt;/p&gt;
&lt;p&gt;The other potential route for involvement is enlisting their help in content modeling and KCS design. They can help define the structure of your article types, and provide guidance on how to add categories and other kinds of metadata to your knowledge base, ensuring that these things align with your broader product guides and resources. Technical writers are uniquely positioned as a high-value add when it comes to defining and explaining the product and bringing them into the evolve loop can improve the ecosystem as a whole.&lt;/p&gt;
&lt;p&gt;Still, I think leaders looking to involve technical writers in their KCS flows should be cautious. KCS is demand driven, and technical writers highest-value time should not be spent as a reactive editor. The tactical route for involvement is enlisting their help in &lt;em&gt;content modeling&lt;/em&gt; and &lt;em&gt;coaching&lt;/em&gt;. A stronger use is as a strategic partner, helping shape the architecture of your knowledge articles, and benefitting from the evidence that a KCS system can provide.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;different-content-for-different-purposes&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Different content for different purposes
  &lt;a href=&#34;#different-content-for-different-purposes&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The complaint I started with stems from a simple confusion: we tend to refer to any written output of business units as &lt;em&gt;documentation&lt;/em&gt;. But product/engineering embedded technical writers are doing something fundamentally different from KCS. To borrow a term from philosophy of science, product documentation and KCS articles are &lt;strong&gt;distinct magisteria&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Stephen J Gould&amp;rsquo;s idea of &lt;a href=&#34;https://en.wikipedia.org/wiki/Non-overlapping_magisteria&#34;&gt;non-overlapping magisteria (NOMA)&lt;/a&gt; is that religion and science are directed at different questions, with different standards for evaluating correctness. Science is directed at answering questions about how the world works, while religion is directed at answering questions about morality, meaning, and how we should live. The methods of science aren&amp;rsquo;t suited to answering those questions, and the methods of religion aren&amp;rsquo;t suited for answering questions about how the physical world works. While NOMA itself is a philosophical concept often debated, the core idea&amp;mdash;that different domains (magisteria) have fundamentally different questions and methodologies&amp;mdash;is a powerful lens to apply to technical writing and KCS.&lt;/p&gt;
&lt;p&gt;Product documentation (the proactive and foundational magisterium) is forward-looking &amp;mdash; articles define the intended operation of the product, tell users &lt;strong&gt;what&lt;/strong&gt; the product does, &lt;strong&gt;how&lt;/strong&gt; to use a feature correctly, and provide reference for technical details. They create a &lt;strong&gt;shared language&lt;/strong&gt;. KCS articles (the reactive magisterium) are bottom-up, and created after a failure. They tell the user why something broke, and how to fix that specific contextual scenario. One &lt;strong&gt;defines&lt;/strong&gt; the map, the other &lt;strong&gt;fixes&lt;/strong&gt; the potholes.&lt;/p&gt;
&lt;p&gt;As anyone who has built something knows, users tend to surprise you. Things will break in ways that you can&amp;rsquo;t anticipate &amp;mdash; or rely on configurations outside of what product managers, QA teams, and technical writers can anticipate. The knowledge built by support teams is a valuable guide to what happens after the unexpected happens.&lt;/p&gt;
&lt;p&gt;More importantly, KCS is a &lt;em&gt;reactive&lt;/em&gt; posture. A central challenge for KCS is adapting to &lt;em&gt;changes&lt;/em&gt; or &lt;em&gt;new products&lt;/em&gt;. It&amp;rsquo;s approach allows a team to rapidly scale a knowledge base, but it relies on customers and support sharing a common ground for communication.&lt;/p&gt;
&lt;p&gt;Technical writers should be positioned to be &lt;em&gt;proactive&lt;/em&gt;. Technical writers create the material for building a shared language between &lt;em&gt;internal staff&lt;/em&gt; and &lt;em&gt;users&lt;/em&gt;. There needs to be some kind of common ground between the customer and the support team to identify and resolve issues. Users acquire that language from the product, the documentation, and their onboarding.&lt;/p&gt;
&lt;p&gt;KCS extends that base of knowledge to more complicated scenarios where the system encounters potential failures. Support staff, working from KCS, will go from their knowledge articles to the docs when there are gaps in their knowledge, extending and transforming that foundation into new knowledge. If they&amp;rsquo;ve internalized use-as-review, then they&amp;rsquo;ll be encouraged to create tickets and supplement the docs with their own feedback, just like they identify bugs in the core product.&lt;/p&gt;
&lt;p&gt;This division of labor is precisely why the two supplement each other. KCS articles, with their high volume and explicit ties to support tickets, generate powerful data. If a thousand tickets are being solved by a specific KCS article on a core feature, it tells the technical writer one of three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The official documentation for that feature is missing context&lt;/li&gt;
&lt;li&gt;The official documentation is not findable&lt;/li&gt;
&lt;li&gt;The product has a defect that needs a dedicated guide&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The data transforms the technical writer&amp;rsquo;s work from guessing what users need to &lt;strong&gt;evidence-based documentation planning&lt;/strong&gt;. The solve and evolve loops are sources of data for informing your practice. The core idea is that technical writers are strategic partners who can benefit from data, but help guide the standards and improve the KCS knowledge base in the &lt;strong&gt;evolve loop&lt;/strong&gt;. The more senior a technical writer is, the better positioned they are to help with conversations regarding metadata, retrieval, and content planning to ensure that knowledge base is healthy and up-to-date.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;three-contribution-models&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Three contribution models
  &lt;a href=&#34;#three-contribution-models&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hopefully this has convinced you that technical writing and KCS aren&amp;rsquo;t in conflict, and when done right, are complementary approaches to providing self-service resources. I think technical writers and be involved in KCS in several ways that benefit the program.&lt;/p&gt;
&lt;p&gt;Here is a table summarizing each of the three approaches:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Feature&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Technical Writer as Editor (Tactical)&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Technical Writer as Coach (Enabler)&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Technical writer as architect (Strategic Partner)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Primary Focus&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Daily quality control and editing of articles&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Training support staff on standards and tools&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Defining structure, taxonomy, and feedback loops&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Role in Solve Loop&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Gatekeeper/bottleneck&lt;/strong&gt;: Reviewing and editing articles before publication&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Trainer&lt;/strong&gt;: Championing writing standards, templates&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;No direct involvement&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Role in Evolve Loop&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Perspective on content health, performance assessment&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Facilitator/communicator - helps managers relate&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Uses KCS data to identify improvements in product documentation, insights from product docs inform KCS practices&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Core Value Proposition&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Improved KCS article quality&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Faster adoption of content standards by support staff&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Evidence-Based Strategy&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Risk/Drawback&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Velocity bottleneck, technical writer is pushed into a reactive posture, potentially over-leveraged.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Limited strategic impact, doesn&amp;rsquo;t utilize insights from KCS&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Requires tools for data analysis, expertise&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Relationship between Docs and KCS&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Shared content, responsibility&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Technical writers are expert communicators, facilitating comms skills&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Distinct magisteria: KCS informs docs strategy, docs are the foundation for shared understanding of product&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;While I tend to prefer the third model, I think there are value-adds that technical writers can provide in each. It only becomes a concern if we think that KCS can supplant the proactive, forward looking role that good docs provide.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;concluding-thoughts&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Concluding thoughts
  &lt;a href=&#34;#concluding-thoughts&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Like I mentioned, I was exposed to KCS through my work. Technical writers and support teams should be closely aligned, and I&amp;rsquo;ve benefited from KCS content directly. I think it&amp;rsquo;s a powerful framework, and it gets to the core of something about service-based work that should inform how teams think about building, maintaining, and transferring knowledge.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s easy to view it as something in conflict with or replacing docs entirely. But I hope I&amp;rsquo;ve demonstrated some of the ways that technical writers can contribute to a KCS ecosystem through it&amp;rsquo;s processes, the ways they can benefit from KCS, and the fundamental value that technical writers have for a product.&lt;/p&gt;
&lt;p&gt;The reality is that we have tight budgets, varying incentives, and lots of demanding customers. Transformation and practice is hard, but worthwhile. Adopting KCS isn&amp;rsquo;t about giving up proactively written guides and reference material, it&amp;rsquo;s about building a culture that values knowledge sharing and use. In this light, companies need to address questions about governance and architecture. The questions are part of KCS, but technical writers are well suited to contribute to answering these questions.&lt;/p&gt;
&lt;p&gt;It can be a difficult road building that kind of culture at a company. I think that technical writers as content strategists can be helpful champions, co-architects, and beneficiaries from KCS. I think there&amp;rsquo;s a deeper question of content architecture that I&amp;rsquo;ve hinted at. Tooling (like docs-as-code or a CCMS) gives technical writers a powerful authoring environment, but using those effectively is a core competency of technical writers, not support staff. Enterprise knowledge management solutions give support teams CMS/databases that are easily linked to customer tickets, but the bifurcated systems here create problems (analytics, search, etc.).&lt;/p&gt;
&lt;p&gt;A unified content pool is the dream, but how do you balance the competing needs? Building and designing these systems is tricky to begin with, and made even more urgent as retrieval augmented generation (RAG) and LLMs depend entirely on structured, authoritative content pools for accurate retrieval. KCS struggles with changes due to its reactive posture, and I think technical writers can help with propagation. Involving technical writers in the evolve loop is part of the answer. But these are thoughts for future posts.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the takeaway for leaders and technical writers: KCS is not a replacement for documentation; it’s an opportunity for evidence-based strategy. Strategically minded technical writers are well suited to move beyond serving as an editor to leverage KCS data. Helping to build a knowledge ecosystem that serves both the product and the customer better than either system could alone.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Note: Thanks for making it through this deep dive! If you found this strategic breakdown valuable and want to support more content like this, &lt;a href=&#34;https://www.buymeacoffee.com/kevinrkuhl&#34;&gt;consider buying me a coffee&lt;/a&gt;. I&amp;rsquo;m currently between positions, and I appreciate the support.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tech Writing Webring</title>
      <link>https://www.kevinrkuhl.com/blog/2025/11/webring/</link>
      <pubDate>Sat, 08 Nov 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/11/webring/</guid>
      <description>&lt;p&gt;Following a discussion on LinkedIn about why more technical writers should blog, I&amp;rsquo;ve joined a new project: the &lt;a href=&#34;https://caseyrfsmith.github.io/webring/&#34;&gt;tech writing webring&lt;/a&gt;, started by Casey Smith.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;whats-a-webring&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What&amp;rsquo;s a webring?
  &lt;a href=&#34;#whats-a-webring&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A circular structure of websites that are linked together, organized around a theme or perspective. Basically this was a way to help people discover content prior to search engines. It&amp;rsquo;s a fun, retro-internet approach lines up nicely with my goals and ideals for this site.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;how-do-i-join&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;How do I join?
  &lt;a href=&#34;#how-do-i-join&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To join this webring, add the links to your site and submit a pull request adding your site to &lt;code&gt;sites.json&lt;/code&gt;. See the &lt;a href=&#34;https://github.com/caseyrfsmith/webring&#34;&gt;README&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;implementation-details&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Implementation details
  &lt;a href=&#34;#implementation-details&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Implementation is driven by a simple agreement: all members display a block of links to help people discover other sites in the ring. Sometimes this is done with javascript, but what&amp;rsquo;s cool about this ring is that the requirements for adding it to your site are really pleasantly minimal.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note, going by LinkedIn discussions, this part is optional - but it&amp;rsquo;s part of the fun!&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;All you need to do is add a block of links somewhere on your site, replacing &lt;code&gt;YOUR-SITE-URL&lt;/code&gt; with the URL of your site:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Part of the &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://caseyrfsmith.github.io/webring/&amp;#34;&lt;/span&gt;&amp;gt;tech writing blog webring&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt; | 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://caseyrfsmith.github.io/webring/navigate.html?action=prev&amp;amp;site=YOUR-SITE-URL&amp;#34;&lt;/span&gt;&amp;gt;Previous&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt; | 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://caseyrfsmith.github.io/webring/navigate.html?action=next&amp;amp;site=YOUR-SITE-URL&amp;#34;&lt;/span&gt;&amp;gt;Next&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt; | 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;href&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://caseyrfsmith.github.io/webring/navigate.html?action=random&amp;amp;site=YOUR-SITE-URL&amp;#34;&lt;/span&gt;&amp;gt;Random&amp;lt;/&lt;span style=&#34;color:#f92672&#34;&gt;a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These are connected to the ring, and you can use those to find people who also blog about technical writing. The final step is submitting a pull request to update the list of sites in the public GitHub repository&amp;rsquo;s JSON file.&lt;/p&gt;
&lt;p&gt;Adding this to my site involved four steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Defining a partial (reusable block at the template level) to add the webring text to content on this site.&lt;/li&gt;
&lt;li&gt;Adding the partial to a conditional block in my singles layout(the template) that handles specific elements for blog pages (publishing the title, date, etc.).&lt;/li&gt;
&lt;li&gt;Updating the site with these new elements.&lt;/li&gt;
&lt;li&gt;Making a pull request to add my site to the webring.&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;whats-next-with-this-blog&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What&amp;rsquo;s next with this blog
  &lt;a href=&#34;#whats-next-with-this-blog&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve been taking a little time off from blogging recently, focused on recharging my batteries, but I have some long-form content coming down the pipeline.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;upcoming-posts&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Upcoming posts
  &lt;a href=&#34;#upcoming-posts&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I do have a couple of long form posts that are coming down the pipeline. There&amp;rsquo;s been some good discussions in Write the Docs about &lt;em&gt;knowledge-centered service&lt;/em&gt; (KCS) and &lt;em&gt;Salesforce&lt;/em&gt;, and it&amp;rsquo;ll be nice to get a bunch of thoughts about knowledge management out of my brain. I hope they&amp;rsquo;ll help fellow technical writers if they encounter these very different methodologies in the wild.&lt;/p&gt;
&lt;p&gt;These pieces are in the editing phase and are definitely long form content (3,500 words-ish). My goal, however, is to shift back to shorter, more frequent content once these are published. So keep that in mind if you&amp;rsquo;re going to follow my &lt;a href=&#34;https://www.kevinrkuhl.com/blog/index.xml&#34;&gt;RSS feed&lt;/a&gt;.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;how-i-want-this-site-to-work&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;How I want this site to work
  &lt;a href=&#34;#how-i-want-this-site-to-work&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The other side is I really want to finish the &lt;em&gt;publish-on-own-site and syndicate everywhere&lt;/em&gt; (POSSE) script for this Hugo site, and share it on my Github page. The goal is to have a Python script handle syndication for blogposts to Mastodon/Bluesky, using the front matter from the posts (typically a short description).&lt;/p&gt;
&lt;p&gt;This way, there&amp;rsquo;s always RSS for places where you can control how you receive content from me, but then social media becomes a way of getting additional discovery out there. That way everything I author is stored here.&lt;/p&gt;
&lt;p&gt;The big thought is to follow cool projects like this one by &lt;a href=&#34;https://brojonat.com/posts/bluesky-hugo-comments/&#34;&gt;Jon Brown&lt;/a&gt; which use federated social media as the comment system for your site. This would transition the discussion from one-to-many (me broadcasting) to many-to-many (easier, direct discussion).&lt;/p&gt;
&lt;p&gt;These project developments will probably also end up here, so if that sounds interesting, feel free to follow along in an RSS reader (for now!).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Thinking Strategically About Documentation</title>
      <link>https://www.kevinrkuhl.com/blog/2025/10/thinking-strategically-about-documentation/</link>
      <pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/10/thinking-strategically-about-documentation/</guid>
      <description>&lt;p&gt;As a technical writer, you will contribute to different kinds of documentation projects. It’s important that documentation responsibilities are aligned with a &lt;em&gt;coherent strategy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;One of the biggest things to know about documentation (that people don’t think about) is that the word &lt;em&gt;documentation&lt;/em&gt; &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/09/self-advocacy/&#34;&gt;is polysemous&lt;/a&gt;. The various meanings pretty much guarantee that at more chaotic employers you will be pulled in different directions unless you have a clear strategy or posture when it comes to working as a technical writer.&lt;/p&gt;
&lt;p&gt;I didn’t go into the various definitions in my previous post, but there are three main meanings at play in a company:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Official information source&lt;/strong&gt; &amp;mdash; The canonical guide to a product or service.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Normative guide&lt;/strong&gt; &amp;mdash; This formalizes a decision and guides the behaviour of people (think project documentation, process documentation).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evidential material&lt;/strong&gt; &amp;mdash; Evidence that a control, process, or system is in place.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These three senses of documentation often overlap: team process documentation is from an authoritative source (a manager) and can be a form of evidence that the team does something (for a compliance audit), but it also guides behaviour (the process is only valid if people are held accountable/follow it). Sometimes these definitions come apart: a user manual describes how to use or complete tasks. It’s not a guide to how people should go about working (in the same sense as process documentation) or a guide to what should be done as part of a project. And the same piece of documentation can function differently depending on how an engineering team operates. An &lt;a href=&#34;https://swagger.io/specification/&#34;&gt;OpenAPI spec&lt;/a&gt;, depending on spec-first or code-first engineering, can be either guide the writing of code or describe what has already been written.&lt;/p&gt;
&lt;p&gt;Technical writers can contribute to all three kinds of documentation! The problem arises when employers fail to carefully define lanes of responsibility and prioritize work for technical writers. And, unfortunately, this is particularly common for teams where they feel the need for a technical writer, but don’t have experience with one on staff. In this case, the company is at the bottom of the &lt;a href=&#34;https://passo.uno/docs-hierarchy-of-needs/&#34;&gt;docs hierarchy of needs&lt;/a&gt;. Any documentation is good documentation, and the incoming technical writers are supposed to deliver the solution to their &lt;em&gt;problems&lt;/em&gt;. Managers and leaders from across the company will see you as a &lt;em&gt;resource&lt;/em&gt; they can use to help with &lt;em&gt;their documentation needs&lt;/em&gt;, in whatever ways they’ve internalized the meaning of the word &lt;em&gt;documentation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is a recipe for chaos and the technical writer becoming overwhelmed. And it&amp;rsquo;s why it’s important (as a technical writer) that you build this &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/09/self-advocacy/&#34;&gt;shared understanding with your immediate manager&lt;/a&gt; and ensure it’s communicated to your &lt;em&gt;company as a whole&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Having a clear sense of why, what, who, where, and how is part of what I call a &lt;em&gt;documentation posture&lt;/em&gt; or &lt;em&gt;strategy&lt;/em&gt;. Aligning your work with a strategy involves framing how readers will interact with your output and where your core responsibilities fall.. These can then inform your metrics for evaluating your output and ultimately, which platforms you’ll work with. Having an explicit, shared understanding between you and your manager is key for your success as a technical writer.&lt;/p&gt;
&lt;p&gt;This post is a bit of a brain dump of terminology used in software companies. By the end, however, you&amp;rsquo;ll have an understanding of what goes into framing a coherent docs strategy and ways in which you can define your responsibilities as a writer. Hopefully this is helpful to leaders considering working with technical writers, or technical writers trying to make sense of vague job postings!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;products-audiences-and-support-models&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Products, audiences, and support models
  &lt;a href=&#34;#products-audiences-and-support-models&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Since software products and support models can take various forms, documentation sites look very different from company to company. A lot of technical writing materials assume that there’s a single thing, &amp;ldquo;docs&amp;rdquo;, that we produce. But I think that there’s differences in the kind of output that are worth describing when framing your documentation posture. So, this post will be a brief guide to the different kinds of docs sites that you might have to contribute to as a technical writer working at a &lt;em&gt;software as a service&lt;/em&gt; (SaaS) company.&lt;/p&gt;
&lt;p&gt;For this post, I want to focus on a particular kind of thing that technical writers are uniquely positioned to contribute to: &lt;em&gt;documentation sites&lt;/em&gt;. A documentation site is an electronic resource that provides material that meets documentation needs, and can be publicly available or locked down to require user logins. They are a living resource that is updated as your software product changes (unlike hardware manuals!). Documentation is a (typically written) electronic resource that lives on the docs site. It could be served as web pages, PDFs, videos, etc. and it can be authored through a variety of tools.&lt;/p&gt;
&lt;p&gt;Unsurprisingly, there is no single or standard way of doing this. Understanding the audience’s needs is key to choosing the right solution. Here are a few different models for user needs that documentation sites can address:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developers&lt;/strong&gt; need materials that &lt;em&gt;enable&lt;/em&gt; them to build with a software development kit (SDK) or application programming interface (API).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Administrators&lt;/strong&gt; need &lt;em&gt;guides&lt;/em&gt; oriented around common configuration and maintenance tasks for complex, multi-user apps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Users&lt;/strong&gt; need &lt;em&gt;guides&lt;/em&gt; on how to complete certain tasks within an application (typically through a graphical user interface).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Users/admins/developers&lt;/strong&gt; should have the option to &lt;em&gt;self-support&lt;/em&gt; and &lt;em&gt;troubleshoot&lt;/em&gt; common issues that arise when trying to use your product.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal staff&lt;/strong&gt; need &lt;em&gt;resources&lt;/em&gt; to provide &lt;em&gt;support&lt;/em&gt; to customers experiencing problems with your software.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal staff&lt;/strong&gt; must be able to &lt;em&gt;easily create&lt;/em&gt; and &lt;em&gt;find&lt;/em&gt; resources on their projects or how to work with other teams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internal staff&lt;/strong&gt; need to &lt;em&gt;demonstrate&lt;/em&gt; that they know what to do in certain circumstances and &lt;em&gt;evidence&lt;/em&gt; to external auditors that processes exist.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In choosing a strategy, you need to have a clear sense of why users are coming to find documentation, how they’re navigating through it, and how you’ll evaluate whether what you are doing is useful. This will vary based on what your product is, who your product is for, what they&amp;rsquo;re trying to do with it, and how much involvement your customer facing teams have in the support process.&lt;/p&gt;
&lt;p&gt;In the next section, I’ll break these down into central categories, and explain some of the tools that are used in building and maintaining them, and why you might adopt any mixture of these platforms.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;three-models-of-documentation-practice&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Three models of documentation practice
  &lt;a href=&#34;#three-models-of-documentation-practice&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So! I think bearing in mind the multiple meanings of documentation and the different product categories, there are three main approaches to meeting those needs: there are comprehensive guides, enhancements for user experience, and resources for normative guidance/evidence. As a technical writer, I’ve interviewed for roles involving, or worked on, each of these in some capacity. Each of these needs is better supported by different solutions, so I’ll explore each a bit more closely.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;comprehensive-guides&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Comprehensive guides
  &lt;a href=&#34;#comprehensive-guides&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The first category emphasizes documentation as comprehensive guides or resources. In these instances, the goal is to provide a resource that is like the full operational manual to your software. These are most often in place for products where they are intended to be consumed by technical, engaged users who are comfortable getting into the details of how your product functions. Often these products are for developers &amp;mdash; who interact with your product through code &amp;mdash; but there are cases where a similar level of attention is necessary for products with user interfaces as well.&lt;/p&gt;
&lt;p&gt;It’s important for scenarios where your readers need to build understanding, but also refer to how the parts work to achieve their goals. When contributing to these sites, you’re trying to provide feature coverage. If it’s for administrators, you’ll provide guidance on how to configure integrations, user categories, and permissions. If it’s for end users, you’ll cover the main features and workflows in your app. Once you’ve achieved coverage and are able to maintain it, you can move on to focus on improving the experience and offering tailored learning paths or fancy interactive features.&lt;/p&gt;
&lt;p&gt;In this case, you’ll often see webpages that use terms like “developer portal”, “API Guide”, or “Docs site”. You can find these at &lt;code&gt;developer.product-name.com&lt;/code&gt; or &lt;code&gt;docs.product-name.com&lt;/code&gt; (with the notable exception of Google Docs). These sites are often focussed on displaying content in an easy to read manner, and built to quickly get skilled people into interacting with your product through tutorials and code samples. Larger tables of reference pages are built from automated resources, like an &lt;a href=&#34;https://swagger.io/specification/&#34;&gt;OpenAPI spec&lt;/a&gt; &amp;mdash; a standard way of describing an API and how it will respond to requests.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Note on Content Architecture: CCMSs and DITA&lt;/p&gt;
&lt;p&gt;While many of the tools listed below (Static Site Generators, or SSGs) focus on generating a single, static web experience (a single endpoint), large, complex organizations with numerous products, versions, or regulatory requirements often adopt a Component Content Management System (CCMS), frequently built around the DITA (Darwin Information Typing Architecture) standard. This is not a site type, but rather a content architecture where content is broken into reusable topics. This approach allows a single source of truth to be published to many endpoints (websites, PDFs, embedded help in apps) &amp;mdash; which is essential for large enterprise products. This post largely focuses on web endpoints, so I’m including this here for the sake of completeness!&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Here’s a quick breakdown of how these three categories come apart:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Site Type&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Primary Audience&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Core User Intent (Consumption Model)&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Primary Business Goal&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Typical Tooling/Stack&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Example&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Developer Portal&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;External Developers, Partners&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Conceptual &amp;amp; Tutorial (How to build/integrate)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Increase adoption/API usage; grow ecosystem. Often multiple APIs and/or SDKs. Developers can manage/monitor services within the portal.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SSG (Docusaurus, Hugo, Sphinx), dedicated frameworks.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://discord.com/developers/docs/intro&#34;&gt;Discord developer portal&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;API Reference&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;External Developers&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Reference (Lookup specific parameters/syntax)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Enable quick, correct implementation of code.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;API Spec Integration (OpenAPI/Swagger + Redoc/Stoplight). Can be embedded in SSGs or platforms like Mintlify, Fern.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://docs.github.com/en/rest?apiVersion=2022-11-28&#34;&gt;GitHub REST API Docs&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Docs Site&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;External Users, Admins, Customers&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Procedural &amp;amp; Conceptual (How to use/configure the product)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Drive successful product setup; reduce churn via clarity.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SSG (Hugo, Sphinx), CMS (traditional or headless), CCMS (Paligo, Oxygen) to a publishing endpoint.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://www.mongodb.com/docs/&#34;&gt;MongoDB Docs&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you’re hiring a technical writer to contribute to these kinds of docs, you’ll want them working closely with your engineering team. They’ll need access to the API and test environments so they can verify that code samples function. Users might rely on the information architecture to explore, but often use a combination of search tactics to find the information that they need and quickly leave the site.&lt;/p&gt;
&lt;p&gt;The bulk of technical writer resources on the internet are geared towards technical writers functioning in this kind of space. Why? Well, documentation is necessary for these products to be used. If you’re interacting with an API, there isn’t a graphical interface to guide you to completing key tasks. For apps that focus on user experience, however, things differ.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;enhancements-for-ux&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Enhancements for UX
  &lt;a href=&#34;#enhancements-for-ux&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The second approach is to build resources to supplement a user&amp;rsquo;s experience of a product. Generally speaking, companies that adopt this approach tend to have intuitive products or onboarding for user bases that are less likely to spend time working with specific references. These sites are less focused on in-depth product reference and more on providing resources that develop and enhance a user&amp;rsquo;s journey with a product. They may be built to support and develop skills through structured learning. Like other docs, these could be delivered publicly or as part of a customer portal.&lt;/p&gt;
&lt;p&gt;These resources are part of the overall world of customer experience (CX). If you are contributing to this part of a docs strategy, you will be best served working within the CX function. Overall, the metrics here are deflection and efficiency. Is there a reduction in support tickets after publishing an article about a common issue? Are onboarding goals being met? Are certifications being maintained?&lt;/p&gt;
&lt;p&gt;Rather than expecting users to navigate through these resources, there’s an emphasis on searchability and task-oriented content. There may be a higher volume of shorter, highly specific articles developed along with support teams. In some cases, there may be no visible navigation structure for external audiences (knowledge bases built explicitly to be searched, rather than browsed).&lt;/p&gt;
&lt;p&gt;These kinds of resources live at domains like &lt;code&gt;help.product-name.com&lt;/code&gt; or &lt;code&gt;learn.product-name.com&lt;/code&gt;. They often make sense in contexts when there’s a larger or broader user-base that is less engaged with the technical details of the product, though some platforms make sense when it’s important to track or reward the development of knowledge.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Site Type&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Primary Audience&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Core User Intent (Consumption Model)&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Primary Business Goal&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Typical Tooling/Stack&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Example&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Docs Site&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;External Users, Admins, Customers&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Procedural &amp;amp; Conceptual (How to use/configure the product)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Drive successful product setup; reduce churn via clarity.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;SSG (Hugo, Sphinx), CMS (traditional or headless), CCMS (Paligo, Oxygen) to a publishing endpoint.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://www.mongodb.com/docs/&#34;&gt;MongoDB Docs&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Help Center&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;External users, admins, customers&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Procedural &amp;amp; Task (Quick solve, self-service)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Deflect Support Cases; improve customer satisfaction (CSAT).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Customer Service Platform (Zendesk Guide, Intercom).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://help.dialpad.com/&#34;&gt;DialPad Help Center&lt;/a&gt; (contrast with their &lt;a href=&#34;https://developers.dialpad.com/docs&#34;&gt;Developer Docs&lt;/a&gt;)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Knowledge Base (KB)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Internal support agents, sometimes external&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Task &amp;amp; Procedural (Solve known issues efficiently)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Increase Agent Efficiency; ensure consistency of support answers.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Customer Service Platform (Salesforce Service Cloud, Zendesk).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Salesforce &lt;a href=&#34;https://help.salesforce.com/s/articleView?id=001119120&amp;amp;type=1&#34;&gt;Help Articles&lt;/a&gt; – see this specific example for an example with no visible IA, but externally published and searchable. These kind of KBs are well suited to providing chunkable content for RAG powered AI tools.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Learning Management System (LMS) / Customer Academy&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;External learners (Users, New Admins)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Conceptual &amp;amp; Tutorial (Structured learning, Certification)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Structured Onboarding; reduce support load through education.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Dedicated LMS Platform (Teachable, Moodle).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Salesforce’s &lt;a href=&#34;https://trailhead.salesforce.com/&#34;&gt;Trailhead&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;When contributing to these systems, technical writers usually partner with Support and Customer Success to identify high-volume pain points. It’s often the case that technical writers aren’t the sole contributor, or these systems are owned by people outside of the function entirely. Learning systems in particular are highly multi-modal, and dedicated instructional design professionals will work on LMSes. If a support team practices knowledge-centered service, support team members might author articles that you edit prior to external publication. There’s a variety of models here.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A quick note: &lt;em&gt;training&lt;/em&gt; is an activity or event, but it is also sometimes used as a content type. Slipping between the two can happen here, just like with documentation! An article can be a self-training resource, an LMS is a guided experience that supports learning and training.&lt;/p&gt;&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;guidance-and-evidence&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Guidance and evidence
  &lt;a href=&#34;#guidance-and-evidence&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, there is the documentation that keeps the company running smoothly, ensures internal alignment, and protects the organization legally. These are rarely public facing, but as a technical writer, you’re often regarded as the expert on information architecture, governance, and clarity.&lt;/p&gt;
&lt;p&gt;Common goals for these kinds of artifacts are alignment and compliance. Internal resources help teams align by making sure that engineers use the same UI components, new hires get up to speed quickly, and that decisions are logged and searchable. For compliance, the goal is often purely evidential &amp;mdash; demonstrating that certain controls and processes exist and are followed.&lt;/p&gt;
&lt;p&gt;Writers engaged in this kind of work are often embedded in ops or services teams, and work assignments come in to support experts or managers within a larger company. A technical writer has a domain knowledge in how to communicate processes clearly in writing that managers might not have, and help with standards and clarity on these kinds of documents.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Site Type&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Primary Audience&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Core User Intent (Consumption Model)&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Primary Business Goal&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Typical Tooling/Stack&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Example&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Team Wiki / Internal Knowledge&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Internal Teams (Eng, PM, Marketing)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Reference &amp;amp; Process (Decide, Align, Onboard)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Organizational Alignment; formalize decisions (ADRs); speed up new hire ramp-up.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Collaboration Software (Confluence, Notion, SharePoint).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Gitlab&amp;rsquo;s &lt;a href=&#34;https://handbook.gitlab.com/handbook/product/ux/technical-writing/&#34;&gt;Technical Writing Team Handbook&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Component Library / Design System&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Developers, Designers&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Reference &amp;amp; Conceptual (Standardize UI, find reusable code)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Consistency &amp;amp; Scalability; enforce brand and UX standards.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Storybook documentation, Figma design system&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://www.lightningdesignsystem.com/2e1ef8501&#34;&gt;Lightning SLDS&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Compliance Docs / Audit Artifacts&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Internal Governance Risk and Compliance (GRC), External Auditors&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Evidential &amp;amp; Reference (Prove controls, show history)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Mitigate Legal/Financial Risk; achieve certifications (SOC 2, ISO, HIPAA).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Document Control Systems, SharePoint/Word, tools that generate reliable PDF/LaTeX output (e.g., Doxygen, MadCap Flare).&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;a href=&#34;https://aws.amazon.com/compliance&#34;&gt;AWS Compliance Resources&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Writers might not &lt;em&gt;write&lt;/em&gt; every internal policy, but they can help create efficient templates, manage the structure of the wiki or repositories, and help enforce quality standards to ensure that critical knowledge is accessible and trusted. This kind of internal documentation has the potential to be the biggest spot where responsibilities can slip &amp;mdash; if you are a technical writer embedded in an engineering team, you might produce internal documentation on Confluence regularly. This kind of expertise will look tempting to directors outside of your team.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;developing-a-posture&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Developing a posture
  &lt;a href=&#34;#developing-a-posture&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;One of the core challenges of being a technical writer in changing or smaller companies isn’t just writing, but navigating the views of directors and managers from across a company. I previously talked about building a shared expectation with your immediate manager. Without a clear documentation posture on all three needs, it’s very easy to be pulled in every direction: struggling to maintain product guides, supplementing user support, and managing internal organizational knowledge.&lt;/p&gt;
&lt;p&gt;This is why developing a clear documentation posture is critical for both your success and the coherence of your company’s knowledge ecosystem.&lt;/p&gt;
&lt;p&gt;You should think of it as an explicit, shared agreement on four points:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Core responsibilities&lt;/strong&gt;: For both technical writers and other internal staff. Which is your primary focus as a technical writer? Who contributes to other forms of documentation?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Success metrics&lt;/strong&gt;: Adoption? Deflection rates? Internal efficiency and compliance?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Governance&lt;/strong&gt;: Who owns the content? Who is responsible for the information architecture?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Platforms&lt;/strong&gt;: Where will the content go? What tools and permissions need to be in place to work at scale for that platform?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By answering these questions and having a clear sense of platforms and responsibilities, you can move from having “docs” as a vague “need” or “requirement” and have a coherent plan for working with your technical writers as strategic hires within an organization. You can assess whether your docs are meeting needs, and come up with plans for improvement. This kind of clarity serves as a strong defense against competing priorities, reduces burnout, and sets up your staff members for success.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>CT Smith: Docs-like-Stripe is a Cargo Cult</title>
      <link>https://www.kevinrkuhl.com/blog/2025/10/docs-like-stripe/</link>
      <pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/10/docs-like-stripe/</guid>
      <description>&lt;p&gt;Great post from &lt;a href=&#34;https://docsgoblin.com/blog/25-10-11-cargo-cult.html&#34;&gt;CT Smith&lt;/a&gt; at &lt;a href=&#34;https://docsgoblin.com&#34;&gt;docsgoblin.com&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At a previous role, WE WANT DOCS LIKE STRIPE was directed at me, with full eye contact during a meeting, by a leadership team that refused to give me any money for tooling or development resources. I cracked and said &amp;ldquo;Stripe has like seven engineers on their doc tooling alone, I&amp;rsquo;m not sure what you expect from me with my current resourcing. Could you help me prioritize?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I left shortly after this conversation. Trust, it&amp;rsquo;s been one of many times I&amp;rsquo;ve heard this in job interviews, chats with founders, really any conversation about documentation where the tech writers were outnumbered. Tech writers love lambasting this request when we get together to talk shop, pointing out that companies always want docs like Stripe&amp;rsquo;s, but but they don&amp;rsquo;t ever want to invest in docs like Stripe does.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;It&amp;rsquo;s important to leverage expectations with the resources available, and the unfortunate truth is that companies tend not to have as many resources going towards their documentation. This is true not just for resources like investment or team members, but also in providing time and tools for people to onboard to your systems. I pretty clearly list the tools I&amp;rsquo;m comfortable with on my resume. I can adapt and learn new tools, but you&amp;rsquo;ll have to give me time to get up to speed with them &amp;mdash; and this can be both the things that are documented by your vendor, but also the things you&amp;rsquo;ve built inside of it. And my first pass is not going to be at a professional level.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also important to note what goes unsaid when someone relies on comparison and focuses on the presentation layer:&lt;/p&gt;
&lt;blockquote class=&#34;my-6 p-4 border-l-4 border-gray-300 bg-gray-50 italic&#34;&gt;
    
    &lt;p class=&#34;mb-0&#34;&gt;&lt;p&gt;People who say this think that the docs are in the &amp;ldquo;look&amp;rdquo; or the tool used to build them, or even their perceived comprehensiveness or complexity. They think things like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If we have the same tool Stripe uses for their docs, our docs will be that good too!&lt;/li&gt;
&lt;li&gt;If we make the docs look like Stripe&amp;rsquo;s, our docs will be good too!&lt;/li&gt;
&lt;li&gt;If we have a lot of docs like Stripe, our docs will be good too!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They see the finished product, without any understanding of the kind of work and care that it took to bring it into existence, and say &amp;ldquo;Yes, just like that!&amp;rdquo; and then try to reverse engineer it based on appearances without ever going beyond the presentation layer.&lt;/p&gt;
&lt;/p&gt;

    
    
&lt;/blockquote&gt;
&lt;p&gt;Definitely a good reminder that indirect reference through an example is a bit of a shortcut in communication, and we should always strive to communicate more clearly.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why Link Blog</title>
      <link>https://www.kevinrkuhl.com/blog/2025/10/why-link-blog/</link>
      <pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/10/why-link-blog/</guid>
      <description>&lt;p&gt;A couple of my more recent posts have been &amp;ldquo;link blogs&amp;rdquo;, but what am I doing when I do that and why put the effort in at all?&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;what-is-a-link-blog&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What is a link blog?
  &lt;a href=&#34;#what-is-a-link-blog&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A link blog post is a short blog post for something that I&amp;rsquo;ve read, which interests me. I&amp;rsquo;ll publish a link, some commentary, and any excerpts that interest me. The goal is for them to be brief.&lt;/p&gt;
&lt;p&gt;This idea is loosely taken from &lt;a href=&#34;https://simonwillison.net/2024/Dec/22/link-blog/&#34;&gt;Simon Willison&amp;rsquo;s Weblog&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I proposed two categories of content that are low stakes and high value: &lt;strong&gt;things I learned&lt;/strong&gt; and &lt;strong&gt;descriptions of my projects&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I realize now that link blogging deserves to be included a third category of low stakes, high value writing. We could think of that category as &lt;strong&gt;things I’ve found&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That’s the purpose of my link blog: it’s an ongoing log of things I’ve found&amp;mdash;effectively a combination of public bookmarks and my own thoughts and commentary on why those things are interesting.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I really enjoy reading Simon Willison&amp;rsquo;s link blog posts&amp;mdash;they&amp;rsquo;re short and insightful. They broaden my perspective on working in and with technology. So I figured I&amp;rsquo;d share a little bit about why I&amp;rsquo;m adopting that practice on my own blog.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-link-blog&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why link blog?
  &lt;a href=&#34;#why-link-blog&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The plan for this blog was to have it be a mixture of personal and professional content. As a technical writer, I&amp;rsquo;m a technologist. A user and creator of technology. So mostly, my blog posts will be about technology as it intersects with my life, my personal projects, etc.&lt;/p&gt;
&lt;p&gt;There are three main reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;Building a record&lt;/li&gt;
&lt;li&gt;Contributing to a better Internet&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;simplicity&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Simplicity
  &lt;a href=&#34;#simplicity&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is about simplifying my blogging practice some.&lt;/p&gt;
&lt;p&gt;Like many writers, I find it easy to &lt;em&gt;over write&lt;/em&gt;. If I get into a good flow state, all of a sudden there&amp;rsquo;s thousands of words in front of me, and not all of them are good. I have a folder in the GitHub repo for this site containing various drafts and ideas that I&amp;rsquo;ve been working on. Some may end up published, a lot won&amp;rsquo;t. Feeling comfortable putting a 3000 word post out there without an editor is something that takes time and effort. Anything that I put on the web is a reflection of who I am, to some extent, and this website is part of my professional presence.&lt;/p&gt;
&lt;p&gt;While I want to write long form pieces, the significance and effort can be limiting, and it&amp;rsquo;s easy to fall out of a practice.&lt;/p&gt;
&lt;p&gt;By identifying an alternate form of blogging, I can blog more regularly, and keep engaged with this website as a project. I have a rough limit of a couple of paragraphs of my thoughts about what I&amp;rsquo;ve been reading. The goal is to identify something of interest, then add something like a thought, a connection to something that I read, record my thoughts and move on. The simplicity of the format frees me from a lot of anxiety about having to polish something a bit longer.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;building-a-record&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Building a record
  &lt;a href=&#34;#building-a-record&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Like many writers, I really enjoy the act of reading. Books yes, but I still like reading articles, blog posts, interesting read-mes or conceptual pieces, wiki articles, and more. The variety and amount of written content is part of what makes the Internet a good and valuable thing.&lt;/p&gt;
&lt;p&gt;Having a record of what I&amp;rsquo;ve read, and what thoughts those things have prompted in me is valuable for my own curiosity and learning. Sure I can bookmark things in my browser, but if you&amp;rsquo;re like me, your bookmarks are a messy morass. My &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/01/local-news/&#34;&gt;RSS reader&lt;/a&gt;, &lt;a href=&#34;https://www.inoreader.com/&#34;&gt;Inoreader&lt;/a&gt;, is great and I routinely save things to come back to later, but also allows for stronger navigation of resources.&lt;/p&gt;
&lt;p&gt;But with a link blog, I can add my own thoughts and connections. The blog becomes a record of what I was thinking about as I read those things. And that&amp;rsquo;s valuable for me when I come back to them later. If you&amp;rsquo;re reading and following this, you might be interested in the same kinds of things that I&amp;rsquo;m interested in and I hope that once or twice a week, some of my thoughts about the Internet, culture, or technology will be valuable for you as well.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;building-a-better-internet&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Building a better Internet
  &lt;a href=&#34;#building-a-better-internet&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The Internet is at it is best when its filled with multiple voices and perspectives. Amplifying other voices, platforms, tools, perspectives is an easy way to contribute to this version of the Internet. In many ways, the Internet of 2025 feels oppressive. But as Molly White notes in her talk at &lt;a href=&#34;https://www.youtube.com/watch?v=MTaeVVAvk-c&#34;&gt;XOXO in 2024&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That’s because what really sucks about the web these days, what has us feeling despair and anger, has everything to do with the industry that has formed around the web, but not the web itself. The web is still just a substrate on which anything can be built. Most importantly, the web is the people who use it, not the companies that have established themselves around it.&lt;/p&gt;
&lt;p&gt;And the widespread disillusionment that we’re seeing may actually be a good thing. More people than ever have realized that the utopian dreams of a web that could only bring about positive and wonderful things might have been misguided. That tech companies maybe don’t always have our best interests in mind. And that slogans like &amp;ldquo;don’t be evil&amp;rdquo; might be more about marketing than about truth.&lt;/p&gt;
&lt;p&gt;With this knowledge comes power. The power to shape the web that we want to see, while fighting against the one that we don’t. The tech industry has structural and financial power of its own, to be sure, but the only thing that enables the kind of rot&amp;mdash;and to quote Cory Doctorow, “enshitification”&amp;mdash;that we’ve seen spread throughout the platforms that now form a large part of people’s online experiences, is the platforms’ stranglehold on the web. And that is tenuous.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I want a &lt;a href=&#34;https://www.noemamag.com/we-need-to-rewild-the-Internet/&#34;&gt;wild Internet&lt;/a&gt;, where people can easily create what they want, with minimal constraints from platform providers.&lt;/p&gt;
&lt;p&gt;A personal blog is part of that project. It&amp;rsquo;s a way to contribute to more perspectives and share other voices that are writing and contributing to the same project. I hope that authors who find their way here get something out of my thoughts about their writing, or that people who end up following my blog find something of value from the content on my site.&lt;/p&gt;
&lt;p&gt;The main point is that this record is something I own, I can make freely available, and can be accessed independent of algorithms that are meant to shape people&amp;rsquo;s attention. You can add this site to your RSS reader. Or you might stumble across a link to my thoughts in a social media algorithm.&lt;/p&gt;
&lt;p&gt;The independence and accessibility of it is something that&amp;rsquo;s worthwhile, rather than keeping my thoughts locked up inside of LinkedIn or another closed ecosystem.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;how-to-build-a-link-blog&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;How to build a link blog
  &lt;a href=&#34;#how-to-build-a-link-blog&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are a number of ways to do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I build this website with &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;, a simple static site generator. This means my content is mostly Markdown files on my laptop, which are turned to HTML, and I can move from host to host. The only costs are hosting (negligible to free) and the domain name/DNS. There&amp;rsquo;s a bit of a learning curve, but on the whole a curious, intelligent person can create their own site easily.
&lt;ul&gt;
&lt;li&gt;If you are a developer you may want to pivot to a SSG that uses a language you are familiar with. Jekyll, Astro, Pelican, are all strong alternatives and there&amp;rsquo;s many more out there.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If you want a less hands-on experience, I strongly recommend &lt;a href=&#34;https://www.ghost.org/&#34;&gt;Ghost&lt;/a&gt;. Ghost is a service for publishing newsletters and blogs. Like Substack, without some of the complicated politics.&lt;/li&gt;
&lt;li&gt;WordPress is a bit more of a traditional blogging engine, though I feel like the ecosystem can be overwhelming at first, you might be interested in this if you are a more visual person.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I like about Hugo is my ability to control and tweak many aspects of this site, while keeping the costs low. Aside from the domain name, with the amount of traffic I receive, the cost of my personal website is pretty much negligible.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in doing something similar, the broad steps are to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Experiment with &lt;a href=&#34;https://gohugo.io/getting-started/quick-start/&#34;&gt;building a Hugo site on your computer&lt;/a&gt;, choose a theme that supports blogging, and get a working mockup together.&lt;/li&gt;
&lt;li&gt;Purchase a domain name &amp;mdash; this &lt;a href=&#34;https://www.cloudflare.com/learning/dns/how-to-buy-a-domain-name/&#34;&gt;article from Cloudflare&lt;/a&gt; goes into this topic in detail.&lt;/li&gt;
&lt;li&gt;Configure a hosting service and transfer your site to that hosting service. Here&amp;rsquo;s &lt;a href=&#34;https://gohugo.io/host-and-deploy/host-on-github-pages/&#34;&gt;Hugo&amp;rsquo;s walkthrough on how to do this with Github Pages&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Map the DNS records for your domain name to your hosting service (Here&amp;rsquo;s a &lt;a href=&#34;https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site&#34;&gt;tutorial from Github Pages&lt;/a&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Details will vary based on your service providers, so please take these steps as a rough guide. Ultimately, once you&amp;rsquo;ve got the hang of deploying your site, it&amp;rsquo;s a good feeling, and you&amp;rsquo;ll be able to build your own little pocket of thoughts on the internet, making it a better place for everyone.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dropout: Keep the Internet Weird</title>
      <link>https://www.kevinrkuhl.com/blog/2025/09/keep-the-internet-weird/</link>
      <pubDate>Tue, 23 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/09/keep-the-internet-weird/</guid>
      <description>&lt;p&gt;My TV watching habits have changed pretty dramatically with the times. I still love shows like NBC&amp;rsquo;s Hannibal&amp;mdash;dark, aesthetic, dramatic. But more often than not, I find myself reaching for something a bit more lighthearted and fun. I&amp;rsquo;m nerdy. I&amp;rsquo;m a millennial. In short, I&amp;rsquo;m the target audience of &lt;a href=&#34;https://www.dropout.tv&#34;&gt;dropout.tv&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Depending on your interests, you might have been exposed to Dropout from one of the short social media clips that make their way around various services. Or you might have been exposed to it through Dimension20, if you&amp;rsquo;re the sort of person who plays or is into Dungeons and Dragons. Either way, this is the sort of niche streaming service that provides me with lighthearted bits of skilled comedians and improvisers doing their thing. It&amp;rsquo;s been one of the subscriptions that I don&amp;rsquo;t regret in the slightest.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;ownership-and-advertising-revenue&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Ownership and advertising revenue
  &lt;a href=&#34;#ownership-and-advertising-revenue&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You might, if you&amp;rsquo;re the sort of person who&amp;rsquo;s been into internet comedy long enough, recognize a number of the comedians from &lt;strong&gt;CollegeHumor&lt;/strong&gt;. Dropout has had an interesting history as a business &amp;mdash; being given the freedom to pursue it&amp;rsquo;s own direction after acquisition by private equity. And it&amp;rsquo;s current trajectory makes it compelling as an alternative to other streaming services. Here&amp;rsquo;s an &lt;a href=&#34;https://www.theverge.com/podcast/781331/hank-green-sam-reich-dropout-collegehumor-game-changer&#34;&gt;insightful conversation with Sam Reich, the current CEO of Dropout&lt;/a&gt; on the history and trajectory of Dropout:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dropout was a priority that came out of IAC, which was our corporate parent at the time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This was who owned CollegeHumor?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is who owned CollegeHumor, and for years and years, IAC was trying to figure out how we would make not just a lot of money, but a lot, a lot of money. And there was always kind of a… A cynic might call it a get-rich-quick scheme at the time. It was ad sales, and then social media took a big chomp out of ad sales, and then it was television. It turned out television production didn’t scale very effectively. And then finally, the idea was, let’s try going direct-to-audience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Just to go over-the-top, as they say. I’m not sure exactly what the top we’re going over is, but we’re going over the top of something. I guess the whole system.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That phrase makes it feel like we’re gambling the house, and in a way, we were. There was a collection of executives who were very bullish about this within CollegeHumor. I wasn’t necessarily one of them. I slowly but surely warmed up to it, imagining that if it didn’t work, at least we’d get to create our own cool stuff for a while. The notion was to go direct-to-audience. There won’t be the gatekeepers that there are in Hollywood. We won’t have to start over every year like we do in ad sales. That is, by the way, one of the intrinsic benefits of subscription: you’re not starting your business over every year, versus ad sales, where you have to go out and sell every year.&lt;/p&gt;&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;rewilding-the-internet&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Rewilding the Internet
  &lt;a href=&#34;#rewilding-the-internet&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The conversation covers the history, the business model, the platform they use for streaming and some interesting speculation about what they&amp;rsquo;re doing right. One thing that particularly struck me was the reference to Homestar Runner, later on in the interview:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Interesting. Is there, on the list of reasons that you like this or want to do this, we talked about this before, but let’s end here with this. Is [the idea] that people aren’t doing things weird enough, and you want to do things weird, on that list?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One hundred percent. You and I have connected a lot on the topic of Homestar Runner over the years. Homestar Runner may be hugely responsible for my career taking the direction it has. It was incredibly influential on me. And something I loved about it was like, it felt like a walled garden of weird that existed at a URL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Yeah. That resonates.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And I think about how sometimes I wish that I could plant a forest full of weird trees on the internet. I wish that the internet were still a place where, just like there was really fun, mysterious, hopeful stuff that existed a URL away. I would hope that Dropout can just be one of those things.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That shared sense of weird is also part of why I&amp;rsquo;m very into what they&amp;rsquo;re doing with Dropout. But more importantly, it echoes a vision of the internet that I hope we can reclaim. &lt;a href=&#34;https://www.noemamag.com/we-need-to-rewild-the-internet/&#34;&gt;This essay&lt;/a&gt; by Maria Ferrell and Robin Berjon talks a bit about how the internet would function better if we would &lt;em&gt;rewild&lt;/em&gt; it. Encourage an ecosystem where individual creators can build and share information freely, independent of particular platforms.&lt;/p&gt;
&lt;p&gt;One thing that gives me hope is that the same tools I use to build gardens of docs make publishing a blog relatively easy and painless. What&amp;rsquo;s interesting to see from this piece is how platforms like Vimeo OTT give them the freedom to build their own subscription services for comedy streaming, independent of dependency on ad revenues. It&amp;rsquo;ll be interesting to see how technologies like &lt;a href=&#34;https://www.kevinrkuhl.com/blog/2025/08/guide-to-atproto/&#34;&gt;atproto&lt;/a&gt; can help facilitate cultivating your own ecosystems further.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Self-Advocacy for Technical Writers</title>
      <link>https://www.kevinrkuhl.com/blog/2025/09/self-advocacy/</link>
      <pubDate>Fri, 19 Sep 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/09/self-advocacy/</guid>
      <description>&lt;p&gt;One of the things that has surprised me most in my career was the extent to which you may need to advocate for your skills and the utility of your profession within a changing workplace. As a technical writer, it&amp;rsquo;s easy to say you produce documentation, but &lt;em&gt;&amp;ldquo;documentation&amp;rdquo; is a word that means many different things to different people.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ideally, you have a manager with a clear vision of the work you can produce, strong quarterly goals, and adequate tooling. But that isn&amp;rsquo;t always the case.&lt;/p&gt;
&lt;p&gt;Here’s a story that truly drove home the need to advocate for your profession.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;that-sinking-feeling&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;&lt;strong&gt;That sinking feeling&lt;/strong&gt;
  &lt;a href=&#34;#that-sinking-feeling&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;You&amp;rsquo;re going to have a lot more technical writing like that to look forward to.&amp;rdquo;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;A senior leader said this to me, probably intending to be reassuring. To be honest, I had a sinking feeling in my stomach. I had just spent time working closely with a product manager on a lengthy proposal for a new architectural project. My work included articulating the proposed solution, modeling costs and ROI, and helping to identify potential risks.&lt;/p&gt;
&lt;p&gt;The unfortunate thing is that this isn&amp;rsquo;t what technical writers typically do—in fact, it&amp;rsquo;s almost the exact opposite. I was helping someone write about what a system &lt;em&gt;could&lt;/em&gt; or &lt;em&gt;would&lt;/em&gt; be like. Technical writers are trained to dive into &lt;em&gt;how&lt;/em&gt; systems work, providing instructions for how to &lt;em&gt;use&lt;/em&gt; those systems to achieve specific goals. In manufacturing or hardware, we produce user manuals. In software, we produce the content that ends up on websites like &lt;a href=&#34;https://docs.stripe.com/&#34;&gt;Stripe&amp;rsquo;s documentation site&lt;/a&gt; or &lt;a href=&#34;https://www.mongodb.com/docs/&#34;&gt;MongoDB&amp;rsquo;s Docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Software technical writers are, to borrow a term from Fabrizio Ferri Benedetti, &lt;a href=&#34;https://passo.uno/tech-writer-learn-to-code/&#34;&gt;devlings&lt;/a&gt;&amp;mdash;technically minded people who are interested in and capable of figuring out how a product works to create web-based content that helps users understand it.&lt;/p&gt;
&lt;p&gt;The document I was working on was the sort of thing that &lt;em&gt;product managers&lt;/em&gt; and &lt;em&gt;business analysts&lt;/em&gt; produce. I was happy to contribute because I wanted to be a team player, but that senior leader&amp;rsquo;s statement drove home something I believe every junior technical writer &lt;strong&gt;needs to understand&lt;/strong&gt;, especially if they are the first or only technical writer at a small company.&lt;/p&gt;
&lt;p&gt;Documentation is &lt;strong&gt;polysemous&lt;/strong&gt;. Different people mean different things when they use the word.&lt;/p&gt;
&lt;p&gt;Engineers are expected to produce &lt;strong&gt;documentation&lt;/strong&gt;. Managers are expected to produce &lt;strong&gt;process documentation&lt;/strong&gt;. If your company undergoes a SOC audit, controls will need to have &lt;strong&gt;documentation&lt;/strong&gt;. Project leads? They have to produce &lt;strong&gt;documentation&lt;/strong&gt;. One of the unfortunate truths about working in a knowledge-based company is that just about everyone has to produce &lt;strong&gt;documentation&lt;/strong&gt; and they&amp;rsquo;d much rather be doing the &amp;ldquo;real work&amp;rdquo; instead of writing. Support teams are a great source of knowledge, but ideally, they&amp;rsquo;re turning that knowledge into documentation, too.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not malicious. People will simply see you as a resource to help with their specific documentation needs. You will need to defend your own projects and territory, because in most scenarios, you&amp;rsquo;ll be at capacity trying to produce and maintain end-user documentation for your company&amp;rsquo;s products.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-not-draw-the-line&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;&lt;strong&gt;Why not draw the line?&lt;/strong&gt;
  &lt;a href=&#34;#why-not-draw-the-line&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If project documentation is a skill and responsibility for other departments, and you&amp;rsquo;re already quite busy with your core responsibilities, why would you want to help with that kind of project?&lt;/p&gt;
&lt;p&gt;In my case, I was having trouble getting authorization for the projects I really envisioned. We were a team in transition. But the main reason was to try and steer the team toward a more mature workflow: it was nice to see a project take the shape of what I would call &lt;em&gt;project documentation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Project documentation includes things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Business Requirement Document (BRD)&lt;/strong&gt;: Outlines the business goals for a project, typically for stakeholders.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Product Requirements Document (PRD)&lt;/strong&gt;: Defines features and functionality for developers and designers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User stories&lt;/strong&gt;: Simple, short descriptions of a feature from the end user&amp;rsquo;s perspective.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User personas&lt;/strong&gt;: Descriptions of target users, including goals and pain points.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Architectural Decision Records (ADRs)&lt;/strong&gt;: Documents the &amp;ldquo;why&amp;rdquo; behind key design choices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Technical/System Design Documents (TDD/SDD)&lt;/strong&gt;: A blueprint of components, data models, APIs, or technologies for developers and architects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Charters&lt;/strong&gt;: Captures who authorized the project, high-level goals, key stakeholders, and project boundaries.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project Plans&lt;/strong&gt;: Outlines the scope, timeline, budget, and resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Risk Registers&lt;/strong&gt;: Details potential risks, their impact, and mitigation strategies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decision Logs&lt;/strong&gt;: A record of key project decisions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;m definitely capable of contributing to these kinds of documents. I&amp;rsquo;ve framed personas and user stories in situations where that information was tacit knowledge shared among the team members who designed and implemented a system. I&amp;rsquo;ve also written project charters, plans, and risk registers for my own projects.&lt;/p&gt;
&lt;p&gt;The problem is that most of these documents require a kind of knowledge and involvement that a technical writer lacks. In an ideal world, I&amp;rsquo;m relying on PRDs, ADRs, and TDDs to write my documentation. The more these documents exist before a product is built, the more knowledge I have when I interact with the released product.&lt;/p&gt;
&lt;p&gt;I think one of the unfortunate consequences of Agile escaping into broader business culture is that these kinds of documents are seen as unnecessary steps. This happens when teams forget about the word &lt;strong&gt;&amp;ldquo;comprehensive&amp;rdquo;&lt;/strong&gt; and fail to pay attention to the many meanings of &lt;strong&gt;&amp;ldquo;documentation.&amp;rdquo;&lt;/strong&gt; Agile was a response to attempts to comprehensively scope out entire projects and rigidly adhere to waterfall schedules. The right attitude is to have &amp;ldquo;just enough documentation,&amp;rdquo; and some complex projects require writing to get your ideas on a page.&lt;/p&gt;
&lt;p&gt;The core of design, product, and project work is envisioning a future state. To ensure alignment, you need to communicate it. By building a culture where we had clear examples of early-stage documents and working closely with team members to build them, I hoped to help institute a cultural shift that prioritized reasonable product documentation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is a bit of an aside: I think one of the shifts with GenAI is that these kinds of docs are starting to fall away. I don&amp;rsquo;t mean to imply they&amp;rsquo;re all necessary, but I do think some record of design decisions is necessary once a project hits a certain level of complexity. The interesting thing is negotiating what this looks like with the existing team culture and new tools.&lt;/p&gt;&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;self-advocacy&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;&lt;strong&gt;Self-advocacy&lt;/strong&gt;
  &lt;a href=&#34;#self-advocacy&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;m not opposed to working in a lone-writer environment. There are lots of things that are exciting and invigorating about these kinds of companies. But there are a lot of competing demands, and you cannot rely on leadership to understand your skills and contributions. This is even true in cases where you work embedded in a team.&lt;/p&gt;
&lt;p&gt;For this reason, having a game plan for self-advocacy is crucial. If you&amp;rsquo;re a technical writer like me, this probably doesn&amp;rsquo;t come naturally. The idea of self-advocacy can feel like selling or bragging, which I&amp;rsquo;m personally uncomfortable with. Here are some steps I&amp;rsquo;ve committed to that help me advocate for my work in a way that feels authentic and comfortable.&lt;/p&gt;
&lt;p&gt;One thing I plan on doing is using the words &amp;ldquo;documentation&amp;rdquo; or &amp;ldquo;docs&amp;rdquo; less when I describe my contributions. As much as I love &lt;a href=&#34;writethedocs.org&#34;&gt;Write the Docs&lt;/a&gt; as a community, &amp;ldquo;documentation&amp;rdquo; has too many possible interpretations. Terms like &amp;ldquo;feature-specific user guides,&amp;rdquo; &amp;ldquo;API references,&amp;rdquo; &amp;ldquo;installation guides,&amp;rdquo; and &amp;ldquo;quick starts&amp;rdquo; are all much clearer.&lt;/p&gt;
&lt;p&gt;Here are a couple of things I plan on striving to do, whenever I join a company:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Build a strong, shared understanding of my role&lt;/strong&gt; with my immediate manager and create a plan for how I can be assigned work. Having a sample process document that you can adapt to new environments is a great conversation starter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Find a time and way to introduce myself and my expertise.&lt;/strong&gt; It may be a short presentation explaining what skills I bring, what kinds of work I&amp;rsquo;ve done, and my process for working with other teams. This helps set up guardrails and channels for incoming work. It&amp;rsquo;s also important to build relationships with key customer-facing teams in addition to your developer and product management teams. Most importantly, this presentation will emphasize the value of product docs for all roles in the company. If product documentation explains what and how are product works, it is a helpful knowledge resource for marketing and sales. If this isn&amp;rsquo;t an opportunity, I&amp;rsquo;ll build my own profile in Confluence or SharePoint, so that people can understand my perspective and skills.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be engaged and champion our content in Slack/Basecamp/Discord&lt;/strong&gt;. I&amp;rsquo;ve been in situations where people have asked questions like, &amp;ldquo;What are the differences between these three features/products?&amp;rdquo; in our group chat. It&amp;rsquo;s a good question that points to a confusing area in our product, and I think they genuinely didn&amp;rsquo;t know that good documentation sites can help resolve those kinds of questions. By answering these questions and championing your site, you&amp;rsquo;re increasing the visibility of your work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Celebrate contributors&lt;/strong&gt;. Knowledge is a shared enterprise. Building relationships and celebrating team members who take to the time to give you good feedback is important for driving adoption of your work within the company. By expressing gratitude and value for colleagues who contribute feedback, you can build a culture where leadership acknowledges the value of your work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintain a log of my wins and lessons.&lt;/strong&gt;. I try to keep daily notes on my work. It&amp;rsquo;s important to round these up into wins and lessons. It&amp;rsquo;ll help when I meet with managers to talk about my work. Along with that, find a way to measure outcomes by collaborating with support and other customer facing teams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Show up for engineers and PMs&lt;/strong&gt;. These teams are the core of what I do. While I&amp;rsquo;m building advocacy and learning, it&amp;rsquo;s important to collaborate and work with the engineers who build the products I&amp;rsquo;m writing about.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a starting point, but these commitments build a practice of self-advocacy that doesn&amp;rsquo;t feel like bragging. They help build recognition for your work beyond your immediate team and foster a culture where your contributions are understood and valued.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Kuba Suder: Introduction to AT Protocol</title>
      <link>https://www.kevinrkuhl.com/blog/2025/08/guide-to-atproto/</link>
      <pubDate>Tue, 26 Aug 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/08/guide-to-atproto/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;ve been interested in understanding the world of Bluesky and AT Proto, &lt;a href=&#34;https://mackuba.eu/&#34;&gt;Kuba Suder&lt;/a&gt; has been writing excellent blog posts. I&amp;rsquo;ll be following along closely, since I think that algorithmic choice is going to be an extremely important feature of any social media framework that I would want to use.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://mackuba.eu/2024/02/21/bluesky-guide/&#34;&gt;A Complete Guide to Bluesky&lt;/a&gt; serves as an introduction to Bluesky, as an app:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But that’s just the tip of the iceberg. Bluesky has built a system where anyone with a server and some knowledge of coding can implement their own algorithmic feeds that they can share with everyone else. There are currently about 40 thousands custom feeds (as of Feb 2024) made by the Bluesky community that you can add to your app. And more importantly, the “Following” and “Discover” feeds are just what you start with by default – you can set any of the thousands of other feeds as your main feed, and you can even remove the two built-in feeds if you don’t like them, and leave e.g. only the “Cat Pics” custom feed as your only feed tab. Nothing here is forced on you.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This is from the section on &lt;a href=&#34;https://mackuba.eu/2024/02/21/bluesky-guide/#feeds&#34;&gt;feeds&lt;/a&gt;, but I think the sections on &lt;a href=&#34;https://mackuba.eu/2024/02/21/bluesky-guide/#safety&#34;&gt;safety and moderation&lt;/a&gt;, and features like &lt;a href=&#34;https://mackuba.eu/2024/02/21/bluesky-guide/#starter-packs&#34;&gt;starter packs&lt;/a&gt; are helpful if you&amp;rsquo;re looking to understand Bluesky.&lt;/p&gt;
&lt;p&gt;More interesting is his recent post &lt;a href=&#34;https://mackuba.eu/2025/08/20/introduction-to-atproto/&#34;&gt;Introduction to AT Protocol&lt;/a&gt;. For someone interested in the technical workings of the world behind Bluesky, this is a great introductory post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The system they’ve built, of which Bluesky was initially meant to be just a tech demo, is called the Authenticated Transfer Protocol, or AT Protocol, or ATProto. Bluesky is built on ATProto, and it is in practice a huge part of what ATProto currently is, which makes the boundary between Bluesky and non-Bluesky a bit hard to define at times, but it’s still only a subset of it.&lt;/p&gt;
&lt;p&gt;Bluesky in this second meaning is some nebulous thing that consists of: the data types (“lexicons”) that are specific to the Bluesky microblogging aspect of ATProto, like Bluesky posts or follows; the APIs for handling them and for accessing other Bluesky-specific features; the rules according to which they all work together; and the whole “social layer” that is created out of all of this, the virtual “place” – the thing that people have in mind when they say “this website”, even when it’s accessed through a mobile app. One of the coolest things about Bluesky &amp;amp; ATProto, in my opinion, is that it connects many different independent pieces into something that still feels like one shared virtual space.&lt;/p&gt;
&lt;p&gt;People outside the company can create (and are creating) other such things on ATProto that aren’t necessarily Bluesky-related – see e.g. WhiteWind or Leaflet (blogging platforms), Tangled (GitHub alternative), Frontpage (Hacker News style link aggregator), or Grain (photo sharing site). They use the same underlying mechanisms that are at the base of ATProto, but use separate data types, have different rules, goals, and UIs.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The whole post serves as an excellent conceptual introduction to the world of ATProto. I&amp;rsquo;m curious about building some basic integrations from this website to bluesky and the Fediverse, and will be making reference to this post (and subsequent ones in the series!) as I start to explore.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Drew Bruenig on Reasoning Models and Chain of Thought</title>
      <link>https://www.kevinrkuhl.com/blog/2025/04/bruenig-on-chain-of-thought/</link>
      <pubDate>Mon, 21 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/04/bruenig-on-chain-of-thought/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s an excellent post on &amp;ldquo;reasoning&amp;rdquo; and &amp;ldquo;chain of thought&amp;rdquo; models by Drew Bruenig: &lt;a href=&#34;https://www.dbreunig.com/2025/04/11/what-we-mean-when-we-say-think.html&#34;&gt;What We Mean When We say &amp;ldquo;Think&amp;rdquo;&lt;/a&gt;. It provides a history, and description of how these pieces of technology function, and makes predictions about how certain kinds of testing will shape the perceptions of the utility of LLMs.&lt;/p&gt;
&lt;p&gt;All in all, it&amp;rsquo;s a good read if &lt;strong&gt;you&lt;/strong&gt; want to think carefully about this technology.&lt;/p&gt;
&lt;p&gt;In particular, there&amp;rsquo;s a clear discussion of reinforcement learning (RL) and the economic factors that go into it both it&amp;rsquo;s application, which makes a pretty persuasive case for the following predictions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;Models will keep getting better at testable skills: Quantitive (&lt;em&gt;sic&lt;/em&gt;) domains – like programming and math –&amp;ndash; will continue to improve because we can use unit tests and other validation methods to create more synthetic data and perform more reinforcement learning. Qualitative chops and knowledge bank capabilities will be more difficult to address with synthetic data techniques and will suffer from a lack of new organic data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;An AI perception gap will emerge: Those who use AIs for programming will have a remarkably different view of AI than those who do not. The more your domain overlaps with testable synthetic data and RL, the more you will find AIs useful as an intern. This perception gap will cloud our discussions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m inclined to agree - LLMs function significantly better in some areas than others and it&amp;rsquo;s likely to only intensify.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What Makes a Good Technology</title>
      <link>https://www.kevinrkuhl.com/blog/2025/04/what-makes-a-good-technology/</link>
      <pubDate>Sun, 20 Apr 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/04/what-makes-a-good-technology/</guid>
      <description>&lt;p&gt;This is a question I&amp;rsquo;ve been asking myself lately. It&amp;rsquo;s exciting to be living through the advent of what feels like a major technological change, but I feel like this isn&amp;rsquo;t a question we never really stop to think about. So much of our lives are immersed in technology and influenced by its creators. And pivoting from philosophy to a career in &amp;ldquo;tech&amp;rdquo; &amp;mdash; by which society mostly means software these days, well, it leaves me feeling reflective.&lt;/p&gt;
&lt;p&gt;I do know what kinds of enduring technologies exist that I love and I know what kinds of technologies exist that frustrate me. In my &lt;a href=&#34;https://www.kevinrkuhl.com/about&#34;&gt;About&lt;/a&gt; page, I mention that I think that RSS, the bicycle and Wikipedia are examples of &lt;em&gt;great&lt;/em&gt; technologies. I mean that in a normative (and moral) sense. They&amp;rsquo;re the sort of thing that I think are genuinely praiseworthy. So, let&amp;rsquo;s see what kind of a theory we can come up with to account for why.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;what-is-technology&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What is technology?
  &lt;a href=&#34;#what-is-technology&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is our first stop. Did you expect anything different from someone who spent too much time in the philosophy room? I think how we answer this actually has important results for how we evaluate technologies.&lt;/p&gt;
&lt;p&gt;Technologies, first off, are things that are &lt;em&gt;produced&lt;/em&gt;, they&amp;rsquo;re the result of some kind of directed action.They also require the application of &lt;em&gt;knowledge&lt;/em&gt; (whether explicit or implicit), in pursuit of achieving some kind of &lt;em&gt;end&lt;/em&gt;. Technologies can be used for things other than their intended ends, but technologies have a functional goal that result from their standard application. Importantly, technologies also require that things be a certain sort of way in order for them to function. This is both social and material.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a certain sort of weak normative force around technology. There is a sense that you should use it in certain ways that&amp;rsquo;s related to the original goals (e.g., you should hit a nail with the flat end of a hammer, not the claw, if you want to drive it in effectively). And technologies that are easy to use in that sort of way are good at what they do. This isn&amp;rsquo;t moral force, but technologies are forces for coordinating the world around us.&lt;/p&gt;
&lt;p&gt;And it&amp;rsquo;s in that normative sense that I think we can evaluate technologies as &lt;em&gt;good&lt;/em&gt; or &lt;em&gt;bad&lt;/em&gt; on their own terms. This is a kind of functional goodness. It&amp;rsquo;s good for the task it was meant to be put to. We can also evaluate technologies in terms of the outcomes they are designed to produce and how they require us to organize materials and people (both of these are moral evaluations). A technology is organized towards achieving some kind of goal and it&amp;rsquo;s good or bad in terms of both the nature of the goal and in terms of how well/easily it facilitates achieving that goal. It&amp;rsquo;s genuinely important to evaluate technologies in terms of both of these parameters.&lt;/p&gt;
&lt;p&gt;For example, license plate reader cameras are a remarkably effective technology in terms of the functional achievement of their goal. They enable the &lt;a href=&#34;https://www.forbes.com/sites/larsdaniel/2024/10/22/warrantless-surveillance-federal-lawsuit-challenges-flock-safety-cameras/&#34;&gt;vast collection of data&lt;/a&gt;, the coordination of those datasets, and access to that data by law enforcement organizations. But the construction of a surveillance state is not a laudatory goal, as it is vulnerable to abuses by bad actors such as &lt;a href=&#34;https://www.kansas.com/news/politics-government/article291059560.html&#34;&gt;this officer&lt;/a&gt; who used it to stalk an ex-girlfriend. So I think we can use both senses when evaluating technologies.&lt;/p&gt;
&lt;p&gt;But I don&amp;rsquo;t want to focus on bad technologies. I think that it&amp;rsquo;s more powerful if technologists (people who care about and deploy technology) have a sense of what good technologies are and use that to shape and coordinate their efforts. And it&amp;rsquo;s important to have these discussions so that we can evaluate new and emerging technologies and systems.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;good-tech&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Good tech
  &lt;a href=&#34;#good-tech&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-bicycle&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;The bicycle
  &lt;a href=&#34;#the-bicycle&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Let&amp;rsquo;s start with the bicycle. Bicycles might seem a little weird to include in my understanding of technology, after all, this started with my reflections on software, right?&lt;/p&gt;
&lt;p&gt;Bicycles have been around since the 19th century in various forms. The functional goal of the bicycle is to convey a person using two wheels, and the mechanical effort of the rider, translated through pedals. This goal - transporting a person, is pretty excellent. It allows them to achieve a variety of other goals in reduced time. It can also be recreational and social. So on the whole, the bicycle passes the goal check.&lt;/p&gt;
&lt;p&gt;But how well do they achieve this goal? Well, this is an interesting point - because it depends on the bicycle and the conditions you find yourself in. It&amp;rsquo;s why we see so many different forms. My single speed road bike excels in flat urban environments. A downhill mountain bike with full suspension and knobbly tires could go places that my commuter could never do that. Both scenarios require a bit of expertise to use, and also the presence of certain kinds of infrastructure.&lt;/p&gt;
&lt;p&gt;I think it&amp;rsquo;s important to note though, that the idea of a bicycle imposes very few costs or burdens on the world around it. In many ways, bicycles easily fit with the rest of our social and technological fabric. It doesn&amp;rsquo;t generate pollution and only requires me to eat and stay healthy to operate. With a few basic tools and parts, I can perform most of the maintenance my bicycle needs. This is an important part of why I think that it&amp;rsquo;s a good technology &amp;mdash; it requires spaces where I can operate it (though those are mostly spaces that exist) and minimal upkeep that I can provide by myself.&lt;/p&gt;
&lt;p&gt;There are some drawbacks however: manufacturers have specialized parts so the supply chain might not always be available. And I may be sweaty when I arrive at my destination. And it&amp;rsquo;s not a great means of conveyance for larger distances and using it in the winter is a bit of a hardship. But for getting groceries, a short commuting, or popping over to a coffee shop? It&amp;rsquo;s much better than a car.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve had my bicycle for more than decade, and it was purchased used. It takes me all kinds of places. It&amp;rsquo;s fun, it&amp;rsquo;s relaxing, it&amp;rsquo;s reliable. It&amp;rsquo;s the sort of thing where I&amp;rsquo;m considering get another specialized bicycle so that I could ride more in harder conditions. It&amp;rsquo;s a good technology.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;wikipedia&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Wikipedia
  &lt;a href=&#34;#wikipedia&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Wikipedia is interesting &amp;mdash; the technology is built for the communal aggregation of knowledge. It&amp;rsquo;s a database and a front end that comes together to produce a website where anyone can functionally contribute knowledge.  If it was just that, though, it&amp;rsquo;d be a horrible mess of edit wars and chaos. It&amp;rsquo;s also an organization, and a scheme of processes about how to make those contributions. It&amp;rsquo;s that social coordination through norms that makes it relatively successful.&lt;/p&gt;
&lt;p&gt;People can attempt to coopt and influence it, but &lt;a href=&#34;https://www.nytimes.com/2019/05/30/business/north-face-wikipedia-leo-burnett.html&#34;&gt;if a company attempts to use it for marketing purposes&lt;/a&gt;, these processes attempt to shove the whole enterprise back on to the rails. Strong norms regarding citations and point-of-view in authorship make it an excellent place to conduct initial research on a topic, pointing you to primary resources that can be the basis for successful direct research. In many ways, it&amp;rsquo;s the perfect secondary source to get you started, even if it&amp;rsquo;s a little messy at times.&lt;/p&gt;
&lt;p&gt;Because Wikipedia is a collection of open knowledge, the practices, standards, and what is done on it, are all transparent. That&amp;rsquo;s how it builds it&amp;rsquo;s trust. It&amp;rsquo;s kind of remarkable that these are the things that the blockchain is supposed to provide. In part, I think this is because of the social goals behind both technologies, and that Wikipedia functions because of the ease and transparency of contributions. So, I think that Wikipedia is a great example of how the &lt;em&gt;social&lt;/em&gt; dimensions of the technology work to set a standard.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also not perfect. Standards and practices can vary within communities inside of the contributor culture. Learning and understanding Wikipedian culture and terms is a process. And low priority articles can tend to be messy. But it&amp;rsquo;s a genuinely impressive and vast collection of knowledge that is freely accessible on the internet, maintained by a non-profit and volunteers. It&amp;rsquo;s an astounding achievement of people coordinating effort, software, and practices to produce an objectively valuable resource.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;rss&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;RSS
  &lt;a href=&#34;#rss&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I feel like folks who might find their way to my blog are familiar with RSS. It stands for &lt;em&gt;really simple syndication&lt;/em&gt;. I feel like this is probably a little contentious as a candidate for inclusion, since it&amp;rsquo;s probably a thing that most people thought died out as blogs went out of fashion.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the basic idea behind RSS. If I publish a stream of content to the internet (say blog posts, podcast episodes, videos, etc.) I can have a single file on my website that summarizes the posts into a feed. People who would like to access the feed can use programs that are built to interpret that standard and consume the feed on their own devices.&lt;/p&gt;
&lt;p&gt;So if you use a podcast aggregator, then there&amp;rsquo;s a pretty good chance that you use RSS. As someone who writes a blog, complete with an RSS feed, it&amp;rsquo;s easy to set up and configure, and when I publish changes to my website, the RSS feed updates automatically. So it&amp;rsquo;s pretty great from an author perspective.&lt;/p&gt;
&lt;p&gt;From the perspective of someone consuming writing or podcasts, a feed aggregator/reader is a powerful tool. I can control how my tool presents content to me - and I have a chronological feed of posts from a range of sources. I can choose to bulk skip posts from particular aggressive publishers. It offers me a great deal of control about how I receive what you put out.&lt;/p&gt;
&lt;p&gt;Why did these fade away? A big reason is that open content and advertising weren&amp;rsquo;t served by this mode of content delivery. And social networks began to provide streamlined, high engagement content. But I think that podcasts have been so viable shows that there&amp;rsquo;s ways to deliver content regularly. RSS is also a bit of a mess: as a standard it&amp;rsquo;s difficult to enforce, and different websites may use different versions of the feed. It&amp;rsquo;s an old standard that faces the difficult problem of being superseded by a new standard. It&amp;rsquo;s also difficult to monetize.&lt;/p&gt;
&lt;p&gt;But the idea of integration of feeds is alive and well, and I think quite exciting in the ideas behind federated social media at Mastodon and Bluesky. Podcasts are a great reminder as to why this technology is great: enabling you to control the algorithm and build your own collections of media. So I&amp;rsquo;m optimistic for things to come, and will point to RSS as a powerful form of one-to-many communication.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;concluding-thoughts&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Concluding thoughts
  &lt;a href=&#34;#concluding-thoughts&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So, I&amp;rsquo;ve discussed a bunch of technologies and what makes them good or bad technologies. I think that we should celebrate good technologies. And that identifying them involves thinking about the goals they achieve, how we use them to achieve those goals, and what kinds of demands they make on the world. We live in an era where people are enthusiastic about technology because it enables us to do things (yes, the subtext is large language models/generative AI). Stepping back though, I think it&amp;rsquo;s important to be careful to think about how a technology works, what it requires of the world, and what it produces.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important not just for personal or political reasons, but that as a worker and user of technology, having a framework for thinking about whether what I&amp;rsquo;m building or using is good is valuable professionally. For example &amp;mdash; does it make sense to use an LLM for feedback over a linter? Or are there combinations that might be effective?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to use this reflection as a bit of a kick-off. I&amp;rsquo;ve been interested in critically thinking about technology for a while, but a 2023 interview with &lt;a href=&#34;https://www.politico.com/newsletters/digital-future-daily/2023/12/01/5-questions-for-meredith-whittaker-00129677&#34;&gt;Meredith Whittaker&lt;/a&gt; tipped me off to the work of &lt;a href=&#34;https://en.wikipedia.org/wiki/Ursula_Franklin&#34;&gt;[Ursula Franklin]&lt;/a&gt;. In 1989, she gave the CBC Massey Lectures &amp;mdash; which were collected into &lt;em&gt;The Real World of Technology&lt;/em&gt;. Here&amp;rsquo;s what Whittaker has to say about Franklin&amp;rsquo;s lectures:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;hellip;an incredibly clear-eyed view of the dangers of social control related to computational technology, networking, database, and the early visions of what would become the Internet that were emerging around that time.&lt;/p&gt;
&lt;p&gt;This early vision for the commercial internet, the idea that we would connect every computer to every other computer and this would create social benefit and economic benefit, looks strikingly similar to the promises being made today. If you read back to the primary documents you’re looking at incredibly familiar imaginaries: Health care is always available, education is free, all the world’s information is free. The promises haven’t changed, just the configuration of our social and economic lives. Her book was clear-eyed about some of these dangers, and very clear-eyed about how the information asymmetries that this technology would create could be used for social control.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;As I read through it, I&amp;rsquo;ll post some of my thoughts to this blog. I think it&amp;rsquo;ll be interesting to chart the progress and if my views change as I work through it. I&amp;rsquo;ll post reflections chapter by chapter, and I&amp;rsquo;m looking forward to getting started.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>suitenumerique/docs: An Open-Source Alternative to Notion</title>
      <link>https://www.kevinrkuhl.com/blog/2025/03/numerique-docs/</link>
      <pubDate>Tue, 18 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/03/numerique-docs/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://docs.numerique.gouv.fr/&#34;&gt;Docs&lt;/a&gt; (&lt;a href=&#34;https://github.com/suitenumerique/docs&#34;&gt;GitHub&lt;/a&gt;) is an open source alternative to Notion/Google Docs being built by the French and German governments (with the Netherlands being onboarded). This is &lt;strong&gt;exactly&lt;/strong&gt; the sort of work I like to see coming out of governments.&lt;/p&gt;
&lt;p&gt;Crucially, this application can be self-hosted. Given our current political landscape, &lt;a href=&#34;https://www.weforum.org/stories/2025/01/europe-digital-sovereignty/&#34;&gt;&lt;strong&gt;digital sovereignty&lt;/strong&gt;&lt;/a&gt; is going to become significantly more important. What I like about this, however, is the recognition that investment into infrastructure that can provide for tangible benefits for government can also become a &lt;strong&gt;common good&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In Canada, we have a &lt;a href=&#34;https://code.open.canada.ca/en/open-source-codes.html&#34;&gt;collection of government projects&lt;/a&gt; available as open source. Celebrating and discussing the value from these projects is something our societies should do more.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A Simple Flesch-Kincaid Calculator for Markdown</title>
      <link>https://www.kevinrkuhl.com/blog/2025/03/flesch-kincaid-calc-for-markdown/</link>
      <pubDate>Sun, 09 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/03/flesch-kincaid-calc-for-markdown/</guid>
      <description>&lt;p&gt;This is a quick post inspired by a situation that someone posted about on &lt;a href=&#34;https://www.reddit.com/r/technicalwriting/comments/1ispvq0/how_to_write_at_a_5th_grade_reading_level/&#34;&gt;r/TechnicalWriting&lt;/a&gt;. A technical writer is working as a contractor, needed to evaluate the readability of their content, but was limited in terms of the tools that they could acquire due to strict security and confidentiality requirements.&lt;/p&gt;
&lt;p&gt;At first glance, assessing how hard it is to read a text is a matter of semantics &amp;mdash; what&amp;rsquo;s going on in terms of the ideas conveyed by the words and the way the sentences work to convey meaning. But, well, in English, syntactic features (how the units of words and sentences are constructed) aren&amp;rsquo;t that bad of a proxy for estimating the overall difficulty of a text.&lt;/p&gt;
&lt;p&gt;While there are tools like &lt;a href=&#34;https://hemingwayapp.com/&#34;&gt;Hemmingway&lt;/a&gt; out there, I also believe that it&amp;rsquo;s pretty empowering to know a bit of Python so you can build your own library of scripts and tools to work with files on your own.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;flesch-kincaid-readability-tests&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Flesch-Kincaid readability tests
  &lt;a href=&#34;#flesch-kincaid-readability-tests&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&#34;https://en.wikipedia.org/wiki/Flesch%E2%80%93Kincaid_readability_tests&#34;&gt;Flesch-Kincaid&lt;/a&gt; readability tests are a pair of measures of reading difficulty that rely on two measures: average sentence length (ASL) and average syllables per word (ASW). There are two tests: the reading ease test and the grade level score. Interesting bit of history here: this emerged as a standard for the US military, and spread into industry from there. Eventually, these scores were built into Grammarly, MS Word, etc. With this proxy, we can easily implement the calculator.&lt;/p&gt;
&lt;p&gt;We can start by noting the two formulae that we&amp;rsquo;ll use. The reading ease-score is calculated with the following formula:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Score = 206.835 - (1.015 * ASL) - (84.6 * ASW)  
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this case, a higher score is more readable.&lt;/p&gt;
&lt;p&gt;The grade level score is calculated with the following formula:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Grade level = (0.39 * ASL) + (11.8 * ASW) - 15.59
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The value is roughly the school grade level that would be expected to comprehend this passage. Since this is a mechanical test, it&amp;rsquo;s actually baked into law: insurance contracts in many states are required to be written at a specific grade level.&lt;/p&gt;
&lt;p&gt;There are some key assumptions here: average word and average sentence length doesn&amp;rsquo;t necessarily indicate semantic complexity and it completely ignores elements like sentence structure. But it gives us a handy first pass. Let&amp;rsquo;s turn this into a python script that can take a raw Markdown file and return the corresponding scores.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;planning&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Planning
  &lt;a href=&#34;#planning&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A Markdown file contains simple syntax to indicate formatting. Since I also use Markdown primarily with static site generators or Obsidian, the overall structure will be:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Take a Markdown file as an argument and store the text in a string.&lt;/li&gt;
&lt;li&gt;Use regular expressions and the substitute function to strip any formatting elements.&lt;/li&gt;
&lt;li&gt;Parse the text to build lists of sentences and words in the text.&lt;/li&gt;
&lt;li&gt;Loop through the list of words and count the total number of syllables.&lt;/li&gt;
&lt;li&gt;Perform and return the calculations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When implementing this, you&amp;rsquo;ll want to think about the kinds of source documents your parsing. Both Hugo and Obsidian include front matter specified as YAML or TOML, since I don&amp;rsquo;t want the front-matter contributing to the score of the text, I&amp;rsquo;ll need to handle that front matter in addition to formatting or other elements of Markdown.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;implementation&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Implementation
  &lt;a href=&#34;#implementation&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I started with a simple method to read the file and return the text. When a user runs the script, they&amp;rsquo;ll be prompted to specify the path to the file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Python&#34; data-lang=&#34;Python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;calculate_Markdown_flesch_kincaid&lt;/span&gt;(Markdown_file_path):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Calculates Flesch-Kincaid score from a Markdown file.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; open(Markdown_file_path, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;, encoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; file:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Markdown_content &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; file&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;read()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; calculate_flesch_kincaid(Markdown_content)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;except&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;FileNotFoundError&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;File not found.&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;except&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Exception&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; e:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;An error occurred: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;e&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; __name__ &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Markdown_file &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; input(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Enter the path to your Markdown file: &amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    score, grade &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; calculate_Markdown_flesch_kincaid(Markdown_file)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; score &lt;span style=&#34;color:#f92672&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Flesch-Kincaid Score: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;score&lt;span style=&#34;color:#e6db74&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;.2f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Equivalent Grade Level: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;grade&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(score) &lt;span style=&#34;color:#75715e&#34;&gt;#print error message.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now I just need the method to handle cleaning the file and calculating the scores &amp;mdash; &lt;code&gt;calculate_flesch_kincaid&lt;/code&gt;.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;cleaning-the-file&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Cleaning the file
  &lt;a href=&#34;#cleaning-the-file&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Honestly, I dislike writing regex. When I was learning Python, the courses on regex and string handling were the ones that struggled to hold my attention the most. So, I think this is something that generative AI is genuinely useful for (while I have complex feelings about generative AI, I&amp;rsquo;m fine with this). To handle the text conversion, I specified the basic syntax of Markdown and prompted the Gemini to specify regex to identify key patterns of characters and remove them. This returned the following series of &lt;code&gt;text = re.sub(r&#39;expression&#39;, &#39;&#39;, text)&lt;/code&gt; lines to convert the file to simplified text for analysis.&lt;/p&gt;
&lt;p&gt;I wanted to use the script with Hugo and Obsidian, so I added blocks to perform a similar operation for shortcodes and YAML/TOML front matter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Remove front matter (YAML or TOML)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;(^---.*?---)|(^\+\+\+.*?\+\+\+)&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text, flags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;DOTALL)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Remove Hugo shortcodes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\{\{&amp;lt;.*?\}\}\&amp;gt;&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\{\{%.*?%\}\}&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Remove Markdown formatting&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#{1,6} &amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text)  &lt;span style=&#34;color:#75715e&#34;&gt;# Remove headings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\[.*?\]\(.*?\)&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text) &lt;span style=&#34;color:#75715e&#34;&gt;# Remove links&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\!\[.*?\]\(.*?\)&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text) &lt;span style=&#34;color:#75715e&#34;&gt;# Remove images&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;`.*?`&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text) &lt;span style=&#34;color:#75715e&#34;&gt;#remove inline code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;```.*?```&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text, flags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;DOTALL) &lt;span style=&#34;color:#75715e&#34;&gt;#remove code blocks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\*\*\*|\*\*|\*&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;,text) &lt;span style=&#34;color:#75715e&#34;&gt;#remove bold and italic&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;---&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text) &lt;span style=&#34;color:#75715e&#34;&gt;#remove horizontal rules&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;^&amp;gt;.*$&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text, flags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;MULTILINE) &lt;span style=&#34;color:#75715e&#34;&gt;#remove blockquotes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;~~.*?~~&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text) &lt;span style=&#34;color:#75715e&#34;&gt;#remove strikethrough&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[^\w\s\.\?\!\,\:\;]&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;, text) &lt;span style=&#34;color:#75715e&#34;&gt;# Remove special characters except punctuation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;sub(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\s+&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;, text)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip() &lt;span style=&#34;color:#75715e&#34;&gt;# Remove extra spaces&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A bit of an aside &amp;mdash; the initial text handling logic was pretty good, but the way it initially handled the front matter introduced a bug where it was returning null strings. Having a couple of test files as you go can pay off! Basically the test file included a lorem ipsum block and I could add in blocks for any category that needed to be handled by the cleaning.&lt;/p&gt;
&lt;p&gt;After substitution, I added a quick check to ensure that the &lt;code&gt;text&lt;/code&gt; string is not empty, stopping the script if it is and returning an error message. Following processing, we need to access both the words and sentences from the Markdown file, so I defined two lists: &lt;code&gt;words&lt;/code&gt; and &lt;code&gt;sentences&lt;/code&gt;. Sentences is the list that you get by splitting on sentence ending punctuation (&lt;code&gt;.&lt;/code&gt;, &lt;code&gt;!&lt;/code&gt;, and &lt;code&gt;?&lt;/code&gt;), and to get the words, you can use the simple regex expression &lt;code&gt;\b\w+\b&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sentences &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;split(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[.!?]+&amp;#39;&lt;/span&gt;, text)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sentences &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [s&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip() &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; s &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; sentences &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; s&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;strip()]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;words &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; re&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;findall(&lt;span style=&#34;color:#e6db74&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;\b\w+\b&amp;#39;&lt;/span&gt;, text&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;lower())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With these two lists in hand, we have everything we need to count syllables and calculate the scores.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;calculations&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Calculations
  &lt;a href=&#34;#calculations&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Accurately counting syllables in English is actually a pretty complicated task and context dependent, but we can use spelling to make a quick and reasonable estimate. From &lt;a href=&#34;https://www.grammarly.com/blog/grammar/syllables/&#34;&gt;Grammarly&lt;/a&gt;, they recommend counting the total number of vowels, then subtracting silent vowels (e.g., vowels that occur in tuples, the letter &lt;code&gt;e&lt;/code&gt; at the end of a word, etc.). This is pretty easy to set up a pair of nested loops, going through each word and each character in the word, increasing the number of vowels only if the previous character wasn&amp;rsquo;t a vowel. If the last character is an &amp;rsquo;e&amp;rsquo;, we&amp;rsquo;ll subtract one from the final count.&lt;/p&gt;
&lt;p&gt;Without any additional steps, this will slightly under estimate the number of syllables. Words ending with an &amp;ldquo;e&amp;rdquo; often don&amp;rsquo;t introduce a new syllable (e.g., &amp;lsquo;ice&amp;rsquo; is monosyllabic), but in some cases, they do (as in &amp;ldquo;ukulele&amp;rdquo;). Since the way I looped through counts vowels, I can add an if statement to check if the word ends in an &amp;rsquo;e&amp;rsquo; and decrease the count. In the &amp;ldquo;ukulele&amp;rdquo; case, the pattern is complicated. &amp;ldquo;Ale&amp;rdquo; is monosyllabic, and &amp;ldquo;simple&amp;rdquo; only has two syllables. Basically, the thought is that in longer words, with a vowel sound &lt;strong&gt;before&lt;/strong&gt; the &amp;ldquo;-le&amp;rdquo; you have an extra syllable (e.g., &amp;ldquo;allele&amp;rdquo;, &amp;ldquo;ukulele&amp;rdquo;). So we&amp;rsquo;ll check for that pattern (ends in &amp;ldquo;le&amp;rdquo;, word length is greater than 3 letters, and third last character is not a vowel).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how the script handles counting syllables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; word &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; words:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vowels &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;aeiouy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    word_syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    prev_char_was_vowel &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; char &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; word:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; char &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; vowels:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; prev_char_was_vowel:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                word_syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                prev_char_was_vowel &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                prev_char_was_vowel &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; word&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;e&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            word_syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;-=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; word&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;endswith(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;le&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; len(word) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;and&lt;/span&gt; word[&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;not&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; vowels:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            word_syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        word_syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; max(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, word_syllable_count)  &lt;span style=&#34;color:#75715e&#34;&gt;# Ensure at least 1 syllable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; word_syllable_count
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    num_sentences &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; len(sentences)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    num_words &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; len(words)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have all the values for our formulas, it&amp;rsquo;s a simple matter of implementing and returning the results:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    num_sentences &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; len(sentences)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    num_words &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; len(words)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; num_sentences &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;or&lt;/span&gt; num_words &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Cannot calculate score: Insufficient text.&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    average_sentence_length &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; num_words &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; num_sentences
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    average_syllables_per_word &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; syllable_count &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; num_words
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    flesch_kincaid_score &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;206.835&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1.015&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; average_sentence_length &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;84.6&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; average_syllables_per_word
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    grade_level &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; round(&lt;span style=&#34;color:#ae81ff&#34;&gt;0.39&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; average_sentence_length &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;11.8&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; average_syllables_per_word &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;15.59&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; flesch_kincaid_score, grade_level
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;conclusion&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Conclusion
  &lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With the pieces in place, it&amp;rsquo;s pretty simple to run: you run the script and enter the filepath for the Markdown file that you&amp;rsquo;d like to analyze. It handles my blog posts with ease and isn&amp;rsquo;t a bad heuristic to evaluate the readability of the piece of writing that you&amp;rsquo;re working on. This is a nice little addition to my drawer of helper scripts for writing projects. Not bad for a quick side project!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Meredith Whittaker on Privacy and Signal at SXSW</title>
      <link>https://www.kevinrkuhl.com/blog/2025/03/whittaker-sxsw-2025/</link>
      <pubDate>Sun, 09 Mar 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/03/whittaker-sxsw-2025/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s a lot of great insights in this &lt;a href=&#34;https://youtu.be/AyH7zoP-JOg&#34;&gt;talk with Meredith Whittaker at SXSW&lt;/a&gt;. It&amp;rsquo;s refreshing to see someone talk so straightforwardly about privacy and the incentives that shape our current notions of innovation and progress:&lt;/p&gt;
&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
      &lt;iframe allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen&#34; loading=&#34;eager&#34; referrerpolicy=&#34;strict-origin-when-cross-origin&#34; src=&#34;https://www.youtube-nocookie.com/embed/AyH7zoP-JOg?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; title=&#34;YouTube video&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;

&lt;p&gt;I particularly like how she articulates why we should care about privacy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Look, everyone&amp;rsquo;s always had something to hide&amp;hellip; you all close your bathroom door, right? You talk to your best friend in your moments of crisis. The same way you talk to your boss. Do you think out loud when you&amp;rsquo;re working through an idea. Do you tell your new friend you met at a bar the same thing you tell your oncologist? No, no. We have different relationships. We have a need for intimacy. We have a need for safe spaces to think.&lt;/p&gt;
&lt;p&gt;We have various relationships that are modulated in different ways with different people. And we have a world that is defined by various power asymmetries in which those in power can often weaponize or misuse intimate information about us, information about our preferences and our patterns and our relationships and our vulnerabilities. So there&amp;rsquo;s no world we have ever had, however many changes we&amp;rsquo;ve seen where people don&amp;rsquo;t care about privacy. However, we have made privacy into this sterile, bleached, technocratic concept that feels like we don&amp;rsquo;t have a stake in it. We don&amp;rsquo;t think about what are the things, the precious things, the democracy, freedom of thought, freedom of expression, intimacy that privacy actually guarantees as a fundamental condition.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;There&amp;rsquo;s a clarity of purpose that really makes Signal stand out from other communication or social tools:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I want to contact my friends. I have a, you know, I want to relate to other people. And that&amp;rsquo;s like, I don&amp;rsquo;t I don&amp;rsquo;t pick my friends based on whether they care about privacy. I pick my friends, whether on whether they&amp;rsquo;re cool, you know, whether I like them, whether when I hang out with them, I want to keep hanging out with them or I want to go home. Right? Like. And and that&amp;rsquo;s the world we want to live in. Not one where you have a sort of, you know, it&amp;rsquo;s technological ideology leading, you know, our relationships.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;And some good insight into the economic incentives that it takes to maintain a privacy focussed tool like Signal, as well as the kinds fo things that shape the development of tech:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;hellip;we&amp;rsquo;re looking at a landscape that&amp;rsquo;s a little bit perverse, frankly, where you have, you know, let&amp;rsquo;s give an example. Right. You have a like some defense tech startup is white labeling an AWS API and calling it innovation. And they&amp;rsquo;re getting billion dollar valuations and Signal is, you know, fundraising, even though it&amp;rsquo;s, you know, probably one of the most vital technologies used by every military in the world, right. So, you know, there is something deeply, deeply broken about the economic paradigm, about the incentives in tech.&lt;/p&gt;
&lt;p&gt;And for now, what we&amp;rsquo;re doing is everything we can to protect what Signal is. Because if Signal, you know, if we shut down Signal today, we couldn&amp;rsquo;t rebuild it, right? You can&amp;rsquo;t rebuild a network effect in a saturated market. You can&amp;rsquo;t rebuild the gold standard reputation that has been developed day by day over a decade, by people inspecting our code, looking at our cryptographic systems, looking at what we do, improving it. There&amp;rsquo;s an ecosystem built around it that you can&amp;rsquo;t just snap your fingers and and do. And, you know, that&amp;rsquo;s one of one of the lessons around communication networks, right. The network effect is really powerful.&lt;/p&gt;&lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title>What I Work With: Tools for Technical Writing in 2025</title>
      <link>https://www.kevinrkuhl.com/blog/2025/02/tool_chain_2025/</link>
      <pubDate>Fri, 21 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/02/tool_chain_2025/</guid>
      <description>&lt;p&gt;I feel like technical writers are kind of a difficult creature to understand. Documentation is one of those words that means so many different things to so many different people, but primarily, we build written resources that explain how to use technical products. In my career, the technical products have been software. The audience for my writing has been admins, developers, or non-technical end-users. There are a number of ways to do this, ranging in appearance and complexity. Sometimes I work with documents in a way that looks like code or fiddle with template files for websites. Other times I work through a user interface designed for publishing to multiple endpoints. So I think it typically makes sense for technical writers to be flexible, understanding enough to work with different kinds of tools.&lt;/p&gt;
&lt;p&gt;After all, we&amp;rsquo;re kind of generalists. We need to be able to understand how technical products work. And when you produce documentation, you should probably be pretty good at using documentation as well.&lt;/p&gt;
&lt;p&gt;So, here&amp;rsquo;s a snapshot of my current setup. Maybe I&amp;rsquo;ll revisit this in five years! A quick caveat: if you prefer more user-friendly paid services, this DIY toolchain might not be your cup of tea!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;hardware&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Hardware
  &lt;a href=&#34;#hardware&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I use a &lt;a href=&#34;https://frame.work&#34;&gt;Framework 13&lt;/a&gt;, equipped with an AMD Ryzen 7 CPU and Windows 11. It&amp;rsquo;s a pretty cool little laptop, but I wouldn&amp;rsquo;t recommend it for everyone. I&amp;rsquo;ll go into the pros and cons below. I&amp;rsquo;ve been debating dual-booting with Linux, but for app compatibility and ease of use reasons, I&amp;rsquo;ve stuck with Windows. When I need to use a Linux development environment, WSL2 is there. But more about that in my software section.&lt;/p&gt;
&lt;p&gt;Over the years, I&amp;rsquo;ve used various laptops: MacBooks, Asus netbooks, and more. I enjoy exploring different operating systems and hardware, configuring tools to meet my needs. I&amp;rsquo;m someone who likes to fiddle with hardware and switch between environments. So what works for me might not work for you!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;pros&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Pros
  &lt;a href=&#34;#pros&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I love the Framework&amp;rsquo;s modularity with swappable expansion cards (HDMI on the left instead of the right? No problem!), privacy sliders for the microphone and webcam, and Linux support. I&amp;rsquo;m debating returning to desktop Linux depending on how Windows evolves. The matte screen is a bonus for productivity, reducing glare and has an excellent resolution. It is honestly pretty comfortable for blogging with Hugo running in server mode (for my editing flow) or comparing diffs in VS Code.&lt;/p&gt;
&lt;p&gt;Battery life and CPU are perfect for what I need. It&amp;rsquo;s not spooky-great like Apple&amp;rsquo;s silicon, but the AMD Framework meets my needs for a day on the go.&lt;/p&gt;
&lt;p&gt;What really draws me to it is that every component on the laptop can be upgraded or swapped out for repairs. If I find that media processing or development tasks require more memory than I have, I can order compatible sticks and do the upgrade myself. If the screen is damaged? That can be replaced.&lt;/p&gt;
&lt;p&gt;While the ability to repair is dependent on the continued operation of the company, this is so radically different from every other laptop manufacturer that I think it&amp;rsquo;s worth supporting. This has been successful enough that Intel seems to be &lt;a href=&#34;https://www.tomshardware.com/tech-industry/intel-proposes-easily-repairable-and-sustainable-modular-pc-design-for-laptops-and-mini-pcs&#34;&gt;jumping on the bandwagon&lt;/a&gt;!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;cons&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Cons
  &lt;a href=&#34;#cons&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The modular IO ports can be finicky with the AMD mainboard. Where I put the USB-C and HDMI modules matter with the AMD mainboard. It doesn&amp;rsquo;t break my experience, but you do have to think about things.&lt;/p&gt;
&lt;p&gt;The keyboard and trackpad are also misses for me. The keyboard is functional, but it&amp;rsquo;s not as good as the Macbook style scissor switches. There&amp;rsquo;s noticeable flex when typing. I also don&amp;rsquo;t love that &lt;code&gt;f12&lt;/code&gt; is mapped to launch the Framework marketplace by default (cat stomps can suddenly open a browser window). The trackpad isn&amp;rsquo;t on the same level as Macbook&amp;rsquo;s for gestures. But honestly, I use mine with a mouse more than the trackpad.&lt;/p&gt;
&lt;p&gt;The build quality is a little middling - It&amp;rsquo;s not bad, but it&amp;rsquo;s not as sturdy or well put together as some of the alternatives in the price range. The hinges are a bit too easy to open, and bouncy train rides can be an issue.&lt;/p&gt;
&lt;p&gt;I have noticed that in my current workflows, the 16GB of ram I configured it with isn&amp;rsquo;t quite enough. Having multiple apps open (Discord, Slack, VS Code, Front&amp;hellip; etc.), and then trying to work with WSL2 gets a little dicey. Thankfully I can upgrade! But for building this site or other lightweight platforms, this machine works wonderfully.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;peripherals&#34; --&gt;

&lt;h3 class=&#34;header-anchor-wrapper&#34;&gt;Peripherals
  &lt;a href=&#34;#peripherals&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A couple of other essential things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An external monitor, I have a 32&amp;quot; 1440p display&lt;/li&gt;
&lt;li&gt;A mechanical keyboard (I alternate between a Keychron K6 and a Keychron C3 Pro)&lt;/li&gt;
&lt;li&gt;Logitech MX Anywhere mouse (for portability)&lt;/li&gt;
&lt;li&gt;Steelseries over-ear headphones for long focus sessions or calls&lt;/li&gt;
&lt;li&gt;A USB-C to HDMI, USB-C, and USB adapter&lt;/li&gt;
&lt;li&gt;Leuchtturm 1917 notebook&lt;/li&gt;
&lt;li&gt;Lamy Al Star loaded with black ink&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;software&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Software
  &lt;a href=&#34;#software&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A software technical writer is responsible for producing written content to explain how software works. This is usually in the form of a help center or docs website. In other branches of technical writing, you may produce print or PDF manuals. I work with static site generators (SSGs), content management systems (CMSes), and learning management systems (LMSes) to produce and host content to explain how software works (including videos and screenshots). I think the choice of docs system really depends on how you envision your team functioning and who contributes to your documentation.&lt;/p&gt;
&lt;p&gt;There are strong reasons to prefer docs-as-code as a methodology (using Git, SSGs, workflow automations, and tests) if you have a community of contributors who are comfortable with Git and markup languages. There are strong reasons to prefer a CMS if you have a community of users who are more comfortable working in what-you-see-is-what-you-get (WYSIWYG) type environments. While specialization and tool knowledge is valuable, it can pay to be a bit of a generalist.&lt;/p&gt;
&lt;p&gt;For this site, I rely on Hugo, which is a static site generator, and a common tool for docs-as-code projects. Version control, revisions, and experimentation are all easy to handle using Git and Github. I write inside of VS Code, making use of extensions to handle spellcheck and syntax highlighting. It&amp;rsquo;s also easy to extend and support your docs-as-code projects with helper scripts and functions to carry out automations.&lt;/p&gt;
&lt;p&gt;I run Vale, a linter (tool to check each blog post against a set of style rules), a python script to check links, and python script to move images to a folder I back up to Google Drive (saving me from backing up image files in Github). In my contract work, I can use this setup to build and test templates and configurations for CMSes and LMSes using Docker containers. This involves working a bit with Windows Subsystem for Linux (WSL), which has been a great way to have a flexible and customizable development environment in addition to the more stable Windows environment. Running WSL, Windows, and various productivity apps is where I feel the ram pinch a bit, but taking a bit of care to ensure I&amp;rsquo;ve properly configured the Docker and WSL has made things workable (along with minimizing the number of other apps I have open while I&amp;rsquo;m focussed on these tasks).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a summary of ones that I find particularly useful with an emphasis on free or open source options:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Category&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Tool(s)&lt;/th&gt;
          &lt;th style=&#34;text-align: left&#34;&gt;Notes&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Operating System&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Windows 11, WSL2&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;I chose this for its battery life and software compatibility. WSL2 allows access to a Linux environment if needed (e.g., with Docker)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Productivity &amp;amp; Utils&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;PowerToys (FancyZones, PowerRename, etc.)&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;This is essential for a Windows 11 user. Various handy utilities, worth it alone for bulk renaming of files.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Development&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;VS Code, Git, GitHub Desktop, Hugo, Pa11y, Vale, PowerShell, Python&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;VS Code is my primary code editor; Git and GitHub manage version control; Hugo is used for static site generation; Pa11y and Vale automate accessibility and style checks; PowerShell is the primary terminal.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Screenshots&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;ShareX&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;A powerful and configurable screenshot tool.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Video&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OBS Studio, Kdenlive&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;OBS Studio is used for screen recording and streaming; Kdenlive is used for video editing.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Audio&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Audacity&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Used for audio recording and editing.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Command Line&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Chocolatey, ImageMagick, Pandoc, etc.&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Chocolatey is a package manager; ImageMagick and Pandoc are used for image and document manipulation, respectively.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Browser&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Chrome, Firefox, Edge&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Multiple browsers are used for different workflows and testing.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;&lt;strong&gt;Note-Taking&lt;/strong&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Obsidian&lt;/td&gt;
          &lt;td style=&#34;text-align: left&#34;&gt;Used for its linking, search, and knowledge graph features, useful for drafting and managing content in various formats (Markdown easily transfers to Hugo projects, Google Docs).  Joplin or Logseq is an alternative.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I am purposefully leaving off an AI tool. There is a range of these available, and most of them will work well for general queries and editing, within reason. All of the major providers support adding materials and files as context. The important thing is that they aren&amp;rsquo;t essential for my kind of workflow and many of them are functionally interchangeable. If you are working as a contractor, it&amp;rsquo;s also important to meet requirements from the company you are contracting with, so keep in mind confidentiality and security.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;final-thoughts&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Final thoughts
  &lt;a href=&#34;#final-thoughts&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I think that this is a pretty powerful web-publishing tool set and you can work through this with fairly minimal licensing fees &amp;mdash; Obsidian requires a license if you are using it for commercial purposes, but everything else (aside from Windows), is freely available. I also feel that I could adapt this toolchain to Desktop Linux or MacOS with fairly minimal changes, which means it&amp;rsquo;d be flexible enough for any company I&amp;rsquo;d be going to work with. The repairability of my laptop also means that I can keep it going in the event of a hardware malfunction, but so far the Framework has been stable and powerful.&lt;/p&gt;
&lt;p&gt;It will be interesting to see how I feel about the Framework in five years, and whether I&amp;rsquo;ve done a modular upgrade. My last personal laptop was a Macbook Pro that I used for more than a decade. I&amp;rsquo;m feeling confident that this tool chain will work well into the future.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Replacing Facebook: Fb to Obsidian</title>
      <link>https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/</link>
      <pubDate>Sat, 15 Feb 2025 00:00:00 +0000</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/</guid>
      <description>&lt;p&gt;One of my goals for 2025 is to remove my dependency on social media. I previously discussed how I was staying on top of local news and events without relying on a platform like Facebook. As a Canadian, Facebook stopped being an effective news platform after Meta decided to remove any linked content to Canadian news providers following the &lt;a href=&#34;https://crtc.gc.ca/eng/industr/info.htm&#34;&gt;Online News Act (Bill C-18)&lt;/a&gt;. This left Facebook&amp;rsquo;s function in my life as a way to stay connected to friends and contacts.&lt;/p&gt;
&lt;p&gt;As a social network, Facebook is effectively a record of the people I&amp;rsquo;ve connected with over time. It also supports two primary ways of communicating with people in my social network. The first is one-to-many: I can make a post that other people can read, if they encounter the post in their feed. They can then comment on the post, and it can begin to foster a conversation. The fundamental problem is that one-to-many communication in this mode is entirely dependent on the algorithm&amp;rsquo;s feed. The other main mode of communication is one-to-one. With the messenger app, you can reach other people directly and exchange messages.&lt;/p&gt;
&lt;p&gt;And yes, I know that Facebook has some other things going for it &amp;mdash; games, marketplace, videos, community groups etc. Those are secondary features. Social connections and communication features are the &lt;strong&gt;primary draws&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If that&amp;rsquo;s what Facebook is supposed to do, what&amp;rsquo;s keeping me from using it?&lt;/p&gt;
&lt;p&gt;As a recipient of one-to-many communication, it just doesn&amp;rsquo;t work. At my last count, I see at least six posts from things I do not want to see for every one post from a friend. This is too much waste to wade through and then it&amp;rsquo;s for things which are algorithmically suggested. There&amp;rsquo;s no guarantee that what appears will be what I want to see. And these odds make me less willing to put out updates for people in my life who I want to see things that are going on with me.&lt;/p&gt;
&lt;p&gt;So, I got to thinking about what I need, and how to replace Facebook in my life. This blog post details the process, and what I&amp;rsquo;ve done to regain a bit of control over the information.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;replacing-feeds&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Replacing feeds
  &lt;a href=&#34;#replacing-feeds&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are two ways out of feeds that I can see: for smaller clusters of people that I want to talk with or share general life updates, I use group chats. It&amp;rsquo;s free from the clutter and competition on Facebook, and facilitates just as much group communication as the post. Chat rooms and forums allow you to focus on topics or commonalities, and so I&amp;rsquo;m more engaged in Discord and Slack servers. It turns out that social media became too big and messy, and so we&amp;rsquo;ve retreated to communities where we can control the intrusive content. I think this is a win, overall.&lt;/p&gt;
&lt;p&gt;One other option is email newsletters. While they take a bit of work, letting family and friends know where you are at in life in a less intrusive way can perform some of the work that Facebook posts do.&lt;/p&gt;
&lt;p&gt;And one last option is this blog! It&amp;rsquo;s a place on the internet where people from my past can find me. And I think I&amp;rsquo;m going to aim for weekly link roundups. I&amp;rsquo;m loosely inspired by other link blogging practices, and it will fit nicely with my use of RSS readers. By posting my thoughts, it allows for effective one-to-many conversation to a general audience.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;an-alternative-for-keeping-connections&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;An alternative for keeping connections
  &lt;a href=&#34;#an-alternative-for-keeping-connections&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve had a Facebook account for 20 years, which makes it an interesting snapshot of my life. It spans from high school to grad school to where I&amp;rsquo;m at now. I really do appreciate that in one place, I can connect to so many people. But for a lot of the people in my friends list, we don&amp;rsquo;t really communicate much directly&lt;/p&gt;
&lt;p&gt;I think there&amp;rsquo;s two pieces to the role that Facebook plays here: The first is that Facebook becomes a means of tracking my social history. It&amp;rsquo;s an archive of who I&amp;rsquo;ve known and when (and a way of seeing where they&amp;rsquo;re at now). THe other piece is that it becomes a functional address book. I don&amp;rsquo;t have to worry about updating it, so long as my friends keep their accounts active and running.&lt;/p&gt;
&lt;p&gt;But what&amp;rsquo;s great is that both of these things are pretty easy to solve. For people I am actively socially connected to, I can make sure that I have some stable ways of communicating with them, and have written that down somewhere. If people want to find me, I have this website. And documenting who&amp;rsquo;s been a part of my life? Well, I work making &lt;strong&gt;documentation&lt;/strong&gt; and like building automations to help build and keep it up to date.&lt;/p&gt;
&lt;p&gt;This sounds like a project!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;getting-your-data-from-facebook&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Getting your data from Facebook
  &lt;a href=&#34;#getting-your-data-from-facebook&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;One of the first things to note is that at any point in time, you can make a backup of the data for your Facebook account. Since I have 20 years of data, this is actually kind of large and cumbersome to deal with. To get a download, there are &lt;a href=&#34;https://www.facebook.com/help/212802592074644&#34;&gt;several steps&lt;/a&gt; to go through, and you&amp;rsquo;ll download what is likely a sizable zip containing all your photos and lots of advertising data.&lt;/p&gt;
&lt;p&gt;For this project I just needed a small part of the data - the information about my contacts. You can request this in HTML or JSON, but for ease of working with the data, I went with JSON. If you are looking to explore and browse through your copy of the data, the HTML download is a good option.&lt;/p&gt;
&lt;p&gt;The data in the contacts section is pretty minimal, with the following structure:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;{
    &amp;#34;friends_v2&amp;#34;: [
      {
        &amp;#34;name&amp;#34;: &amp;#34;A Person&amp;#34;,
        &amp;#34;timestamp&amp;#34;: 1726777876
      }
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so it&amp;rsquo;s pretty sparse. The date is a unix timestamp, which will be easy enough to handle later. But at least it&amp;rsquo;s a start for what I&amp;rsquo;m trying to recapture!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you&amp;rsquo;re not into Python, you can easily build the address book part of this using spreadsheets, the HTML export, and contacts apps. Highlight all the text from the contacts page in your HTML export, then copy and paste into Excel or Google sheets. You can use a formula and the auto-complete function to bring the dates into the same row, and VLOOKUP to merge this with your contacts export.&lt;/p&gt;&lt;/blockquote&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;planning-the-project&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Planning the project
  &lt;a href=&#34;#planning-the-project&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Obsidian has rapidly become one of my favorite tools for organizing notes for self-directed learning, household projects, or hobbies. The thought is it would be pretty nice to use Obsidian as a way of handling information about my friends as well. So, after looking at the data, I started to think about how I&amp;rsquo;d want this information to look in Obsidian.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want a page per Facebook contact, since the goal isn&amp;rsquo;t to recreate Facebook profile pages. So I need to filter the list of Facebook contacts to people that I want to be sure to create contact details for in an address book structure. The people that are more historical contacts will go to History pages. History pages would be groups of people with any applicable contact info that I had available.&lt;/p&gt;
&lt;p&gt;With a plan for what the output of the script (or scripts) would be, this meant that I would need to pass through the list of contacts at least once, and add the following details to each contact: whether they&amp;rsquo;d be in the address book or social history, and what kinds of categories they would fall under. For categories, I&amp;rsquo;d aim for at least three per contact &amp;mdash; where, when, and what kind of context I added them in. So for example, someone from highschool cross-country would get &amp;ldquo;london, highschool, cross-country&amp;rdquo; as the list of tags. This should give a fairly interesting structure to the social history pages.&lt;/p&gt;
&lt;p&gt;I also realized that I have a wealth of contact information already available to me. As an Android user, I made regular use of my phone contacts. Ultimately, I&amp;rsquo;d love to be able to sync the data associated with my Obsidian addressbook with my phone contact list as needed. This could be a stretch goal - but the primary thing would be to merge phone contacts with Facebook friends, and output the data to useful notes in my Obsidian Vault.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;carrying-this-out&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Carrying this out
  &lt;a href=&#34;#carrying-this-out&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Originally, I was hoping it would make sense to do this as a single script. At the end of the day though, a more modular approach to this made sense. With over 500 Facebook friends, categorization would be something that I would want to pick up and come back to over a period of multiple days, so a separate command line prompt that I could terminate and come back to seemed like it&amp;rsquo;d be fine for categorization.&lt;/p&gt;
&lt;p&gt;So I settled on four separate scripts: one to merge the contacts and save that to an intermediary JSON file, a simple command line script to prompt me to categorize and tag connections, and finally, two scripts to generate output from the intermediate JSON file.&lt;/p&gt;
&lt;p&gt;Overall, the coding was pretty simple and straightforward: the first script &lt;code&gt;merge_contacts.py&lt;/code&gt; takes your Facebook contacts JSON export, creates a dataframe, converts the CSV export of my Android contacts to a data frame, merges them, then dumps the resulting dataframe to JSON. The matching could be improved, but it does what it needs to do. The second script, &lt;code&gt;review_contacts.py&lt;/code&gt; goes through the JSON file, and prompts the user to categorize each contact, providing relevant information. I set it up so the user could save and exit the script at any time using &lt;code&gt;ctrl-C&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What was a bit more fun was coming up with templates for each doc. Since Obsidian allows you to enter properties for each contact, I decided to write every key from the JSON file to properties of an entry in the address book. If I wanted to, I could use templating features to update the body based on the properties, but for a test MVP, I decided to keep things simple with the Obsidian templates, and created a series of markdown tables that would correspond to groupings of contact information. For social history articles - I decided I simply wanted a list of connections that fell under that category, with key contact information (email, city, etc.) following their name if available. Ideally, the core address book would be significantly smaller.&lt;/p&gt;
&lt;p&gt;Writing the documents to files was pretty simple. Come up with two template docs in markdown, and identify which pieces of information needed to be in both, then convert the markdown templates to f-strings, writing in variables from the data as needed.  From there, it was pretty quick to write two scripts that went through the JSON entries. The first script, &lt;code&gt;create_address_book.py&lt;/code&gt;, would generate address book entries. Any contact flagged as needing to be added to the Address Book would have a unique file created in a directory. Then it would dump key/value pairs from the JSON into YAML frontmatter for the Obsidian note. This helps with updating and merging data in the future, and can be used with Data View in Obsidian to for reporting and queries. Finally, it builds a collection of tables to provide more natural viewing for the note.&lt;/p&gt;
&lt;p&gt;For the history pages, &lt;code&gt;create_soc_history.py&lt;/code&gt; would load the JSON, and check to see if there were any contacts that hadn&amp;rsquo;t been processed by the review script. This prompts a user warning, encouraging them to finish the review step before proceeding with this dataset. It then generates a set of all tags entered during the review, and loops through the list of labels. For each label, it prompts the user to enter a description that would be used in the note. Finally, this script generates a file using a template, and appends contact details to the file if the contact is tagged with this label.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-test-run&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The test run
  &lt;a href=&#34;#the-test-run&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Using the header of the Android CSV file and the structure of the Facebook JSON, I created a test dataset that would build five contacts into a single dataset, so that I could see how data would carry through from both the Facebook side and the Android side.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/fb-obsidian-merge-test.png&#34;
    alt=&#34;Running the merge with test data, generating the desired five contacts based on two test sources&#34; width=&#34;75%&#34;&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/fb-obsidian-review-test.png&#34;
    alt=&#34;Reviewing the test data, adding tags.&#34; width=&#34;55%&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;I was pretty pleased with how this turned out, easily generating notes that listed contacts by label, and loading connection details into the address book. Next up is to spend some time thinking of edge-cases and ways to handle them: special characters are the number one thing I&amp;rsquo;m thinking about, but also improved matching.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/fb-obsidian-create-test.png&#34;
    alt=&#34;Running both create scripts in my terminal, including prompts to describe tags.&#34; width=&#34;75%&#34;&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/fb-obsidian-output-notes.png&#34;
    alt=&#34;Notes created for selected contacts and groups.&#34; width=&#34;30%&#34;&gt;
&lt;/figure&gt;

&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/fb-obsidian-output-properties.png&#34;
    alt=&#34;Obsidian view of the yaml properties for each contact.&#34; width=&#34;30%&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;Tagging and categorizing my Facebook friends list will be significantly more involved run, and there are some usability things that I&amp;rsquo;m going to improve before I go too much further, but I&amp;rsquo;m pretty happy with the results.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;whats-next&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What&amp;rsquo;s next
  &lt;a href=&#34;#whats-next&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s a few things to clean up: improving incrementing and spacing in the &lt;code&gt;review_contacts.py&lt;/code&gt; script, writing tests, and actually going through the process with my own Facebook data (I did test the merge already, and have have more than 600 contacts to review). The idea got into my head too to add LinkedIn data, but I really didn&amp;rsquo;t want to review what was likely more than 1000 connections. Maybe if I continue to push ahead on this a bit. But I do want to get back to &lt;a href=&#34;https://www.kevinrkuhl.com/blog/house-rag/&#34;&gt;other side projects&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2025/02/replacing-facebook/fb-obsidian-merge-all.png&#34;
    alt=&#34;Running the merge with my actual data resulted in 615 contacts to review and tag.&#34; width=&#34;75%&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;At this stage, I&amp;rsquo;m happy with the resulting notes files. I&amp;rsquo;ll publish the project following a bit of the tidying work, in case your curious or want to do the same thing.&lt;/p&gt;
&lt;p&gt;Things have been kind of crazy in the world lately &amp;mdash; but working on this side project has felt good, like I&amp;rsquo;m bringing something back into my control, and it&amp;rsquo;s encouraging me to be more engaged with the people who matter to me.&lt;/p&gt;
&lt;p&gt;Hopefully this inspires you to find ways to take more active control of your life too!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How I Follow Local News and Events</title>
      <link>https://www.kevinrkuhl.com/blog/2025/01/local-news/</link>
      <pubDate>Sat, 25 Jan 2025 12:00:00 -0400</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2025/01/local-news/</guid>
      <description>&lt;p&gt;One of the main reasons people use social media is to stay connected to the flow of information within their community.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been intentionally disentangling my digital life from Meta over the past several years. I&amp;rsquo;ve essentially stopped actively using Facebook and only use certain communication services because they&amp;rsquo;re preferred for group chats. Finishing this process has become more urgent for me given their recent &lt;a href=&#34;https://www.404media.co/its-total-chaos-internally-at-meta-right-now-employees-protest-zuckerbergs-anti-lgbtq-changes/&#34;&gt;overtly anti-LGBT policies&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This shift has made finding and keeping up with local news and events more of a &lt;strong&gt;choose-your-own-adventure&lt;/strong&gt;.  Here&amp;rsquo;s the solution I&amp;rsquo;ve found that works for me.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-basics&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The basics
  &lt;a href=&#34;#the-basics&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;For news, I need a tool that presents stories chronologically. I do not want a recommendation algorithm. I want to preview titles and selectively read articles.  Ideally, I can also save stories for later or potentially re-blog them. Publication feeds like &lt;a href=&#34;https://en.wikipedia.org/wiki/Atom_(web_format)&#34;&gt;Atom&lt;/a&gt; and &lt;a href=&#34;https://en.wikipedia.org/wiki/RSS&#34;&gt;RSS&lt;/a&gt; are perfect for this!&lt;/p&gt;
&lt;p&gt;Unfortunately, I stopped using RSS readers when Google Reader shut down. Facebook and Twitter became my de facto replacements, but in hindsight, this resulted in a worse internet. So, I&amp;rsquo;ve been wanting to reclaim how I interact with online content.&lt;/p&gt;
&lt;p&gt;After considering my needs and doing some research, I landed on &lt;a href=&#34;https://www.inoreader.com/&#34;&gt;Inoreader&lt;/a&gt;. The free tier meets most of my needs, but I&amp;rsquo;m debating moving to paid.  Despite some limitations (e.g., the number of feeds, inability to adjust the feed check frequency), I appreciate its rule creation, filtering, and global search capabilities. These features prevent me from becoming overwhelmed by too many unchecked feeds.&lt;/p&gt;
&lt;p&gt;Adding a feed is easy.  I locate the RSS icon (an orange square with white curved lines) on the website whenever possible.  If not, I open Inoreader, click the subscribe button, and search for the website&amp;rsquo;s main URL. Inoreader is usually good at finding the feed information.&lt;/p&gt;
&lt;p&gt;Events are trickier. My primary interest is what&amp;rsquo;s happening in my local communities.  Electronic calendars are great for this, and many organizations offer iCalendar (.ics) feeds.  For cross-device and multi-user compatibility, I use Google Calendar. It&amp;rsquo;s not the most innovative choice, but it works well for me given the range of devices I use.&lt;/p&gt;
&lt;p&gt;Adding another calendar feed to Google Calendar is simple. I find the iCal feed URL (usually labeled &amp;ldquo;iCal&amp;rdquo; or &amp;ldquo;Subscribe&amp;rdquo;), copy it, and then go to my Google Calendar.  Under &amp;ldquo;Other calendars,&amp;rdquo; I can add the new feed. I will color coordinate events calendars, and can filter them in and out of my calendar when I&amp;rsquo;m curious about what&amp;rsquo;s going on.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;local-news&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Local news
  &lt;a href=&#34;#local-news&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Here&amp;rsquo;s the local news I follow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://www.communityedition.ca/&#34;&gt;The Community Edition&lt;/a&gt; (&lt;a href=&#34;https://www.communityedition.ca/feed/syndication&#34;&gt;Feed&lt;/a&gt;): An alt-weekly newspaper run by Wilfrid Laurier University Student Publications, covering local events, culture, and providing a human perspective on the Waterloo Region.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.cbc.ca/news/canada/kitchener-waterloo&#34;&gt;CBC News Kitchener Waterloo&lt;/a&gt; (&lt;a href=&#34;https://rss.cbc.ca/lineup/canada-kitchenerwaterloo.xml&#34;&gt;Feed&lt;/a&gt;): CBC is Canada&amp;rsquo;s national broadcaster, a valuable part of our cultural and information ecosystem. This feed is filtered for regional news.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kitchener.ctvnews.ca&#34;&gt;CTV News Kitchener&lt;/a&gt; (&lt;a href=&#34;https://kitchener.ctvnews.ca/rss/ctv-news-kitchener-1.822359&#34;&gt;Feed&lt;/a&gt;):  A local news channel owned by Bell Media, providing regular regional news updates.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Beyond traditional media, I follow these newsletters and new media options:&lt;/p&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;&lt;a href=&#34;https://tlwr.substack.com/&#34;&gt;TL;WR&lt;/a&gt; (&lt;a href=&#34;https://tlwr.substack.com/feed&#34;&gt;Feed&lt;/a&gt;): Alex Kinsella&amp;rsquo;s newsletter highlighting local events, music, and food. I&amp;rsquo;ve included it under news since it highlights the upcoming week, and doesn&amp;rsquo;t function as an event calendar.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://citified.substack.com/&#34;&gt;Citified&lt;/a&gt; (&lt;a href=&#34;https://citified.substack.com/feed&#34;&gt;Feed&lt;/a&gt;): Melissa Bowman&amp;rsquo;s newsletter focusing on municipal politics and civic engagement in Kitchener-Waterloo. If you want to learn about how municipal politics works in KW and what&amp;rsquo;s going on at the municipal level, this is the feed to follow.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Finally, for breaking news and local discussions, I monitor these subreddit. Using an RSS reader is less distracting than the reddit interface, and I typically mark posts as read in bulk:&lt;/p&gt;
&lt;ol start=&#34;6&#34;&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/kitchener/&#34;&gt;Kitchener Subreddit&lt;/a&gt; (&lt;a href=&#34;https://www.reddit.com/r/kitchener/.rss&#34;&gt;Feed&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/waterloo/&#34;&gt;Waterloo Subreddit&lt;/a&gt; (&lt;a href=&#34;https://www.reddit.com/r/waterloo/.rss&#34;&gt;Feed&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These local news websites lack RSS/Atom feeds, but I&amp;rsquo;d add them to Inoreader with a paid subscription:&lt;/p&gt;
&lt;ol start=&#34;8&#34;&gt;
&lt;li&gt;&lt;a href=&#34;https://kitchener.citynews.ca/&#34;&gt;City News Kitchener&lt;/a&gt;: Rogers Media operates the City News brand, however they do not have an RSS feed.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kitchener.citynews.ca/audio/&#34;&gt;AM570&lt;/a&gt;: This is local news radio, also part of Rogers Media&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.therecord.com/&#34;&gt;The Record&lt;/a&gt;: The Waterloo Region record is owned and operated by Torstar/Metroland. They offer email subscriptions, but their RSS feed has been defunct since June 2023.&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;calendars-and-events&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Calendars and events
  &lt;a href=&#34;#calendars-and-events&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;My event calendar subscriptions reflect my involvement in the tech and local queer communities:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://watcamp.com/&#34;&gt;WatCamp&lt;/a&gt;: This is a feed of tech sector events in the Kitchener Waterloo region.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ourspectrum.org&#34;&gt;Spectrum&lt;/a&gt;:  The Rainbow Community Calendar from Spectrum, a queer community organization. (To get a feed, click the calendar&amp;rsquo;s menu icon, go to preferences, and select the iCalendar feed.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://calendar.wpl.ca/events&#34;&gt;Waterloo Public Library&lt;/a&gt;: Libraries are a wonderful community resource, and have interesting programs and special events. (Their feed service includes filters set on the calendar.)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.princesscinema.com&#34;&gt;The Princess Cinema&lt;/a&gt; (&lt;a href=&#34;https://www.princesscinemas.com/princess.ics&#34;&gt;ICS Feed&lt;/a&gt;) A local indie cinema in Waterloo.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I also regularly check these calendars (even without subscription options):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://kpl.events.mylibrary.digital/&#34;&gt;Kitchener Public Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://apollocinema.ca/&#34;&gt;The Apollo Cinema&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kwconcerts.ca/&#34;&gt;KW Concerts&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;final-thoughts&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Final thoughts
  &lt;a href=&#34;#final-thoughts&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This framework effectively connects me with local news and events. Importantly, it&amp;rsquo;s not algorithm-driven.  I see published items chronologically and choose what to engage with. This is a more proactive and empowering approach compared to the algorithmic whims of social media. It requires more effort, but the control and awareness of my information intake are worthwhile.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;addendum&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Addendum
  &lt;a href=&#34;#addendum&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;While writing this, I realized others have curated similar resources!  If you have other feeds to suggest, let me know, and I&amp;rsquo;ll link to them:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://feeds.off-topic.kwlug.org&#34;&gt;feeds.off-topic.kwlug.org&lt;/a&gt; The local Linux users group has a comprehensive list of calendars and news feeds. I will probably update my list based on this.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wrdashboard.ca/&#34;&gt;WR Dashboard&lt;/a&gt; An aggregator project that lists multiple RSS feeds.&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Project Hinzelmann: Building a Household RAG App</title>
      <link>https://www.kevinrkuhl.com/blog/2024/12/house-rag/</link>
      <pubDate>Sun, 01 Dec 2024 12:00:00 -0400</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2024/12/house-rag/</guid>
      <description>&lt;p&gt;I’ve been thinking about how generative AI impacts the ways people find, retrieve, and access information. As a technical writer, my job involves helping build systems for these purposes. This lead me to consider the ways I could build skills in this area. Inspired by Luke Hsiao’s &lt;a href=&#34;https://luke.hsiao.dev/blog/housing-documentation/&#34;&gt;house documentation project&lt;/a&gt;, I’ve been wanting to implement a document system for managing information about my house.&lt;/p&gt;
&lt;p&gt;The thought is that bringing together these two projects, I’ll be able to create a small household-generative AI application. I’ll share my learnings and challenges along the way. And, since projects are a little more fun with cheeky names, I’m going to call this project &lt;em&gt;Hinzelmann&lt;/em&gt; — after the figure from &lt;a href=&#34;https://en.wikipedia.org/wiki/Hinzelmann&#34;&gt;German folklore&lt;/a&gt;. Why is it cheeky? Well the Hinzelmann was a helpful figure, they were also a bit of a trickster and troublemaker.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-use-this-as-a-case-to-explore-generative-ai&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why use this as a case to explore generative AI?
  &lt;a href=&#34;#why-use-this-as-a-case-to-explore-generative-ai&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Generative AI is a &lt;strong&gt;powerful UX&lt;/strong&gt; for information retrieval. Think about how we go about finding information for a second. Let’s start with a relatively simple task: writing the regex to identify a credit card number in a text response. Regex is a great way to find patterns in strings of text, but the syntax can be difficult to parse and sometimes, for common tasks, it’s easiest to look up a pattern that already works for your case.&lt;/p&gt;
&lt;p&gt;Let’s do a traditional websearch:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2024/12/house-rag/regex_google.png&#34;
    alt=&#34;A traditional websearch&#34; width=&#34;60%&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;And we’ll go into stackoverflow and read a little ways down. And we have a (relatively) trustworthy answer:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2024/12/house-rag/regex_stack-overflow.png&#34;
    alt=&#34;A stack overflow response&#34; width=&#34;60%&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;It takes effort on the part of the user to assess the linked source, parse the source information, and assess how trustworthy the information is. This is fairly cognitively complex - but it’s research skills!&lt;/p&gt;
&lt;p&gt;While using a copilot:&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://www.kevinrkuhl.com/blog/2024/12/house-rag/regex_copilot.png&#34;
    alt=&#34;A copilot response in VS Code, with the answer displayed immediately following the query, ready to paste in.&#34; width=&#34;60%&#34;&gt;
&lt;/figure&gt;

&lt;p&gt;You are provided an authoritative answer without additional context cluttering the results.&lt;/p&gt;
&lt;p&gt;Most users will understandably prefer this streamlined experience to the traditional search experience. It is &lt;strong&gt;fewer&lt;/strong&gt; clicks, and much more &lt;strong&gt;focused&lt;/strong&gt; as an experience. But there are some concerns you should have about this: LLMs are not search. They can behave like search — returning the most proabable sequence of responses to queries, but they have a key limitation. An LLM is trained on publicly available data up until a certain point in time. They don’t have &lt;strong&gt;current&lt;/strong&gt; text patterns as part of the model.&lt;/p&gt;
&lt;p&gt;LLMs are a poor search tool when you’re looking for new, specific, or private information: this is exactly the sort of information related to household projects, tasks, appliances, and tools. Ideally I’ll be able to use it to help plan projects, identify tasks that should be done, etc. Hopefully, I’ll be able to ask the application questions like “When did I last replace the air filter?”, “What’s the model number of our furnace?”, and so on.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;rag-more-carefully&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;RAG more carefully
  &lt;a href=&#34;#rag-more-carefully&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;One of the main architectures for trying to resolve this issue is what’s known as &lt;strong&gt;retrieval augmented generation&lt;/strong&gt;. An LLM can adopt context: additional data that can be used to help shift the probability of it’s output.&lt;/p&gt;
&lt;p&gt;The context window of an LLM depends on a number of factors — Claude’s projects have a 100mb limit for files that can be used as context. The thought is that in an LLM powered application to interact with documentation, you can query the documentation so that it can be used as particular context when providing an answer. This way the LLM has access to content that it wasn’t trained on.&lt;/p&gt;
&lt;p&gt;Here’s the overall structure:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Documentation is generated and maintained in a helpful and lightweight environment.&lt;/li&gt;
&lt;li&gt;Scripts and tools convert the documentation to a form that can be supplied to the LLM application as context.&lt;/li&gt;
&lt;li&gt;A user interacts with the LLM through (some kind of) interface.&lt;/li&gt;
&lt;li&gt;The inputs from the user are used to query the documentation.&lt;/li&gt;
&lt;li&gt;The query results are passed to the LLM as context.&lt;/li&gt;
&lt;li&gt;The output of the LLM is generated from both context and user text.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Why am I excited about this? Well, it’s a small, self-contained project about an emerging technology. I could, for example, probably skip to an effective similar result with Claude (my notes will be well within its entire context window) or existing tools for integrating note apps with ChatGPT. But this is an opportunity to explore model choice and the architecture necessary to build these kinds of applications.&lt;/p&gt;
&lt;p&gt;I haven’t decided on what the actual build will look like yet (I’ve started research and some notes), but it’s also nice in that it puts me more in touch with the cost of running these models. For a wide range of uses, we’re obscured from seeing the costs of using these tools (both in terms of the actual expense, but also the externalities). By managing the budget and toolchain, I can be better equipped to understand the actual implications of these tools (deciding between a local LLM and an API based instance will be interesting!).&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;the-plan&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;The plan
  &lt;a href=&#34;#the-plan&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s what the project looks like in terms of phases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Phase 1 – Content Creation&lt;/strong&gt;: Document my house, with an eye towards notes that are well suited for this use-case.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2 – Retrieval Tooling&lt;/strong&gt;: Build scripts and tools to convert the content to a database that can be used with the generative AI tools of my choosing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 3 – Back-end Implementation&lt;/strong&gt;: Implement an application back-end to handle key tasks for handling the query and context retrieval.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 4 – Front-end Implementation&lt;/strong&gt;: Build an interface for this so that I can interact with it without using CLI tools.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overall the plan is to blog my way through this: I’ll create posts explaining decisions and steps that I take as I work my way through the project. How am I structuring my house documents? What decisions am I making to try and get the best result at the end? How did I decide on a model? Should I run that model locally or in the cloud?&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;potential-challenges&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Potential challenges
  &lt;a href=&#34;#potential-challenges&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I’m excited to take this on, but it’s going to be a learning experience throughout the project. I’d consider myself ok with writing scripts and simple tools, but not a full developer by any means. In a lot of ways, this feels straight-forward: there’s nothing radically new or interesting about any part of this project, but it will be instructive to assemble these parts.&lt;/p&gt;
&lt;p&gt;Some tool choices are going to be easy (Github, Obsidian, Python) while other parts of the project are new to me (choosing a vector database and query engine). It’s also going to require a bit of a period of dedicated work on top of regular chores — I do think the benefits will be worthwhile. Having improved notes about the house will help me with those chores and integrating them into my life, but this will take a bit more discipline on these matters.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;alternatives&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Alternatives
  &lt;a href=&#34;#alternatives&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is a complicated way of doing the project, but there’s value in doing overly complicated things when you’re interested in building skills.&lt;/p&gt;
&lt;p&gt;Here are some simple alternatives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Claude’s Projects allows you to &lt;a href=&#34;https://support.anthropic.com/en/articles/8241126-what-kinds-of-documents-can-i-upload-to-claude-ai&#34;&gt;store a collection of files&lt;/a&gt; as part of individual projects. The documentation base for your house is probably going to fall within the size window.&lt;/li&gt;
&lt;li&gt;You could probably achieve a similar result using Gemini Pro and Google Drive. Gemini Pro has a large context window, is a general purpose LLM, and can interact with your Google Drive content.&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;how-to-follow-and-contribute&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;How to follow and contribute
  &lt;a href=&#34;#how-to-follow-and-contribute&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You can subscribe to my &lt;a href=&#34;https://www.kevinrkuhl.com/blog/index.xml&#34;&gt;blog feed&lt;/a&gt; for my site to receive updates on this project. I’ll be sharing code samples, documentation structure and more. And if you’d like to get in touch with me to discuss the project or have any advice, you can reach out to me through my &lt;a href=&#34;https://www.kevinrkuhl.com/contact&#34;&gt;contact page&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introduction</title>
      <link>https://www.kevinrkuhl.com/blog/2024/09/introduction/</link>
      <pubDate>Mon, 02 Sep 2024 15:10:46 -0400</pubDate>
      
      <guid>https://www.kevinrkuhl.com/blog/2024/09/introduction/</guid>
      <description>&lt;p&gt;Welcome to my blog!&lt;/p&gt;
&lt;p&gt;My name is &lt;strong&gt;Kevin&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I am a software technical writer in Canada and this is a return to blogging after a few years. I previously blogged about trail running in and around my home province. Up until recently, I was happy with my personal website as a repository for my CV and a small home space on the web.&lt;/p&gt;
&lt;p&gt;Running a blog in 2024 might seem a little passé, after all blogging&amp;rsquo;s heyday was over a decade ago. What I&amp;rsquo;d like to do in my first post is to talk about why and what you can expect if you come back to this blog (or follow this sites RSS feed).&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-a-blog-in-2024&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why a blog in 2024?
  &lt;a href=&#34;#why-a-blog-in-2024&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There are a couple of reasons why I&amp;rsquo;m returning to blogging in 2024.&lt;/p&gt;
&lt;p&gt;Primarily, it&amp;rsquo;s an excuse to write. One of the powerful things about writing is how closely the act is tied to creating ideas. When I write technical documentation, I&amp;rsquo;m helping bring together intentions about what a tool does and creating a resource to build &lt;em&gt;shared understanding&lt;/em&gt;. Writing (and doing it independently) is important because these ideas become clearer in the process. This is especially true for the kinds of projects I work on as a professional writer.&lt;/p&gt;
&lt;p&gt;So, this blog will be a repository for the &amp;ldquo;whys&amp;rdquo; and &amp;ldquo;hows&amp;rdquo; of the things I do when I&amp;rsquo;m writing—a place for those ideas to become more concrete. It will also be a place for other people to understand how they can do similar things. I also think it&amp;rsquo;s important to &lt;em&gt;advocate&lt;/em&gt; for the kind of work we do in software companies. In some cases, people might make assumptions about the kinds of projects and work we can take on. I hope I can showcase the value we bring to software companies.&lt;/p&gt;
&lt;p&gt;Now, all of this could be done with a service like Medium or Substack. After all, if you just want to write, those are good ways to go. You could then have your old site link to the Medium posts.&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;why-a-personal-website&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;Why a personal website?
  &lt;a href=&#34;#why-a-personal-website&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I was already committed to owning a domain and having a website as part of maintaining a bit of personal space on the internet.&lt;/p&gt;
&lt;p&gt;One big reason is that I&amp;rsquo;m looking to stay sharp on my skills for building and managing websites using a variety of tools, such as Github, cloud computing and static site generators. I find fiddling with these tools fun and rewarding! This site is built using &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;, but there are many other options. This kind of technology is flexible, freely available, and has strong community support.&lt;/p&gt;
&lt;p&gt;By authoring on my own computer, all of my content is already on my laptop. I don&amp;rsquo;t have to export my writing elsewhere. I can also write using the tools of my choosing (Git for version control, my preferred editor, Markdown, etc.), which is a definite plus.&lt;/p&gt;
&lt;p&gt;I believe the internet is at its best when it provides opportunities for independent or collaborative efforts. Building and maintaining my own website, with its own content, is part of a project to make the internet a better place. I want the internet to be filled with diverse perspectives and stories. I want it to have meaningful writing that&amp;rsquo;s meant to communicate ideas and points of view.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve modified this Hugo theme to fit with the principles of the &lt;a href=&#34;https://indieweb.org/&#34;&gt;Indieweb&lt;/a&gt;, because my personal outlook on technology and content aligns with the principles and goals of this movement. I want to own my identity on the web, and my content. By writing it here, I&amp;rsquo;ll have local copies of all my posts. And above all, fiddling with websites and computers is &lt;em&gt;fun&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So, these are the reasons I&amp;rsquo;m returning to blogging. Thanks for coming along as a reader!&lt;/p&gt;
&lt;!-- end-chunk --&gt;
&lt;!-- begin-chunk data-anchor=&#34;what-can-you-expect-on-this-blog&#34; --&gt;

&lt;h2 class=&#34;header-anchor-wrapper&#34;&gt;What can you expect on this blog?
  &lt;a href=&#34;#what-can-you-expect-on-this-blog&#34; class=&#34;header-anchor-link&#34;&gt;
&lt;svg
    xmlns=&#34;http://www.w3.org/2000/svg&#34;
    width=&#34;1rem&#34; height=&#34;1rem&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;
    stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34;
    stroke-linejoin=&#34;round&#34;&gt;
    &lt;line x1=&#34;4&#34; y1=&#34;9&#34; x2=&#34;20&#34; y2=&#34;9&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;4&#34; y1=&#34;15&#34; x2=&#34;20&#34; y2=&#34;15&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;10&#34; y1=&#34;3&#34; x2=&#34;8&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;&lt;line x1=&#34;16&#34; y1=&#34;3&#34; x2=&#34;14&#34; y2=&#34;21&#34;&gt;&lt;/line&gt;
&lt;/svg&gt;

&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Primarily, I&amp;rsquo;ll be talking about professional topics. As a software technical writer, my job is to produce useful and clear writing that explains how to do things with software products. This is an interesting field! There&amp;rsquo;s a lot to understanding how people learn and use software. And while I have produced pieces ranging from white papers to reference documents and learning modules, what I really enjoy is thinking about the design and upkeep of knowledge.&lt;/p&gt;
&lt;p&gt;Technical writing is about being able to build resources that are useful and clear. My best experiences with documentation involved well-built tutorials, carefully crafted conceptual explanations, and clear answers to questions I was struggling to articulate. And I think this is why, even though the profession is changing with the advent of generative AI, I don&amp;rsquo;t think our role is going away.&lt;/p&gt;
&lt;p&gt;Projects I have in mind for this website include:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Explaining how I approach certain kinds of processes, work situations, and solutions.&lt;/li&gt;
&lt;li&gt;Discussions of emerging technologies and their impact on the profession.&lt;/li&gt;
&lt;li&gt;Documenting projects and things that I&amp;rsquo;m working on, as I regularly use coding scripting, and various tools.&lt;/li&gt;
&lt;li&gt;Book read-alongs and comments on media that relates to my professional life.&lt;/li&gt;
&lt;li&gt;Posts about social trends working in technology, and thoughts from community projects I&amp;rsquo;m interested in organizing.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I won&amp;rsquo;t be holding myself to a regular publishing schedule, but I am aiming for roughly monthly posts. If you have any thoughts or ideas for posts, feel free to reach out to me through my &lt;a href=&#34;https://www.kevinrkuhl.com/contact&#34;&gt;contact&lt;/a&gt; page or on social media!&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>