<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	 xmlns:friends="wordpress-plugin-friends:feed-additions:1" >

<channel>
	<title>Alex Kirk</title>
	<atom:link href="https://alex.kirk.at/feed/" rel="self" type="application/rss+xml" />
	<link>https://alex.kirk.at</link>
	<description></description>
	<lastBuildDate>Wed, 03 Jun 2026 09:32:43 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cropped-2025.Alex-512x512-1-150x150.jpg</url>
	<title>Alex Kirk</title>
	<link>https://alex.kirk.at</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordCamp Companion</title>
		<link>https://alex.kirk.at/2026/06/03/wordcamp-companion/</link>
					<comments>https://alex.kirk.at/2026/06/03/wordcamp-companion/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Wed, 03 Jun 2026 09:12:32 +0000</pubDate>
				<category><![CDATA[My WordPress]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[my.wordpress.net]]></category>
		<category><![CDATA[WCEU]]></category>
		<category><![CDATA[WordCamp]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=3399450</guid>

					<description><![CDATA[I released a WordCamp Companion plugin to guide you through your day. You can run it inside my.wordpress.net.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Although I won&#8217;t be attending the WordPress conference <a href="https://europe.wordcamp.org/2026/">WordCamp Europe 2026 in Krakow</a> this year because of other commitments, I built something that could be useful for attendees of it, as well as for future WordCamps.</p>



<p class="wp-block-paragraph"><a href="https://github.com/akirk/wordcamp-companion">WordCamp Companion</a> is a tool to plan your WordCamp and guide you through it, as well as for taking notes during sessions.</p>



<p class="wp-block-paragraph">It is built as a WordPress plugin which you can install to your own WordPress (not in the plugin directory yet so you need to <a href="https://github.com/akirk/wordcamp-companion/archive/refs/heads/dist/main.zip">download the ZIP</a>) or use through <a href="https://my.wordpress.net/">my.wordpress.net</a> that I talked about in <a href="https://alex.kirk.at/tag/my-wordpress-net/">my previous posts</a>.</p>



<p class="wp-block-paragraph">Use <a href="https://my.wordpress.net/?myapps-i=wordcamp-companion">this link to start it directly in my.wordpress.net</a>. Since it is a WordPress hosted in your browser, it is free and private.</p>



<p class="wp-block-paragraph">The plugin features:</p>



<ul class="wp-block-list">
<li>A live updating timeline with easy adding of sessions,</li>



<li>Note taking for each session with export,</li>



<li>Sharing sessions to others,</li>



<li>AI Assistant compatibility.</li>
</ul>



<p class="wp-block-paragraph">Scroll down to find screenshots and screen recordings of those features.</p>



<p class="wp-block-paragraph">Let&#8217;s start with timeline view. It will automatically update according to the current time and show you when to switch tracks.</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-medium"><img fetchpriority="high" decoding="async" width="474" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline-474x800.png" alt="Timeline view of WordCamp Companion" class="wp-image-3425454" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline-474x800.png 474w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline-606x1024.png 606w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline-768x1297.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline-909x1536.png 909w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline.png 932w" sizes="(max-width: 474px) 100vw, 474px" /><figcaption class="wp-element-caption">At a glance you can see what&#8217;s up next</figcaption></figure>



<figure class="wp-block-video"><video height="782" style="aspect-ratio: 450 / 782;" width="450" controls src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline.mp4"></video><figcaption class="wp-element-caption">Speed run through a day</figcaption></figure>
</div>



<h3 class="wp-block-heading">Adding Sessions</h3>



<p class="wp-block-paragraph">In the timeline you can see an &#8220;Add a session&#8221; in the gaps of your schedule.</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-medium"><img decoding="async" width="461" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-add-session2-461x800.png" alt="" class="wp-image-3425825" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-add-session2-461x800.png 461w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-add-session2-590x1024.png 590w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-add-session2-768x1332.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-add-session2-885x1536.png 885w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-add-session2.png 898w" sizes="(max-width: 461px) 100vw, 461px" /><figcaption class="wp-element-caption">Adding sessions</figcaption></figure>



<figure class="wp-block-image size-medium"><img decoding="async" width="459" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-overlap-459x800.png" alt="" class="wp-image-3425824" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-overlap-459x800.png 459w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-overlap-588x1024.png 588w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-overlap-768x1337.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-overlap-882x1536.png 882w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-overlap.png 896w" sizes="(max-width: 459px) 100vw, 459px" /><figcaption class="wp-element-caption">Overlaps are pointed out</figcaption></figure>
</div>



<h3 class="wp-block-heading">Note Taking</h3>



<p class="wp-block-paragraph">You can take notes inline in Markdown-style which you can then export.</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-video"><video height="780" style="aspect-ratio: 448 / 780;" width="448" controls src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes.mp4"></video><figcaption class="wp-element-caption">Video showing how to add notes</figcaption></figure>



<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="459" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-overview-1-459x800.png" alt="The notes export screen featuring a preview of the notes" class="wp-image-3425804" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-overview-1-459x800.png 459w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-overview-1-587x1024.png 587w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-overview-1-768x1339.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-overview-1-881x1536.png 881w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-overview-1.png 896w" sizes="auto, (max-width: 459px) 100vw, 459px" /><figcaption class="wp-element-caption">Export your notes</figcaption></figure>
</div>



<h3 class="wp-block-heading">Session Sharing</h3>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="458" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-458x800.png" alt="A QR code of a link that contains the wordcamp + shared schedule" class="wp-image-3425807" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-458x800.png 458w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-586x1024.png 586w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-768x1341.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-879x1536.png 879w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share.png 892w" sizes="auto, (max-width: 458px) 100vw, 458px" /><figcaption class="wp-element-caption">Share via QR code</figcaption></figure>



<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="458" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-accept-458x800.png" alt="Import Shared Schedule screenshot showing checkboxes of what can be added to your schedule" class="wp-image-3425813" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-accept-458x800.png 458w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-accept-586x1024.png 586w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-accept-768x1341.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-accept-879x1536.png 879w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-share-accept.png 892w" sizes="auto, (max-width: 458px) 100vw, 458px" /><figcaption class="wp-element-caption">Selectively accept</figcaption></figure>
</div>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>If you are interested, here are some technical details about how this works.</summary>
<p class="wp-block-paragraph">Since the sharing link points to my.wordpress.net, a lot needs to happen for this to work:</p>



<ol class="wp-block-list">
<li>You click the WordCamp Companion share link pointing to a URL like <code>https://my.wordpress.net/?myapps-i=wordcamp-companion&amp;wcc1=…</code> which:</li>



<li>Loads my.wordpress.net which downloads WordPress, PHP wasm, etc, everything that is needed for the Playground runtime.</li>



<li>Installs the My Apps plugin which is a central point in the easy experience of it,</li>



<li>Navigates to URL above so that WordPress receives it,</li>



<li>My Apps installs the Wordcamp Companion and redirects to it (minus its own parameter), </li>



<li>Then the WordCamp Companion plugin reads the URL parameter <code>wcc1</code> to import the schedule.</li>
</ol>



<p class="wp-block-paragraph">This is all quite complex just to make it work inside my.wordpress.net. But this offers an experience where you don&#8217;t install it on your WordPress just to try it. If you like it, I recommend doing so because then all you need to know is your own URL.</p>



<p class="wp-block-paragraph">And if you did install it on your own WordPress, you can import it also  by just pasting the share link into your companion.</p>
</details>



<h3 class="wp-block-heading">All WordCamps</h3>



<p class="wp-block-paragraph">While it is good timing for WordCamp Europe, it also works for multiple (future) WordCamps:</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="458" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-upcoming-wordcamps-458x800.png" alt="List of upcoming WordCamps" class="wp-image-3425860" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-upcoming-wordcamps-458x800.png 458w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-upcoming-wordcamps-587x1024.png 587w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-upcoming-wordcamps-768x1341.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-upcoming-wordcamps-880x1536.png 880w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-upcoming-wordcamps.png 896w" sizes="auto, (max-width: 458px) 100vw, 458px" /></figure>



<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="459" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-mannheim-459x800.png" alt="A timeline of WordCamp Mannheim" class="wp-image-3425861" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-mannheim-459x800.png 459w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-mannheim-588x1024.png 588w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-mannheim-768x1338.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-mannheim-882x1536.png 882w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-mannheim.png 898w" sizes="auto, (max-width: 459px) 100vw, 459px" /></figure>
</div>



<h3 class="wp-block-heading">AI Assistant Compatible</h3>



<p class="wp-block-paragraph">I&#8217;ve been working on a capable <a href="https://github.com/akirk/ai-assistant">AI Assistant for WordPress</a> that you can try inside my.wordpress.net. It can help you work out a schedule:</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="457" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-tips-457x800.png" alt="AI Assistant shows tips of what it can do for you with regards to the WordCamp Companion" class="wp-image-3425980" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-tips-457x800.png 457w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-tips-585x1024.png 585w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-tips-768x1345.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-tips-877x1536.png 877w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-tips.png 892w" sizes="auto, (max-width: 457px) 100vw, 457px" /><figcaption class="wp-element-caption">The AI Assistant gives you tips on what you can do</figcaption></figure>



<figure class="wp-block-video"><video height="776" style="aspect-ratio: 432 / 776;" width="432" controls src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-ai-assistant.mp4"></video><figcaption class="wp-element-caption">For example, adding sessions to your plan</figcaption></figure>
</div>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="457" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-start-457x800.png" alt="Taking notes in AI assistant as you go" class="wp-image-3425982" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-start-457x800.png 457w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-start-585x1024.png 585w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-start-768x1345.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-start-877x1536.png 877w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-start.png 894w" sizes="auto, (max-width: 457px) 100vw, 457px" /><figcaption class="wp-element-caption">Write notes as you go</figcaption></figure>



<figure class="wp-block-image size-medium"><img loading="lazy" decoding="async" width="459" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-compile-459x800.png" alt="Afterwards the AI Assistant helps tightening your notes" class="wp-image-3425981" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-compile-459x800.png 459w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-compile-587x1024.png 587w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-compile-768x1340.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-compile-881x1536.png 881w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes-compile.png 892w" sizes="auto, (max-width: 459px) 100vw, 459px" /><figcaption class="wp-element-caption">Compile notes at the end</figcaption></figure>
</div>



<p class="wp-block-paragraph">If you&#8217;re attending this WordCamp Europe, or other future WordCamps, give the WordCamp Companion a try. You can do it easily and risk-free with <a href="https://my.wordpress.net/?myapps-i=wordcamp-companion">this link to start it directly in my.wordpress.net</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2026/06/03/wordcamp-companion/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		<enclosure url="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-timeline.mp4" length="1379112" type="video/mp4" />
<enclosure url="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-notes.mp4" length="1107458" type="video/mp4" />
<enclosure url="https://alex.kirk.at/wp-content/uploads/sites/2/2026/06/wordcamp-companion-ai-assistant.mp4" length="6939203" type="video/mp4" />

		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Personal Software Needs a Home</title>
		<link>https://alex.kirk.at/2026/05/14/personal-software-needs-a-home/</link>
					<comments>https://alex.kirk.at/2026/05/14/personal-software-needs-a-home/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Thu, 14 May 2026 12:22:16 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[My WordPress]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[my.wordpress.net]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=3354509</guid>

					<description><![CDATA[AI makes personal software easier to create, but it still needs a place to live. I see WordPress as an unexpected but practical platform for personal apps and data.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">David Pierce’s piece in <a href="https://www.theverge.com/tech/928905/vibe-code-personal-software-revolution">The Verge about the “personal software revolution”</a> captures something that resonates strongly with me: AI is making it easier to create software for one&#8217;s exact needs.</p>



<p class="wp-block-paragraph">I think today every developer who is jumping on the AI train experiences it themselves: they can suddenly scratch many of their own software itches with a quick prompt.</p>



<p class="wp-block-paragraph">Of course, developers are more likely to think of software-driven solutions to real-world problems than non-developers. But as creating apps gets easier, that instinct may spread beyond developers too, as the Verge article describes.</p>



<p class="wp-block-paragraph">That is exciting. But I think the more interesting question is not only “who writes the code?” It is: where does this personal software live?</p>



<p class="wp-block-paragraph">Already before this AI revolution, developers built software using their favorite stack. That&#8217;s what they are fastest in, that&#8217;s a setup where they run their other self-developed software already. And this leads to what I call the self-hosting chaos:</p>



<p class="wp-block-paragraph">Yes, there is Docker as a solution to run any stack on any machine but it&#8217;s really a developer tool. And while there are solutions like <a href="https://instapods.com/">Instapods</a> which I applaud for its effort to try and make it easy, as a user, every tool still has its own setup flow.</p>



<p class="wp-block-paragraph">And then there are questions like: Where is the data stored? Can I export it? Do I need another host for a second app?</p>



<p class="wp-block-paragraph">It might be a surprising angle but this is where I think <a href="https://wordpress.org/">WordPress</a> has an interesting role to play, and I&#8217;ve been working on making this even more feasible recently.</p>



<p class="wp-block-paragraph">The fact that it&#8217;s a widely used software for blogging has the side-effect that it&#8217;s easy to find hosting for it anywhere you like. So, what if you don&#8217;t use it for blogging, but as a personal app platform?</p>



<p class="wp-block-paragraph">This needs a reframe of people&#8217;s thinking, and <a href="https://alex.kirk.at/2026/04/14/why-my-wordpress/" data-type="post" data-id="3267981">I wrote about it just recently</a>. But once you let it sink in, WordPress is a pretty decent platform for personal apps, providing lots of things out of the box:</p>



<ul class="wp-block-list">
<li>Easy plugin installation,</li>



<li>User accounts and permissions,</li>



<li>Media library,</li>



<li>Posts, pages, custom post types, and taxonomies,</li>



<li>REST APIs,</li>



<li>Import/export,</li>



<li>Widely available hosting.</li>
</ul>



<p class="wp-block-paragraph">Ok, if you send someone to wp-admin and ask them to install an app, that would be overwhelming. But with the right tooling to guide the user, we can make this real easy.</p>



<p class="wp-block-paragraph">While the final destination would be a hosted WordPress somewhere, there is <a href="https://my.wordpress.net/">my.wordpress.net</a> which is a free, hosted-in-the-browser WordPress where you can give it a go without registration.</p>



<p class="wp-block-paragraph">You&#8217;ll arrive in an <a href="https://wordpress.org/plugins/my-apps/">app launcher</a>-like screen:</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="483" height="292" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.39.23.png" alt="Hi, Alex!
What can I do?
Welcome to your WordPress
Add" class="wp-image-3354516"/></figure>



<p class="wp-block-paragraph">And the Add button takes you to an &#8220;App Store&#8221; with apps pre-selected for the yet-uncommon use case of &#8220;personal software.&#8221;</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="845" height="836" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.39.40.png" alt="AI Assistant — AI-powered chat interface to modify your WordPress to your liking. Bring your own key or use a local LLM
Chat to Blog — Import media from Beeper chats and create blog posts. Requires Beeper Desktop running.
Collect Posts from the Web — Use the Post Collection Plugin to save articles from around the web
Cookbook — Store your recipes in your WordPress, with ingredients, steps, and prep/cook times. Paste a URL to pull a recipe in from the web.
Memex — Turn WordPress into a note-taking app with bi-directional links, automatic backlinks, daily notes, tags, and reminders. Import notes from Obsidian, Notion, Evernote, or Roam Research with one click.
Personal CRM — Manage your contacts and relationships directly from WordPress
RSS Reader — Follow friends and consume their content in your WordPress" class="wp-image-3354518" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.39.40.png 845w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.39.40-655x648.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.39.40-768x760.png 768w" sizes="auto, (max-width: 845px) 100vw, 845px" /></figure>



<p class="wp-block-paragraph">Granted, the selection of apps is still limited but this is mostly an effort to kickstart the ecosystem for this use case, while at the same time having some really useful apps that go beyond a simple prototype.</p>



<p class="wp-block-paragraph">Recipes aim to give you more concrete ideas of what you can do:</p>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="837" height="1000" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.40.48.png" alt="Build a Family Blog — Memories worth keeping, kept where they belong
Document Family History — A private Wikipedia for your family
Build a Personal Cookbook — Keep the recipes you actually cook
Take Notes in WordPress — Capture notes in the shape that fits
Personal Reading Hub — Follow friends, save articles, read on your terms
Bring Your Data In — Move existing data onto your WordPress, in the right shape for each app
Stay in Touch — A private contact directory with reminders
Customize with AI — Modify your WordPress through chat" class="wp-image-3354519" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.40.48.png 837w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.40.48-655x783.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/05/Screenshot-2026-05-14-at-13.40.48-768x918.png 768w" sizes="auto, (max-width: 837px) 100vw, 837px" /></figure>



<p class="wp-block-paragraph">For example, personally, I&#8217;ve been enjoying <a href="https://github.com/akirk/cookbook/">storing my recipes in my WordPress</a>. Some are recipes passed down through family generations. Others are ones I had cherry-picked from the web, then later had to remember which blog I had found them on when I wanted to cook them again.</p>



<p class="wp-block-paragraph">And while &#8220;<a href="https://github.com/akirk/ai-assistant">AI Assistant</a>&#8221; is quickly becoming an overused concept, I really like how it can not only work with those apps (&#8220;I&#8217;m trying to eat vegan today, give me a variation of the recipe (I&#8217;m currently looking at)&#8221;) but also how it can work across app boundaries because they all live in my WordPress (&#8220;My friend recently blogged about recipe X, please add it to my cookbook and put it on my meal plan for tomorrow&#8221;).</p>



<p class="wp-block-paragraph">Granted, you need to provide your own API key or run <a href="https://ollama.com/">Ollama</a> or <a href="https://lmstudio.ai/">LM Studio</a> locally (I hope this will get better some day!), but then it can even build the apps you wish for right there as a new plugin that you can then download and share.</p>



<h3 class="wp-block-heading">WordPress as the Personal App Platform</h3>



<p class="wp-block-paragraph">But back to the point about the platform for apps:</p>



<p class="wp-block-paragraph">I think WordPress is so great because installing an app is as easy as installing a regular WordPress plugin (if not easier, with the <a href="https://wordpress.org/plugins/my-apps/">My Apps plugin</a> screenshotted above).</p>



<p class="wp-block-paragraph">And for developers, there is this place where all your apps can run, with nice features out of the box, and honestly, AI doesn&#8217;t care much in which programming language they implement your dream software. Even PHP.</p>



<p class="wp-block-paragraph">I&#8217;ll just admit that <a href="https://my.wordpress.net/">my.wordpress.net</a> is my work, so I am biased. But I believe there is real merit in building the future of personal software on the benefits of the legacy of open source WordPress. It was built for one weird use case twenty years ago. It might quietly turn out to be built for the next one too.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2026/05/14/personal-software-needs-a-home/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Why My WordPress?</title>
		<link>https://alex.kirk.at/2026/04/14/why-my-wordpress/</link>
					<comments>https://alex.kirk.at/2026/04/14/why-my-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Tue, 14 Apr 2026 10:01:14 +0000</pubDate>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[Mastodon]]></category>
		<category><![CDATA[my.wordpress.net]]></category>
		<category><![CDATA[playground]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=3267981</guid>

					<description><![CDATA[WordPress as a personal tool: for keeping memories, staying in touch, owning your data. No audience required.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Most WordPress plugins are built to grow your audience. I&#8217;ve been going in the opposite direction for years: building tools not to increase reach, but for personal reasons: to stay connected to people I care about, to keep memories that would otherwise scatter, to own the data that documents my own life.</p>



<p class="wp-block-paragraph">That work has added up to something I&#8217;d call a coherent vision. And now, with <a href="https://my.wordpress.net">my.wordpress.net</a>, I believe I have contributed to tearing down one of the last walls that have been blocking people from joining me in this experience.</p>



<h2 class="wp-block-heading">The wall</h2>



<p class="wp-block-paragraph">I have created many of the plugins I&#8217;m going to describe already some while ago. They&#8217;ve found an audience, but admittedly inside a bubble: people who already had a WordPress, or were technical enough to spin one up just to try something.</p>



<div class="wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-7387b849 wp-block-group-is-layout-flex">
<p class="wp-block-paragraph">But I believe the personal use of WordPress goes beyond people who already use WordPress today. It is not well known that WordPress is a pretty good platform to run just for your own or your small social circle&#8217;s benefit.</p>
</div>



<figure class="wp-block-image aligncenter size-medium"><img loading="lazy" decoding="async" width="655" height="248" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/my-wordpress-2-655x248.png" alt="" class="wp-image-3283488" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/my-wordpress-2-655x248.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/my-wordpress-2-768x291.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/my-wordpress-2.png 1020w" sizes="auto, (max-width: 655px) 100vw, 655px" /><figcaption class="wp-element-caption">Your free WordPress without setup at <a href="https://my.wordpress.net/">my.wordpress.net</a></figcaption></figure>



<p class="wp-block-paragraph">To try a plugin that makes WordPress personally useful, you first need a WordPress. And setting one up means finding a host, picking a domain, making decisions about a site you&#8217;re not even sure you want yet. That&#8217;s a publishing commitment, and most people won&#8217;t make it just to see if a feed reader or a personal CRM might be useful to them.</p>



<p class="wp-block-paragraph">That&#8217;s the wall I kept running into. And that&#8217;s why I built <a href="https://wordpress.org/news/2026/03/announcing-my-wordpress/">my.wordpress.net</a>: a complete WordPress that runs in your browser, no sign-up, no hosting plan, no domain needed.</p>



<p class="wp-block-paragraph">It just behaves like a normal WordPress: you change something, you come back tomorrow, it&#8217;s still there. Persistent, and private by default.</p>



<p class="wp-block-paragraph">Which sounds obvious because that&#8217;s how a website is supposed to work. But it&#8217;s built on <a href="https://playground.wordpress.net/">WordPress Playground</a>, a developer tool that is fresh and forgetful by design, because that&#8217;s useful when you&#8217;re testing things. And if you&#8217;re a developer: don&#8217;t worry, <a href="https://playground.wordpress.net/">playground.wordpress.net</a> will remain.</p>



<h2 class="wp-block-heading">What your personal WordPress can do</h2>



<p class="wp-block-paragraph">Once you have a WordPress that&#8217;s yours rather than your audience&#8217;s, a whole different set of questions becomes interesting.</p>



<p class="wp-block-paragraph"><strong>Keeping memories.</strong> When our first child was born, we wanted to keep a diary. We wanted more than just collecting the photos and videos, we wanted to have a place where we could also write down the stories, the funny things they say, messages in a bottle to them later on. A private blog was the perfect solution for that. And later, with <a href="https://wordpress.org/plugins/enable-mastodon-apps/">Enable Mastodon Apps</a>, we started using a nice mobile Mastodon app to do it, and grandparents to follow along, who would have thought of that?</p>



<p class="wp-block-paragraph"><strong>Gathering memories.</strong> My daughter had a ski day recently. Photos came in from several different group chats: parents, the teachers. Before <a href="https://github.com/akirk/chat-to-blog">Chat to Blog</a>, I would have to save them each and reupload them to my WordPress. But since I can now privately connect it to <a href="https://www.beeper.com/">Beeper</a> (a messaging client that can talk to Signal, Whatsapp, etc), it allows me to put the media directly into a new post and the media library, without any forwarding or downloading. The chat messages can disappear someday and it won&#8217;t matter, I still have the blog post.</p>



<p class="wp-block-paragraph"><strong>Staying in touch.</strong> There are people in my life I genuinely care about, where things have faded a little; not because either of us stopped caring, but just because everyone has a busy life. Sometimes all it would take is a reminder to send a quick hello. <a href="https://github.com/akirk/personal-crm">Personal CRM</a> turns WordPress into a private contact directory for the people who matter to you. Combined with <a href="https://github.com/akirk/keeping-contact">Keeping Contact</a>, it tracks when you last reached out and reminds you when it&#8217;s been too long. It&#8217;s not a sales tool. It&#8217;s just the nudge to actually do it.</p>



<p class="wp-block-paragraph"><strong>What are you reading?</strong> The <a href="https://wordpress.org/plugins/friends/">Friends plugin</a> makes WordPress a feed reader: follow RSS feeds, Atom feeds, ActivityPub accounts. Everything you chose to follow in one timeline, without any algorithm deciding what to surface. <a href="https://alex.kirk.at/2026/03/25/friends-4-0/">Friends 4.0</a> added three themes: a Google Reader-style interface with keyboard shortcuts (for those who never quite got over losing it in 2013), a Mastodon-style view for people already at home in the Fediverse, and a Block Theme option that integrates with your site&#8217;s own design. On a hosted WordPress, you can also participate in the Fediverse directly: follow and be followed, post to your own site and have it federate to Mastodon; and with <a href="https://wordpress.org/plugins/enable-mastodon-apps/">Enable Mastodon Apps</a>, you can use any Mastodon client to do it.</p>



<figure class="wp-block-gallery has-nested-images columns-2 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="415" data-id="3247954" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-1024x415.png" alt="" class="wp-image-3247954" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-1024x415.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-655x265.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-768x311.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon.png 1160w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="414" data-id="3247950" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-1024x414.png" alt="" class="wp-image-3247950" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-1024x414.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-655x265.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-768x310.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader.png 1176w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="456" data-id="3247949" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-1024x456.png" alt="" class="wp-image-3247949" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-1024x456.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-655x292.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-768x342.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme.png 1175w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="463" data-id="3247948" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-1024x463.png" alt="" class="wp-image-3247948" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-1024x463.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-655x296.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-768x347.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme.png 1177w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
<figcaption class="blocks-gallery-caption wp-element-caption">Themes for your Friends Plugin</figcaption></figure>



<p class="wp-block-paragraph"><strong>What articles did you save and actually read?</strong> <a href="https://github.com/akirk/friends-post-collection">Post Collection</a> clips articles from the web into your WordPress. <a href="https://github.com/akirk/friends-send-to-e-reader">Send to E-Reader</a> routes them to your Tolino or Kobo, Kindle or Pocketbook, so the things you saved are the things you actually end up reading, just maybe on a different device on which you saved them.</p>



<p class="wp-block-paragraph"><strong>Keeping family history.</strong> I&#8217;ve always enjoyed hearing the little anecdotes from my family, but I wish I&#8217;d have a better memory for them. Thus I started <a href="https://alex.kirk.at/2024/01/19/keeping-a-family-wiki/" data-type="post" data-id="1919057">keeping a private family wiki</a> where the we collaborate in maintaining a Wikipedia for our family. It feels great to have this family chronicle to pass on.</p>



<p class="wp-block-paragraph"><strong>Longevity.</strong> Right now, in my family, I am the most technical person. What will happen to all those memories in our WordPress? To make sure all those stories can persist, I created <a href="https://github.com/akirk/static-archive">Static Archive</a> which turns backups into easily accessible treasure troves. It works by keeping an HTML copy of your posts (and wiki pages) with inline media in your uploads folder, automatically updated every time you publish. It&#8217;s not a typical static site generator, it just quietly maintains an archive that is always current.</p>



<p class="wp-block-paragraph"><strong>What do you want to ask your own data?</strong> The <a href="https://github.com/akirk/ai-assistant">AI Assistant</a> empowers you to modify your WordPress through chat. It can create or modify plugins to your liking, theme your site, interact with plugins through abilities that they provide. It pulls AI into your WordPress instead of interacting with it from the outside. This supports local models (for example through <a href="https://lmstudio.ai/">LM Studio</a>) as well as OpenAI and Anthropic if you can provide an API key.</p>



<p class="wp-block-paragraph">When <a href="https://wordpress.org/news/2026/03/announcing-my-wordpress/">announcing My WordPress</a> and also inside <a href="https://my.wordpress.net/">my.wordpress.net</a>, we&#8217;re using the metaphor of an app because they work like a web app, just hosted on your own WordPress. For the technically inclined: they are indeed plugins, but sometimes multiple working together, installed already configured through a blueprint.</p>



<figure class="wp-block-image aligncenter size-medium"><img loading="lazy" decoding="async" width="641" height="800" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/Screenshot-2026-04-10-at-12.54.00-641x800.png" alt="" class="wp-image-3275245" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/Screenshot-2026-04-10-at-12.54.00-641x800.png 641w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/Screenshot-2026-04-10-at-12.54.00-820x1024.png 820w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/Screenshot-2026-04-10-at-12.54.00-768x959.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/04/Screenshot-2026-04-10-at-12.54.00.png 990w" sizes="auto, (max-width: 641px) 100vw, 641px" /><figcaption class="wp-element-caption">The <a href="https://wordpress.org/plugins/my-apps/">My Apps plugin</a> in action, making it easy to go into your different installed apps</figcaption></figure>



<h2 class="wp-block-heading">What this is really about</h2>



<p class="wp-block-paragraph">WordPress is a widely available piece of open source software: you have a vast choice of hosts, or you can even install it on your local NAS (they usually already allow to install WordPress easily). While there are <a href="https://selfh.st/">many tools that you can already self-host</a>, each needs individual knowledge to set them up correctly. WordPress can be this one platform that can run all your apps, making it much more accessible.</p>



<p class="wp-block-paragraph">The plugins I mentioned before have a few things in common. Your data lives on your WordPress: contacts, reading lists, saved articles, conversation history. They are not locked into someone else&#8217;s service where maybe you can get them out with a data export request, in a format of their choice.</p>



<p class="wp-block-paragraph">But instead, everything lives in one place, and you (or a plugin) can combine it however you want, without involving anyone else.</p>



<p class="wp-block-paragraph">You can modify your WordPress like you want: have plugins created for your needs, modify existing ones to your liking. With AI this is now becoming much more feasible for anyone.</p>



<p class="wp-block-paragraph">And finally, this is all free and open source. No subscriptions, no per-user fees. You can run the software yourself, for as long as you want.</p>



<h2 class="wp-block-heading">Getting Started</h2>



<p class="wp-block-paragraph"><a href="https://my.wordpress.net">my.wordpress.net</a> can be your starting point. It has its limitations and you might outgrow them. Because it&#8217;s a browser-based WordPress, it can reach out to the web to fetch feeds, clip articles, call APIs. But the web can&#8217;t reach in: ActivityPub federation, being followed by others, multi-device access: these need a reachable server.</p>



<p class="wp-block-paragraph">But that&#8217;s just a natural progression: You start in the browser, discover what you actually want from a personal WordPress, and transfer to a webhost when the networked features become worth it.</p>



<p class="wp-block-paragraph">And if you already have a WordPress, all of this is for you too. Skip <a href="https://my.wordpress.net/">my.wordpress.net</a> and proceed to taking back the web for yourself straight away.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2026/04/14/why-my-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Friends 4.0</title>
		<link>https://alex.kirk.at/2026/03/25/friends-4-0/</link>
					<comments>https://alex.kirk.at/2026/03/25/friends-4-0/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Wed, 25 Mar 2026 13:15:41 +0000</pubDate>
				<category><![CDATA[Enable Mastodon Apps]]></category>
		<category><![CDATA[Friends Plugin]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=3247868</guid>

					<description><![CDATA[It has been baking for much longer than I wanted, but today I released the next major version of my Friends Plugin for WordPress. Focusing on ActivityPub The biggest change is a deviation from the original idea: Friendships between WordPresses have been removed. With ActivityPub (when the respective ActivityPub plugin is installed, too) we have [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">It has been baking for much longer than I wanted, but today I released the next major version of my <a href="https://wordpress.org/plugins/friends/">Friends Plugin for WordPress</a>.</p>



<h3 class="wp-block-heading">Focusing on ActivityPub</h3>



<p class="wp-block-paragraph">The biggest change is a deviation from the original idea: Friendships between WordPresses have been removed. With ActivityPub (when the respective <a href="https://wordpress.org/plugins/activitypub/">ActivityPub plugin</a> is installed, too) we have a communication protocol that is supported by many more platforms than just other WordPresses that also happen to have installed the Friends plugin.</p>



<p class="wp-block-paragraph">Removing friendship functionality reduces a lot of complexity in the plugin that changed some fundamentals of WordPress. The friendship functionality had been deactivated for a while behind a checkbox.</p>



<p class="wp-block-paragraph">This means that the Friends plugin now focusses on functionality of subscribing to feeds (be it RSS, Atom or ActivityPub) and integrating outward communication via ActivityPub (direct messages, replies).</p>



<h3 class="wp-block-heading">Themes</h3>



<p class="wp-block-paragraph">To make the consuming more attractive, I have worked on providing more integrated themes. I had <a href="https://github.com/akirk/friends/wiki/Writing-Themes">added the ability to contribute themes</a> already some time ago, thanks for the <a href="https://github.com/alquimidia/fedipress">FediPress theme</a> contribution! Being more a developer than a designer, my <strong>default Friends theme</strong> has been deemed more functional than pretty (from what I heard).</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="463" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-1024x463.png" alt="" class="wp-image-3247948" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-1024x463.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-655x296.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme-768x347.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-default-theme.png 1177w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Default theme</figcaption></figure>



<p class="wp-block-paragraph">So, the new themes are:</p>



<p class="wp-block-paragraph">A <strong>Block Theme</strong>, which allows you to modify the Friends page using the Site Editor and gives it the design of your own site&#8217;s theme.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="456" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-1024x456.png" alt="" class="wp-image-3247949" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-1024x456.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-655x292.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme-768x342.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-block-theme.png 1175w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Block Theme</figcaption></figure>



<p class="wp-block-paragraph">A <strong>Google Reader Theme</strong> makes it look like Google Reader. This comes with keyboard shortcuts and the accordion-like behavior of the posts.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="414" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-1024x414.png" alt="" class="wp-image-3247950" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-1024x414.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-655x265.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader-768x310.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-google-reader.png 1176w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Google Reader Theme</figcaption></figure>



<p class="wp-block-paragraph">I had already done a <a href="https://github.com/akirk/friends-mastodon-like-interface">prototype</a> of a <strong>Mastodon Theme</strong> and have now added a functional one that is shipped by default.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="415" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-1024x415.png" alt="" class="wp-image-3247954" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-1024x415.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-655x265.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon-768x311.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-mastodon.png 1160w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Mastodon Theme</figcaption></figure>



<p class="wp-block-paragraph">All the themes now support light and dark mode (which makes the Mastodon theme look a bit unusual in light mode).</p>



<p class="wp-block-paragraph">I hope that the screenshots above highlight the versatility of the plugin and how much the visual appearance can shape the perception.</p>



<h3 class="wp-block-heading">Migrations</h3>



<p class="wp-block-paragraph">A big reason for the 4.0 version number was the number of migrations of internal data structures towards more taxonomies (the Friends plugin did not and does not use custom tables). This removes the last bits of supporting WordPress users as friend users and adds proper term relationships between friends and subscriptions. This also allowed to add support for folders.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="147" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-1024x147.png" alt="" class="wp-image-3247959" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-1024x147.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-655x94.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification-768x110.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-4.0-notification.png 1308w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">But it makes a transition from an earlier version potentially a bit tricky. With this amount of changes and migrations, I opted to make it easier to discover what&#8217;s new and what is already migrated. I hope that all migrations go smoothly but if they don&#8217;t, this gives you insight into where things might be stuck. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="567" height="1024" src="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-567x1024.png" alt="" class="wp-image-3247968" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-567x1024.png 567w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-443x800.png 443w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-768x1386.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-851x1536.png 851w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news-1135x2048.png 1135w, https://alex.kirk.at/wp-content/uploads/sites/2/2026/03/friends-news.png 1180w" sizes="auto, (max-width: 567px) 100vw, 567px" /></figure>



<p class="wp-block-paragraph">The amount of necessary fundamental changes and migrations made this release somewhat risky and was a reason for the long time since the last release. I am hoping that with these changes now shipped, I can provide more frequent updates again!</p>



<p class="wp-block-paragraph">Oh, I also shipped a new version of the <a href="https://wordpress.org/plugins/enable-mastodon-apps/">Enable Mastodon Apps plugin</a> (1.5.0) which makes use of some of the taxonomy changes in Friends that now allow to distinguish between mentions and direct messages, and there should be a speed-up in many endpoints, especially the notifications endpoint.</p>



<p class="wp-block-paragraph">Enjoy this new release, which I hope will make it easier and more feasible to use <a href="https://alex.kirk.at/2024/06/13/your-wordpress-as-your-personal-mastodon-instance/">Your WordPress as Your Personal Mastodon Instance</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2026/03/25/friends-4-0/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>WordPress Development Without a Computer</title>
		<link>https://alex.kirk.at/2025/11/29/wordpress-development-without-a-computer/</link>
					<comments>https://alex.kirk.at/2025/11/29/wordpress-development-without-a-computer/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Sat, 29 Nov 2025 06:27:14 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Playground]]></category>
		<category><![CDATA[playground]]></category>
		<category><![CDATA[Step Library]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2937002</guid>

					<description><![CDATA[With AI coding assistants and WordPress Playground, you can now develop WordPress plugins from your phone. Here's how to set it up.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">You&#8217;re on the train, scrolling through your WordPress site on your phone, and you see an issue that you&#8217;d like to fix, for example improvement to the mobile view. Normally you&#8217;d make a (mental) note and deal with it when you&#8217;re back at your computer.</p>



<p class="wp-block-paragraph">But what if you could just fix it right there?</p>



<p class="wp-block-paragraph">With AI coding assistants that run in the browser—like <a href="https://claude.ai/code">Claude Code</a>, <a href="https://openai.com/codex/">OpenAI Codex</a>, <a href="https://githubnext.com/projects/copilot-workspace">GitHub Copilot Workspace</a>, or similar tools—combined with <a href="https://playground.wordpress.net/">WordPress Playground</a> for testing, you can now do WordPress plugin development without a computer.</p>



<h2 class="wp-block-heading">What It Looks Like</h2>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">AI: I&#8217;ve implemented the fix for you, committed and pushed it to Github. Use this link to <a href="https://playground.wordpress.net/">Test it in WordPress Playground</a>.</p>
</blockquote>



<p class="wp-block-paragraph">This link above just leads to a generic Playground but to give you an idea of the workflow: The AI helps you fix or implement what you asked for and makes the code available in a branch. You&#8217;ll then run/view it via Playground. Here&#8217;s how to set this up:</p>



<h2 class="wp-block-heading">What You Need</h2>



<ul class="wp-block-list">
<li>Your plugin or theme in a GitHub repository,</li>



<li>A web AI coding assistant,</li>



<li>A way to tell the AI how to generate Playground test links that you can click.</li>
</ul>



<p class="wp-block-paragraph">The third part is where the <a href="https://akirk.github.io/playground-step-library/">Playground Step Library</a> comes in.</p>



<h2 class="wp-block-heading">Step 1: Create Your Blueprint</h2>



<p class="wp-block-paragraph">WordPress Playground uses <a href="https://wordpress.github.io/wordpress-playground/blueprints-api/index/">blueprints</a>: JSON configurations that describe what to install and how to set things up. You can install plugins, themes, configure settings, import content, and more. Writing these by hand is a little cumbersome, so I built the Step Library as a visual tool to assemble blueprints step by step.</p>



<p class="wp-block-paragraph">The Step Library also provides more steps than Playground offers natively: that&#8217;s where the name comes from. It compiles these custom steps into the native steps that Playground understands. The native steps are powerful but require you to know how to combine them in clever ways; the Step Library&#8217;s <a href="https://github.com/akirk/playground-step-library/tree/main/docs">custom steps</a> make it easier. Examples include <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/addProduct.md">addProduct</a> for WooCommerce, <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/addTemplatePart.md">addTemplatePart</a> for block themes, a <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/debug.md">debug</a> step to enable common debug settings and plugins, or <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/disableWelcomeGuides.md">disableWelcomeGuides</a>.</p>



<p class="wp-block-paragraph">Use <a href="https://akirk.github.io/playground-step-library/?step%5B0%5D=installPlugin">this special link to the Step Library</a> to start with an <a href="https://github.com/akirk/playground-step-library/blob/main/docs/steps/installPlugin.md">&#8220;Install Plugin&#8221; step</a>. Paste your HTTPS GitHub repository URL. If you want to test a specific branch, add <code>/tree/branch-name</code> to the URL—but for now, just use your main branch. We&#8217;ll make the branch dynamic later.</p>



<p class="wp-block-paragraph">Add any other steps your testing environment needs: maybe WooCommerce if your plugin integrates with it, or some test content, or specific WordPress settings.</p>



<h2 class="wp-block-heading">Step 2: Generate AI Instructions</h2>



<p class="wp-block-paragraph">Once your blueprint is ready, open the &#8220;Copy/Share&#8221; dropdown and select &#8220;Generate AI Instructions&#8221;. This creates a markdown snippet you can add to your project&#8217;s <code>CLAUDE.md</code>, <code>.github/copilot-instructions.md</code>, or similar AI instruction file:</p>



<figure class="wp-block-image size-full is-resized"><img loading="lazy" decoding="async" width="674" height="568" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/copy-dropdown-menu.png" alt="" class="wp-image-2937025" style="width:271px;height:auto" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/copy-dropdown-menu.png 674w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/copy-dropdown-menu-655x552.png 655w" sizes="auto, (max-width: 674px) 100vw, 674px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="929" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-1024x929.png" alt="" class="wp-image-2937024" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-1024x929.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-655x594.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-768x696.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions-1536x1393.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/11/generate-ai-instructions.png 1630w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">The generated instructions tell the AI to include a Playground testing link at the end of its responses. The branch name in your URL gets replaced with a <code>BRANCH_NAME</code> placeholder, so the AI knows to substitute the actual branch it&#8217;s working on.</p>



<h2 class="wp-block-heading">Step 3: Add to Your Repository</h2>



<p class="wp-block-paragraph">Copy the generated markdown and add it to your AI instruction file. Commit it to your repository. Now any AI assistant that reads these instructions will include Playground links when it makes changes to your code.</p>



<p class="wp-block-paragraph">Bonus: you can also instruct your coding assistant to add such a file to your repo!</p>



<h2 class="wp-block-heading">The Workflow</h2>



<p class="wp-block-paragraph">Here&#8217;s what this looks like in practice:</p>



<ol class="wp-block-list">
<li>Open your AI coding assistant on your phone (or desktop),</li>



<li>Connect to your GitHub repository,</li>



<li>Describe what you want to change or fix,</li>



<li>The AI makes the changes and pushes a branch,</li>



<li>Tap the Playground link in the response,</li>



<li>Test the changes in Playground—if it&#8217;s a private repo, you&#8217;ll authenticate with GitHub here,</li>



<li>If it works, create a PR and merge it—you got to test before even opening the PR.</li>
</ol>



<p class="wp-block-paragraph">It&#8217;s a complete development loop. The AI handles the code, GitHub handles version control, and Playground handles testing. Your phone is just the interface tying it all together.</p>



<h2 class="wp-block-heading">Private Repositories</h2>



<p class="wp-block-paragraph">Until recently, this workflow only worked with public GitHub repositories. I <a href="https://github.com/WordPress/wordpress-playground/pull/2856">submitted a PR to WordPress Playground</a> that adds GitHub OAuth authentication. Now when you load a plugin from a private repository, Playground prompts you to authenticate, and then it works just like public repos.</p>



<h2 class="wp-block-heading">Beyond Mobile: Preconfigured Test Environments</h2>



<p class="wp-block-paragraph">The mobile workflow is a fun demo, but the same setup is useful on desktop too. The real power is in the preconfigured Playground environments through <a href="https://wordpress.github.io/wordpress-playground/blueprints-api/index/">blueprints</a> (which you can easily create with the <a href="https://akirk.github.io/playground-step-library/">Step Library</a>).</p>



<p class="wp-block-paragraph">Say your plugin integrates with <a href="https://woocommerce.com/">WooCommerce</a>. You can create a blueprint that installs WooCommerce, sets up a test product, and installs your plugin from the current branch. Now every Playground link the AI generates loads an environment where you can actually test the integration—not just whether your plugin activates without errors.</p>



<p class="wp-block-paragraph">Or you want to test across different configurations: multisite vs single site, classic editor vs block editor, different PHP versions. Create a blueprint for each scenario, generate AI instructions for each, and you have a test matrix that&#8217;s one click away.</p>



<h2 class="wp-block-heading">GitHub Actions</h2>



<p class="wp-block-paragraph">You can take this further with a <a href="https://wordpress.github.io/wordpress-playground/guides/github-action-pr-preview">GitHub Action that posts a Playground link &#8220;Try it in Playground&#8221; as a comment on every PR</a>. That way anyone reviewing the PR can test the changes without setting up a local environment.</p>



<p class="wp-block-paragraph">The Step Library is available as an <a href="https://www.npmjs.com/package/playground-step-library">npm package</a>, so you can integrate it into your own tooling and CI pipelines.</p>



<h2 class="wp-block-heading">Let AI Create Blueprints for You</h2>



<p class="wp-block-paragraph">Something often overlooked: the Step Library is also useful for getting AI to help you create blueprints in the first place. The native Playground steps are low-level—things like <code>writeFile</code> and <code>runPHP</code>—so AI assistants often don&#8217;t grasp what&#8217;s actually possible with blueprints. The Step Library&#8217;s high-level steps are more intuitive, and with a <a href="https://akirk.github.io/playground-step-library/step-library-schema.json">JSON schema</a> that describes them, AI can easily understand what&#8217;s available and generate useful blueprints.</p>



<h2 class="wp-block-heading">Other New Step Library Features</h2>



<p class="wp-block-paragraph">Some notable other things I added recently:</p>



<p class="wp-block-paragraph"><strong><a href="https://akirk.github.io/playground-step-library/docs/importers#wp-envjson">wp-env.json import</a></strong>: Drop your <code>.wp-env.json</code> into the Step Library and it converts your local dev environment config into a Playground blueprint.</p>



<p class="wp-block-paragraph"><strong><a href="https://akirk.github.io/playground-step-library/docs/importers#plugintheme-urls">GitLab, Bitbucket, and Codeberg support</a></strong>: Not everyone uses GitHub. The Step Library now recognizes repository URLs from these platforms.</p>



<p class="wp-block-paragraph"><strong><a href="https://akirk.github.io/playground-step-library/docs/importers">Paste detection</a></strong>: Paste a plugin URL, some PHP code, or even an existing Playground URL, and the Step Library figures out what it is and creates the right steps.</p>



<h2 class="wp-block-heading">Try It</h2>



<p class="wp-block-paragraph">The <a href="https://akirk.github.io/playground-step-library/">Playground Step Library</a> is where you can create your blueprint and generate AI instructions.</p>



<p class="wp-block-paragraph">I&#8217;ve found myself using this on the train, in waiting rooms, wherever I have a few minutes and an idea I want to try. It&#8217;s not how I imagined WordPress development would work, but it does.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/11/29/wordpress-development-without-a-computer/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title></title>
		<link>https://alex.kirk.at/2025/11/12/2910911/</link>
					<comments>https://alex.kirk.at/2025/11/12/2910911/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Wed, 12 Nov 2025 15:34:32 +0000</pubDate>
				<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2910911</guid>

					<description><![CDATA[I&#8217;ll speak about Telex and how to use Playground in your AI workflow at today&#8217;s WordPress Vienna meetup!]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I&#8217;ll speak about <a href="https://telex.automattic.ai/">Telex</a> and how to use Playground in your AI workflow at <a href="https://www.meetup.com/vienna-wordpress-meetup/events/311518999/">today&#8217;s WordPress Vienna meetup</a>!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/11/12/2910911/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>status</friends:post-format>
	</item>
		<item>
		<title>Adapting Tools to Your Needs with AI</title>
		<link>https://alex.kirk.at/2025/10/14/adapting-tools-to-your-needs-with-ai/</link>
					<comments>https://alex.kirk.at/2025/10/14/adapting-tools-to-your-needs-with-ai/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Tue, 14 Oct 2025 08:54:06 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[adb]]></category>
		<category><![CDATA[Claude Code]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2828314</guid>

					<description><![CDATA[These days you can just fix and adapt incomplete tools that you encounter with AI like Claude Code!]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In past years, as a developer, for some features or the early stages of software, writing down the code felt like a chore. You knew what to do and you had to tediously spell it out. Of course, with AI tools like <a href="https://www.claude.com/product/claude-code">Claude Code</a> (which I like in particular, the CLI approach appeals to me) this now is vastly better, and actually it&#8217;s quite easy to accidentally take it too far.</p>



<p class="wp-block-paragraph">But here, I want to talk about something different: It happens that you search for a tool and then you come across something that almost does what you want, but not quite.</p>



<p class="wp-block-paragraph">Before AI programming tools, you either had to be lucky to know the software stack, or it must be a really important problem to you that you would try to understand the codebase and make the modification you need.</p>



<p class="wp-block-paragraph">Today, I can just use Claude Code to modify any tool how I like. So instead of turning away in frustration, I just ask Claude to help me fix what doesn&#8217;t work for me. How great is that?</p>



<p class="wp-block-paragraph">A recent example for me has been transferring files to my Android Phone. <a href="https://openmtp.ganeshrvel.com/">OpenMTP</a> exists but to me it has proven to be highly unrealiable, you need to remember to not have Preview open in macOS for it to work, and recently it didn&#8217;t complete a copy process but didn&#8217;t tell me about it. I only found out on the go that some files had not been copied.</p>



<p class="wp-block-paragraph">So I realized, that I can use <code>adb</code> to push files to my phone using the debug mode. It&#8217;s very niche, I know, but it works. And then I realized a little UI would be nice, and I discovered <a href="https://github.com/darkhz/adbtuifm">darkhz&#8217;s adbtuifm</a>. A tool written in Go but only tested on Linux, a file manager like Total Commander for the CLI that uses <code>adb</code> in the background.</p>



<p class="wp-block-paragraph">And indeed, it didn&#8217;t really work well on macOS CLI. The left side appeared empty.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="976" height="511" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before.png" alt="" class="wp-image-2828419" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before.png 976w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before-655x343.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-before-768x402.png 768w" sizes="auto, (max-width: 976px) 100vw, 976px" /><figcaption class="wp-element-caption">Hardly anything readable and the left side empty</figcaption></figure>



<p class="wp-block-paragraph">But this is what it looks like today:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="778" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-1024x778.png" alt="" class="wp-image-2828393" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-1024x778.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-655x498.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-768x584.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm-1536x1167.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/10/adbtuifm.png 1950w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">My updated version of <a href="https://github.com/akirk/adbtuifm">adbtuifm</a></figcaption></figure>



<p class="wp-block-paragraph">So I forked it and <a href="https://github.com/darkhz/adbtuifm/compare/master...akirk:adbtuifm:main">adapted it to my needs</a>:</p>



<ul class="wp-block-list">
<li>It <a href="https://github.com/darkhz/adbtuifm/commit/e2d75de31b06cb463f8b2e5e7254920a036ceda0">now uses the current directory</a> instead of the non-existent-on-macOS <code>/home</code>.</li>



<li><a href="https://github.com/darkhz/adbtuifm/commit/df5eafb6ecfb0e6af09b339d2428a633555adc3a">Fixed the colors</a> so that things are also readable in light mode.</li>



<li><a href="https://github.com/darkhz/adbtuifm/commit/d92b3224f5058d5b32af00fffd2d091c3d231111">Introduced an ADB log pane</a> to see what&#8217;s going on behind the scenes.</li>



<li>It now <a href="https://github.com/darkhz/adbtuifm/commit/d0fb25fe438f4fec12119e9caeaf78d707d1d031">shows size and last modification dates</a>.</li>



<li>Introduced <a href="https://github.com/darkhz/adbtuifm/commit/77731d3293b14850250707d82d3d83b904d89650">history navigation</a>.</li>



<li>Even <a href="https://github.com/darkhz/adbtuifm/commit/05344a29073b6bc18f1856c4f2d70add943d55ea">fixed a (tricky?) UI hang</a> when deleting files.</li>
</ul>



<p class="wp-block-paragraph">The most important change for me probably was the first one, and, ok, I could have probably just changed the hardcoded string myself. </p>



<p class="wp-block-paragraph">But it was such a joy to continue and make the tool nicer to use! Also, I don&#8217;t think I could have fixed that hanging UI before wasting too much time.</p>



<p class="wp-block-paragraph">You can <a href="https://github.com/akirk/adbtuifm">try my version</a>, and maybe fork it and add more things you like yourself? I could send back a PR but maybe I won&#8217;t do it this time because my changes are opinionated and the repo <a href="https://github.com/darkhz/adbtuifm">seems abandoned</a> with the last change in 2022.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/10/14/adapting-tools-to-your-needs-with-ai/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Proposal: an Interactive Mode for phpcbf</title>
		<link>https://alex.kirk.at/2025/09/29/proposal-an-interactive-mode-for-phpcbf/</link>
					<comments>https://alex.kirk.at/2025/09/29/proposal-an-interactive-mode-for-phpcbf/#respond</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Mon, 29 Sep 2025 12:05:06 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2814422</guid>

					<description><![CDATA[It can be very time consuming to resolve issues detected by PHP Code Sniffer. An interactive mode for phpcbf could make things much faster!]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Did you ever get a little annoyed at <code>phpcs</code>? Maybe you&#8217;re like me: I like the idea of <a href="https://github.com/phpcsstandards/PHP_CodeSniffer">PHP Code Sniffer</a> (phpcs), but I think the user experience has room for improvement:</p>



<p class="wp-block-paragraph">Especially when trying to get larger amounts of PHP code to comply with the coding standards, it feels like this tool just scolds you and all you can do is to diligently work away on each and every violation that it discovers.</p>



<p class="wp-block-paragraph">And you might have gotten yourself into such a situation because <a href="https://github.com/akirk/friends/pull/329">you realized well into the project that you forgot an important ruleset</a>, or when you&#8217;re merging codebases.</p>



<h3 class="wp-block-heading">Sniffs are Opinions</h3>



<p class="wp-block-paragraph">One important thing that we tend to forget: often we are in a position where we can actually make the decisions which rules to follow and which not. A ruleset prepared by someone else might contain things we disagree with. Thus phpcs contains the ability to exclude sniffs via its phpcs.xml configuration file, and I think it&#8217;s ok to make use of that. But also, I think that phpcs could be more helpful to you in doing so.</p>



<p class="wp-block-paragraph">When you encounter such an overly eager ruleset, you might complain that the ruleset itself should be updated. But maybe you are not in a position to fight that battle, so you can just find a solution for yourself.</p>



<h3 class="wp-block-heading">phpcbf can help fix things</h3>



<p class="wp-block-paragraph">The PHP Code Sniffer project comes with two main executables: <code>phpcs</code>, and <code>phpcbf</code>. While <code>phpcs</code> complains, <code>phpcbf</code> tries to help you. Sniffs can provide auto-fixers for violations they encounter and <code>phpcbf</code> applies them for you. But oftentimes it seems like there should be an auto-fixer but in the end, you have to fix it yourself.</p>



<p class="wp-block-paragraph">A side-note here: maintaining the phpcs project is certainly not a piece of cake since it&#8217;s a project heavily exposed to opinion. Many things have to be considered, and it looks like there has been agreement that an auto-fixer can only be added if there is a single and clear solution to the problem.</p>



<p class="wp-block-paragraph">Thus, there are a number of sniffs where the resolution of a violation needs a user decision. This decision could be complex, like you need to rearrange code, or add something that you forgot (like a type for a parameter). But I believe there are also decisions to make where it&#8217;s a matter of choosing between several options.</p>



<h3 class="wp-block-heading">User Decision Required</h3>



<p class="wp-block-paragraph">One example of this is <code>Squiz.Commenting.InlineComment.InvalidEndChar</code>: &#8220;Inline comments must end in full-stops, exclamation marks, or question marks.&#8221; Let&#8217;s not argue about its validity but about the reason it cannot be auto-fixed: There are multiple valid end chars and an auto-fixer cannot know which one is the right one here.</p>



<p class="wp-block-paragraph">So, what happens if we make <code>phpcbf</code> interactive, so that it can ask the user to select one of the potential fixes, and then just goes ahead and makes them?</p>



<p class="wp-block-paragraph">Or, if you realize that you disagree with this sniff: what if <code>phpcbf</code> will just quickly add an <code>&lt;exclude ref="Sniff.Name"/&gt;</code> to your <code>phpcs.xml</code>? Or it could help you just disable the rule for the file? Or just ignore this line?</p>



<p class="wp-block-paragraph">Many IDEs actually already have some of these ways of dealing with violations, <a href="https://www.jetbrains.com/help/phpstorm/using-php-code-sniffer.html#fixing-issues">either natively</a> or <a href="https://github.com/sdobreff/vscode-php-resolver/blob/main/README.md#phpcs-rules-ignore">through an extension</a>. Bringing them to phpcbf itself would make this available to a wider audience and solutions could be baked in to sniffs.</p>



<h3 class="wp-block-heading">Interactive Mode</h3>



<p class="wp-block-paragraph">All of these thoughts culminate in this idea to make <code>phpcbf</code> interactive. I didn&#8217;t know until recently that phpcs has an interactive mode, too. But all it does is to process a file and pauses to allow the user to edit the file, and then to process it again. It assists you in checking, but not in fixing.</p>



<p class="wp-block-paragraph">So, here is how this could work. Let&#8217;s assume this <code>test.php</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php

//helo
class test
{
echo &#039;hello&#039;;
}
</pre></div>


<p class="wp-block-paragraph">This file has some problems as <code>phpcs</code> tells you (the selection of Sniffs here is a bit arbitrary but to show the variety of options we&#8217;ll face):</p>


<div class="wp-block-syntaxhighlighter-code ">
\e[1mFILE: test.php\e[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
\e[1mFOUND 6 ERRORS AFFECTING 4 LINES\e[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
 1 | \e[31mERROR\e[0m | [ ] You must use &#8220;/**&#8221; style comments for a file comment
 3 | \e[31mERROR\e[0m | [x] No space found before comment text; expected &#8220;// helo&#8221; but found &#8220;//helo&#8221;
 3 | \e[31mERROR\e[0m | [ ] Inline comments must start with a capital letter
 3 | \e[31mERROR\e[0m | [ ] Inline comments must end in full-stops, exclamation marks, or question marks
 4 | \e[31mERROR\e[0m | [ ] Test name must begin with a capital letter
 6 | \e[31mERROR\e[0m | [x] Line indented incorrectly; expected at least 4 spaces, found 0
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
\e[1mPHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY\e[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

</div>


<p class="wp-block-paragraph">As you can see, some violations can be fixed, most cannot. The reason for those is that there is no auto-fixer implemented for them, and often the reason is that there is no one-and-only-way to fix this.</p>



<p class="wp-block-paragraph">So let&#8217;s see how interactive mode would work here. In this first case I&#8217;d like to show a situation where there is no auto-fixer available. These would be the options:</p>


<div class="wp-block-syntaxhighlighter-code ">
[1mPHPCBF INTERACTIVE MODE &#8211; test.php[0m

[33mERRORS[0m at line 1, column 6:
  You must use &#8220;/**&#8221; style comments for a file comment
  Sniff: PEAR.Commenting.FileComment.WrongStyle
  [31m(Not auto-fixable)[0m

      [33m  1> &lt;?php[0m
      [90m  2  [0m
      [90m  3  //helo[0m
Choose an action:
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: edit):
</div>


<p class="wp-block-paragraph">Now let&#8217;s look at a case where an auto-fixer is available. In non-interactive mode, <code>phpcbf</code> would just fix it, but here you have the option to skip it, too. It would be nice if it even could preview the auto-fix:</p>


<div class="wp-block-syntaxhighlighter-code ">
[33mERRORS[0m at line 6, column 1:
  Line indented incorrectly; expected at least 4 spaces, found 0
  Sniff: Generic.WhiteSpace.ScopeIndent.Incorrect
  [32m(Auto-fixable)[0m

      [90m  4  class test[0m
      [90m  5  {[0m
      [31m  6- echo &#8216;hello&#8217;;[0m
      [32m  6+      echo &#8216;hello&#8217;;[0m
      [90m  7  }[0m
      [90m  8  [0m
Choose an action:
  [f] Fix automatically
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: auto-fix):
</div>


<p class="wp-block-paragraph">Now let&#8217;s look come back to our example from above where it seems like an auto-fixer could exist but it does not because there are multiple ways to fix it. For this one, we&#8217;d have an interactive fixer that gives the user the choice how to fix it:</p>


<div class="wp-block-syntaxhighlighter-code ">
[33mERRORS[0m at line 3, column 1:
  Inline comments must end in full-stops, exclamation marks, or question marks
  Sniff: Squiz.Commenting.InlineComment.InvalidEndChar
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Append a .
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo.[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [2] Append a !
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo![0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [3] Append a ?
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo?[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [4] Remove comment
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m

Choose an action:
  [1] Apply: Append a .
  [2] Apply: Append a !
  [3] Apply: Append a ?
  [4] Apply: Remove comment
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Append a .&#8221;):
</div>


<p class="wp-block-paragraph">One could argue that you can do all of this today but I think with such an interactive mode we can relieve much of the pain it causes to get a code base to comply by streamlining what you need to do already today anyway: go through each violation and try to fix it.</p>



<p class="wp-block-paragraph">Some of the choices I haven&#8217;t described yet:</p>



<ul class="wp-block-list">
<li><code>i</code> would just append a <code>// phpcs:ignore Sniff.Name</code> to the line.</li>



<li><code>d</code> would add a <code>// phpcs:disable Sniff.Name</code> at the beginning of the file.</li>



<li><code>p</code> would add an <code>&lt;exclude ref="Sniff.Name"/&gt;</code> to your <code>phpcs.xml</code>.</li>



<li><code>e</code> would open an editor at the line of the code</li>
</ul>



<p class="wp-block-paragraph">In summary, this is a proposal to improve the user experience. I think this could transform an experience where <code>phpcs</code> is the tool that scolds you, to the tool that assists you in unifying a codebase to certain standards.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Finally, expand this to see the whole run-down of an interactive <code>phpcbf -a</code> session.</summary><div class="wp-block-syntaxhighlighter-code ">
❯ bat test.php
[38;5;246m───────┬────────────────────────────────────────────────────────────────────────[0m
       [38;5;246m│ [0mFile: [1mtest.php[0m
[38;5;246m───────┼────────────────────────────────────────────────────────────────────────[0m
[38;5;246m   1[0m   [38;5;246m│[0m [38;5;231m&lt;?php[0m
[38;5;246m   2[0m   [38;5;246m│[0m 
[38;5;246m   3[0m   [38;5;246m│[0m [38;5;242m//[0m[38;5;242mhelo[0m
[38;5;246m   4[0m   [38;5;246m│[0m [38;5;149mclass[0m[38;5;231m [0m[4;38;5;81mtest[0m
[38;5;246m   5[0m   [38;5;246m│[0m [38;5;231m{[0m
[38;5;246m   6[0m   [38;5;246m│[0m [38;5;167mecho[0m[38;5;231m [0m[38;5;186m&#8217;[0m[38;5;186mhello[0m[38;5;186m&#8217;[0m[38;5;231m;[0m
[38;5;246m   7[0m   [38;5;246m│[0m [38;5;231m}[0m
[38;5;246m───────┴────────────────────────────────────────────────────────────────────────[0m
❯ ./bin/phpcs test.php

[1mFILE: test.php[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mFOUND 6 ERRORS AFFECTING 4 LINES[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
 1 | [31mERROR[0m | [ ] You must use &#8220;/**&#8221; style comments for a file comment
 3 | [31mERROR[0m | [x] No space found before comment text; expected &#8220;// helo&#8221; but found &#8220;//helo&#8221;
 3 | [31mERROR[0m | [ ] Inline comments must start with a capital letter
 3 | [31mERROR[0m | [ ] Inline comments must end in full-stops, exclamation marks, or question marks
 4 | [31mERROR[0m | [ ] Test name must begin with a capital letter
 6 | [31mERROR[0m | [x] Line indented incorrectly; expected at least 4 spaces, found 0
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mPHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

❯ ./bin/phpcbf -a test.php
[1mPHPCBF INTERACTIVE MODE &#8211; test.php[0m

[33mERRORS[0m at line 1, column 6:
  You must use &#8220;/**&#8221; style comments for a file comment
  Sniff: PEAR.Commenting.FileComment.WrongStyle
  [31m(Not auto-fixable)[0m

      [33m  1> &lt;?php[0m
      [90m  2  [0m
      [90m  3  //helo[0m
Choose an action:
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: edit): i
Added phpcs:ignore comment to line 1

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 6, column 1:
  Line indented incorrectly; expected at least 4 spaces, found 0
  Sniff: Generic.WhiteSpace.ScopeIndent.Incorrect
  [32m(Auto-fixable)[0m

      [90m  4  class test[0m
      [90m  5  {[0m
      [31m  6- echo &#8216;hello&#8217;;[0m
      [32m  6+     echo &#8216;hello&#8217;;[0m
      [90m  7  }[0m
      [90m  8  [0m
Choose an action:
  [f] Fix automatically
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: auto-fix):
Auto-fixing&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 3, column 1:
  No space found before comment text; expected &#8220;// helo&#8221; but found &#8220;//helo&#8221;
  Sniff: Squiz.Commenting.InlineComment.NoSpaceBefore
  [32m(Auto-fixable)[0m

      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- //helo[0m
      [32m  3+ // helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m
Choose an action:
  [f] Fix automatically
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: auto-fix):
Auto-fixing&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 3, column 1:
  Inline comments must start with a capital letter
  Sniff: Squiz.Commenting.InlineComment.NotCapital
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Suggestion
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // helo[0m
      [32m  3+ // Helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m

Choose an action:
  [1] Apply: Suggestion
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Capitalize first letter&#8221;):
Applying option 1&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 3, column 1:
  Inline comments must end in full-stops, exclamation marks, or question marks
  Sniff: Squiz.Commenting.InlineComment.InvalidEndChar
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Append a .
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo.[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [2] Append a !
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo![0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [3] Append a ?
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [32m  3+ // Helo?[0m
      [90m  4  class test[0m
      [90m  5  {[0m
  [4] Remove comment
      [90m  1  &lt;?php[0m
      [90m  2  [0m
      [31m  3- // Helo[0m
      [90m  4  class test[0m
      [90m  5  {[0m

Choose an action:
  [1] Apply: Append a .
  [2] Apply: Append a !
  [3] Apply: Append a ?
  [4] Apply: Remove comment
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Append a .&#8221;): 2
Fixing with option 2&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
[33mERRORS[0m at line 4, column 7:
  Test name must begin with a capital letter
  Sniff: PEAR.NamingConventions.ValidClassName.StartWithCapital
  [36m(Interactive fixes available)[0m

[1mInteractive Fix Options:[0m
  [1] Suggestion
      [90m  2  [0m
      [90m  3  // Helo![0m
      [31m  4- class test[0m
      [32m  4+ class Test[0m
      [90m  5  {[0m
      [90m  6      echo &#8216;hello&#8217;;[0m

Choose an action:
  [1] Apply: Suggestion
  [i] Add a phpcs:ignore to this line (phpcs:ignore)
  [d] Disable this sniff for this file (phpcs:disable)
  [p] Project-wide: exclude this sniff in phpcs.xml
  [e] Edit the file manually
  [s] Skip this violation
  [q] Quit
Action (default: 1 &#8220;Capitalize first letter&#8221;):
Applying option 1&#8230;
[32mFixed![0m

&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;

[1mPHPCBF RESULT SUMMARY[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mFILE                                                  FIXED  REMAINING[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
test.php                                              5      0
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mA TOTAL OF 5 ERRORS WERE FIXED IN 1 FILE[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

❯ bat test.php
[38;5;246m───────┬────────────────────────────────────────────────────────────────────────[0m
       [38;5;246m│ [0mFile: [1mtest.php[0m
[38;5;246m───────┼────────────────────────────────────────────────────────────────────────[0m
[38;5;246m   1[0m   [38;5;246m│[0m [38;5;231m&lt;?php[0m[38;5;231m [0m[38;5;242m//[0m[38;5;242m phpcs:ignore PEAR.Commenting.FileComment.WrongStyle[0m
[38;5;246m   2[0m   [38;5;246m│[0m 
[38;5;246m   3[0m   [38;5;246m│[0m [38;5;242m//[0m[38;5;242m Helo![0m
[38;5;246m   4[0m   [38;5;246m│[0m [38;5;149mclass[0m[38;5;231m [0m[4;38;5;81mTest[0m
[38;5;246m   5[0m   [38;5;246m│[0m [38;5;231m{[0m
[38;5;246m   6[0m   [38;5;246m│[0m [38;5;231m    [0m[38;5;167mecho[0m[38;5;231m [0m[38;5;186m&#8217;[0m[38;5;186mhello[0m[38;5;186m&#8217;[0m[38;5;231m;[0m
[38;5;246m   7[0m   [38;5;246m│[0m [38;5;231m}[0m
[38;5;246m───────┴────────────────────────────────────────────────────────────────────────[0m

</div>


<p class="wp-block-paragraph">For comparison, this is what regular mode produces:</p>


<div class="wp-block-syntaxhighlighter-code ">
❯ ./bin/phpcbf test.php

[1mPHPCBF RESULT SUMMARY[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mFILE                                                  FIXED  REMAINING[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
test.php                                              2      4
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-
[1mA TOTAL OF 2 ERRORS WERE FIXED IN 1 FILE[0m
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-

❯ bat test.php
[38;5;246m───────┬────────────────────────────────────────────────────────────────────────[0m
       [38;5;246m│ [0mFile: [1mtest.php[0m
[38;5;246m───────┼────────────────────────────────────────────────────────────────────────[0m
[38;5;246m   1[0m   [38;5;246m│[0m [38;5;231m&lt;?php[0m
[38;5;246m   2[0m   [38;5;246m│[0m 
[38;5;246m   3[0m   [38;5;246m│[0m [38;5;242m//[0m[38;5;242m helo[0m
[38;5;246m   4[0m   [38;5;246m│[0m [38;5;149mclass[0m[38;5;231m [0m[4;38;5;81mtest[0m
[38;5;246m   5[0m   [38;5;246m│[0m [38;5;231m{[0m
[38;5;246m   6[0m   [38;5;246m│[0m [38;5;231m    [0m[38;5;167mecho[0m[38;5;231m [0m[38;5;186m&#8217;[0m[38;5;186mhello[0m[38;5;186m&#8217;[0m[38;5;231m;[0m
[38;5;246m   7[0m   [38;5;246m│[0m [38;5;231m}[0m
[38;5;246m───────┴────────────────────────────────────────────────────────────────────────[0m

</div></details>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">You can find <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1285">the issue I created about this in the PHP CodeSniffer repo</a>, and <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/compare/4.x...akirk:PHP_CodeSniffer:phpcbf-interactive">my implementation on Github</a>. This is not yet a PR because <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/4.x/.github/CONTRIBUTING.md#requestingsubmitting-new-features">they prefer to have a discussion it first</a> but I worked on an implementation already so that you can experience how it feels to use it and don&#8217;t just have to imagine it. Find the instructions to do so <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer/issues/1285">on the bottom of the issue</a>.</p>



<p class="wp-block-paragraph">PS: to make the terminal output look well in this post, I have made this <a href="https://github.com/akirk/syntaxhighlighter-ansi">syntaxhighlighter-ansi</a> plugin for the <a href="https://wordpress.com/plugins/syntaxhighlighter">SyntaxHighlighter Evolved plugin</a> for WordPress that will interpret the ANSI escape sequences from the terminal and convert it to colorful output like you can see above.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/09/29/proposal-an-interactive-mode-for-phpcbf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>npm install playground-step-library</title>
		<link>https://alex.kirk.at/2025/09/05/npm-install-playground-step-library/</link>
					<comments>https://alex.kirk.at/2025/09/05/npm-install-playground-step-library/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Fri, 05 Sep 2025 14:14:57 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Playground]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2768972</guid>

					<description><![CDATA[I have updated my Playground Step Library (which I had written about before)–the tool that allows you to use more advanced steps in WordPress Playground–so that it can now also be used programmatically: It is now an npm package: playground-step-library. Behind the scenes this actually dominoed into migrating it to TypeScript and restructuring the code [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I have updated <a href="https://github.com/akirk/playground-step-library/" data-type="post" data-id="1996330">my Playground Step Library</a> (<a href="https://alex.kirk.at/2024/07/11/wordpress-playground-step-library/" data-type="post" data-id="1996330">which I had written about before</a>)–the tool that allows you to use <a href="https://github.com/akirk/playground-step-library/tree/main/docs">more advanced steps</a> in <a href="https://playground.wordpress.net/">WordPress Playground</a>–so that it can now also be used programmatically: It is now an npm package: <a href="https://www.npmjs.com/package/playground-step-library">playground-step-library</a>.</p>



<p class="wp-block-paragraph">Behind the scenes this actually <a href="https://github.com/akirk/playground-step-library/pull/5">dominoed into</a> migrating it to TypeScript and restructuring the code so that it now both powers the <a href="https://akirk.github.io/playground-step-library/">Web UI</a> and the npm package.</p>



<p class="wp-block-paragraph">Having those custom steps available now makes even more sense that the <a href="https://www.npmjs.com/package/@wp-playground/cli">Playground CLI</a> is production ready and you can use it for things like testing your WordPress plugin with Playwright, see this presentation <a href="https://wordpress.tv/2025/06/07/building-automated-tests-with-wordpress-playground/">Building Automated Tests with WordPress Playground</a> from WordCamp Europe 2025 by my colleague <a href="https://github.com/bgrgicak/">Berislav &#8220;Bero&#8221; Grigicak</a>.</p>



<p class="wp-block-paragraph">In this example you can see a blueprint JSON that contains steps <code>setSiteName</code> and <code>addPage</code> that <a href="https://wordpress.github.io/wordpress-playground/blueprints/steps/#">don&#8217;t exist in the library of steps of Playground</a>. At the time of writing there are <a href="https://github.com/akirk/playground-step-library/tree/main/docs#custom-steps">36 custom steps</a> with the goal of making it easier to do things that can be done with a blueprint already but need some complexity. See in the example below how creating a page can be done with <code>runPHP</code> and <code>wp_insert_post</code> but it&#8217;s visually easier with a step <code>addPage</code>.</p>



<pre class="wp-block-preformatted">import PlaygroundStepLibrary from 'playground-step-library';<br>const compiler = new PlaygroundStepLibrary();<br><br>const blueprint = {<br>    steps: [<br>        {<br>            step: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-pale-pink-color">setSiteName</mark>',<br>            sitename: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-purple-color">My Site</mark>',<br>            tagline: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-orange-color">A WordPress Playground demo</mark>'<br>        },<br>        {<br>            step: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">addPage</mark>',<br>            title: '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-green-cyan-color">Welcome</mark>',<br>            content: '&lt;p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-amber-color">Welcome to my site!</mark>&lt;/p>'<br>        }<br>    ]<br>};<br><br>const compiledBlueprint = compiler.compile(blueprint);<br>console.log(compiledBlueprint);</pre>



<p class="wp-block-paragraph">Which turns this into a valid blueprint:</p>



<pre class="wp-block-preformatted">{<br>  "steps": [<br>    {<br>      "step": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-pale-pink-color">setSiteOptions</mark>",<br>      "options": {<br>        "blogname": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-purple-color">My Site</mark>",<br>        "blogdescription": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-orange-color">A WordPress Playground demo</mark>"<br>      }<br>    },<br>    {<br>      "step": "<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">runPHP</mark>",<br>      "code": "\n&lt;?php require_once '/wordpress/wp-load.php';\n$page_args = array(\n\t'post_type'    => 'page',\n\t'post_status'  => 'publish',\n\t'post_title'   => '<mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-green-cyan-color">Welcome</mark>',\n\t'post_content' => '&lt;p><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-luminous-vivid-amber-color">Welcome to my site!</mark>&lt;/p>',\n);\n$page_id = <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">wp_insert_post</mark>( $page_args );"<br>    }<br>  ]<br>}</pre>



<p class="wp-block-paragraph">You can then pass this blueprint to playground CLI to run it (<a href="https://github.com/fellyph/playwright-testing-plugin/tree/main/demos">see other demos</a> by my colleague <a href="https://blog.fellyph.com.br/">Fellyph</a>):</p>



<pre class="wp-block-code"><code>import { runCLI, RunCLIServer } from '@wp-playground/cli';
await runCLI({
  command: 'server',
  login: true,
  blueprint: compiledBlueprint
});</code></pre>



<p class="wp-block-paragraph">You can also <a href="https://playground.wordpress.net/?blueprint-url=data:application/json;base64,eyJzdGVwcyI6W3sic3RlcCI6InNldFNpdGVPcHRpb25zIiwib3B0aW9ucyI6eyJibG9nbmFtZSI6Ik15IFNpdGUiLCJibG9nZGVzY3JpcHRpb24iOiJBIFdvcmRQcmVzcyBzaXRlIn19LHsic3RlcCI6InJ1blBIUCIsImNvZGUiOiI8P3BocCByZXF1aXJlX29uY2UgJy93b3JkcHJlc3Mvd3AtbG9hZC5waHAnO1xuJHBhZ2VfYXJncyA9IGFycmF5KFxuJ3Bvc3RfdHlwZScgICAgPT4gJ3BhZ2UnLFxuJ3Bvc3Rfc3RhdHVzJyAgPT4gJ3B1Ymxpc2gnLFxuJ3Bvc3RfdGl0bGUnICAgPT4gJ1dlbGNvbWUnLFxuJ3Bvc3RfY29udGVudCcgPT4gJzxwPldlbGNvbWUgdG8gbXkgc2l0ZSE8L3A%2BJyxcbik7XG4kcGFnZV9pZCA9IHdwX2luc2VydF9wb3N0KCAkcGFnZV9hcmdzICk7dXBkYXRlX29wdGlvbiggJ3BhZ2Vfb25fZnJvbnQnLCAkcGFnZV9pZCApO3VwZGF0ZV9vcHRpb24oICdzaG93X29uX2Zyb250JywgJ3BhZ2UnICk7In1dfQ%3D%3D">conveniently try it out in WordPress Playground with this link</a> (and also <a href="https://akirk.github.io/playground-step-library/#eyJzdGVwcyI6W3sic3RlcCI6InNldFNpdGVOYW1lIiwidmFycyI6eyJzaXRlbmFtZSI6Ik15IFNpdGUiLCJ0YWdsaW5lIjoiQSBXb3JkUHJlc3Mgc2l0ZSJ9fSx7InN0ZXAiOiJhZGRQYWdlIiwidmFycyI6eyJwb3N0VGl0bGUiOiJXZWxjb21lIiwicG9zdENvbnRlbnQiOiI8cD5XZWxjb21lIHRvIG15IHNpdGUhPC9wPiIsImhvbWVwYWdlIjp0cnVlfX1dfQ==">view in the Step Library UI</a>).</p>



<p class="wp-block-paragraph">Finally, in the repo there are <a href="https://github.com/akirk/playground-step-library/tree/main/examples">a number of examples</a> that you can browse and I created a little screen recording of a few of them:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="800" height="661" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/09/playground-step-library-examples.gif" alt="" class="wp-image-2769055"/></figure>



<p class="wp-block-paragraph">Happy coding!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/09/05/npm-install-playground-step-library/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
		<item>
		<title>Can&#8217;t Follow You!</title>
		<link>https://alex.kirk.at/2025/06/19/cant-follow-you/</link>
					<comments>https://alex.kirk.at/2025/06/19/cant-follow-you/#comments</comments>
		
		<dc:creator><![CDATA[Alex Kirk]]></dc:creator>
		<pubDate>Thu, 19 Jun 2025 05:53:54 +0000</pubDate>
				<category><![CDATA[Fediverse]]></category>
		<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">https://alex.kirk.at/?p=2605214</guid>

					<description><![CDATA[So, I created this little website https://cantfollowyou.kirk.at/ as something that you can send to people who don&#8217;t realize that they are on a closed network and what it means to others. A bit like Let me Google that for you but for the Fediverse. Here is the backstory, and some details around it: I attended [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">So, I created this little website <a href="https://cantfollowyou.kirk.at/">https://cantfollowyou.kirk.at/</a> as something that you can send to people who don&#8217;t realize that they are on a closed network and what it means to others. A bit like <a href="https://letmegooglethat.com/">Let me Google that for you</a> but for the Fediverse. Here is the backstory, and some details around it:</p>



<p class="wp-block-paragraph">I attended (German-spoken) <a href="https://graz.fedi.camp/">FediCamp Graz 2025</a> last Saturday (see <a href="https://wittenbrink.net/das-erste-grazer-fedicamp/">Heinz Wittenbrink&#8217;s summary in German</a>) where we discussed a plethora of topics around the Fediverse, barcamp-style.</p>



<p class="wp-block-paragraph">One question that we discussed and that has been bugging me for a long time, is why people are quite unwilling to switch to federated, open networks.</p>



<p class="wp-block-paragraph">One reason is certainly is inertia. I guess it&#8217;s a human property to stick with what you know. Also change means work.</p>



<p class="wp-block-paragraph">Another reason is ignorance. You know, like &#8220;bliss.&#8221; It can be comforting to focus on the <a href="https://alex.kirk.at/2025/04/24/wordpress-as-a-refuge-from-algorithms/" data-type="post" data-id="2491886">good sides of your social consumption and not deal too much with the negative sides</a>.</p>



<p class="wp-block-paragraph">Following a train of thought, I realized that maybe many people don&#8217;t realize that they can&#8217;t be followed by people who are not on their network. And don&#8217;t realize that this is a lock-in by the platform that is not necessary.</p>



<p class="wp-block-paragraph">To combat this, I created a <a href="https://cantfollowyou.kirk.at/">little one-page website</a> (<a href="https://github.com/akirk/cantfollowyou">source on Github</a>, open to PRs!) that is meant as something that you can take and send this URL to a person you&#8217;d like to follow who is on a closed social network.</p>



<figure class="wp-block-image size-large"><a href="https://cantfollowyou.kirk.at/insta/Alex"><img loading="lazy" decoding="async" width="1024" height="816" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-1024x816.png" alt="" class="wp-image-2605220" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-1024x816.png 1024w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-655x522.png 655w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-768x612.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1-1536x1225.png 1536w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-1.png 1598w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">A personalized URL <a href="https://cantfollowyou.kirk.at/insta/Alex">https://cantfollowyou.kirk.at/insta/Alex</a> shows the closed network and it&#8217;s alternative</figcaption></figure>



<p class="wp-block-paragraph">It contains a table of ActivityPub equivalents of social networks (see also my WordCamp Europe 2025 presentation <a href="https://europe.wordcamp.org/2025/session/what-youre-missing-if-you-dont-have-your-own-wordpress/">What you’re missing if you don’t have your own WordPress</a>; <a href="https://alex.kirk.at/wceu2025/" data-type="page" data-id="2551153">slides</a>, <a href="https://wordpress.tv/2025/06/07/what-youre-missing-if-you-dont-have-your-own-wordpress/">video</a>):</p>



<figure class="wp-block-image size-large"><a href="https://cantfollowyou.kirk.at/"><img loading="lazy" decoding="async" width="806" height="1024" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-806x1024.png" alt="" class="wp-image-2605221" srcset="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-806x1024.png 806w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-630x800.png 630w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-768x976.png 768w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table-1209x1536.png 1209w, https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-table.png 1420w" sizes="auto, (max-width: 806px) 100vw, 806px" /></a></figure>



<p class="wp-block-paragraph">At the bottom of the page you can customize it:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="679" height="55" src="https://alex.kirk.at/wp-content/uploads/sites/2/2025/06/cantfollowyou-enter.gif" alt="" class="wp-image-2605222"/></figure>



<p class="wp-block-paragraph">Probably this is not going to change the needle significantly, but I see this as a little contribution to enable raising awareness about the problem. The decentralized fediverse surely has a steeper learning curve because you need to make a choice before you start. But I think it&#8217;s worth it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://alex.kirk.at/2025/06/19/cant-follow-you/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<friends:post-format>standard</friends:post-format>
	</item>
	</channel>
</rss>
