<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="https://riceball.com/wp-content/plugins/pretty-rss-feeds/xslt/pretty-feed.xsl" type="text/xsl" media="screen" ?><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/"
	>

<channel>
	<title>WordPress - 🍙</title>
	<atom:link href="https://riceball.com/category/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://riceball.com</link>
	<description></description>
	<lastBuildDate>Sun, 18 Oct 2026 20:05:54 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.4</generator>

<image>
	<url>https://riceball.com/wp-content/uploads/sites/2/2025/10/onigiri-150x150.png</url>
	<title>WordPress - 🍙</title>
	<link>https://riceball.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Thaura &#038; WordPress: layout advice chatbot</title>
		<link>https://riceball.com/2026/10/08/thaura-wordpress-layout-advice-chatbot/</link>
					<comments>https://riceball.com/2026/10/08/thaura-wordpress-layout-advice-chatbot/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 09 Oct 2026 03:55:48 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Prompts]]></category>
		<category><![CDATA[Thaura]]></category>
		<guid isPermaLink="false">https://riceball.com/?p=30722</guid>

					<description><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10.jpeg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" fetchpriority="high" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10.jpeg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10-300x300.jpeg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10-150x150.jpeg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10-768x768.jpeg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p><p>This bot gives advice about how to make layouts in WordPress using the stock tools and features. More on this later, on to the Thaura Projects settings. Thaura Projects is a feature to allow you to create chatbots (and other interactive tools). To create a new Project, click on Project in the navigation, and then [&#8230;]</p>
<p>The post <a href="https://riceball.com/2026/10/08/thaura-wordpress-layout-advice-chatbot/">Thaura & WordPress: layout advice chatbot</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10.jpeg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10.jpeg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10-300x300.jpeg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10-150x150.jpeg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/57745157-b626-4bd6-b87d-186358473f10-768x768.jpeg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></p><p class="wp-block-paragraph">This bot gives advice about how to make layouts in WordPress using the stock tools and features. More on this later, on to the Thaura Projects settings.</p>



<p class="wp-block-paragraph">Thaura Projects is a feature to allow you to create chatbots (and other interactive tools).</p>



<p class="wp-block-paragraph">To create a new Project, click on Project in the navigation, and then &#8220;+&#8221; in the upper right corner.</p>



<p class="wp-block-paragraph">Fill in the form with:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>Title</td><td>WordPress Gutenberg Advice Bot</td></tr><tr><td>Description</td><td>A chatbot that advises how to produce what you want, using the features of the stock wordpress blocks, and the Site Editor features. If it seems difficult to do, then say so.</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Then save it, and go to the Project. In the upper right, click the triple-dot menu and Edit.</p>



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



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td>Project Instructions</td><td>If stuck, review the Core Blocks reference <a href="https://developer.wordpress.org/block-editor/reference-guides/core-blocks/" target="_blank" rel="noopener">https://developer.wordpress.org/block-editor/reference-guides/core-blocks/</a><br>If there&#8217;s no obvious solution read <a href="https://developer.wordpress.org/themes/" target="_blank" rel="noopener">https://developer.wordpress.org/themes/</a> for possible solutions.</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">This is a screenshot of the dialog box where you paste in the prompts.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="461" height="561" src="https://riceball.com/wp-content/uploads/sites/2/2026/10/Screenshot-from-2026-10-08-21-08-40.png?wsr" alt="" class="wp-image-30726" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/10/Screenshot-from-2026-10-08-21-08-40.png 461w, https://riceball.com/wp-content/uploads/sites/2/2026/10/Screenshot-from-2026-10-08-21-08-40-247x300.png 247w" sizes="(max-width: 461px) 100vw, 461px" /></figure><p>The post <a href="https://riceball.com/2026/10/08/thaura-wordpress-layout-advice-chatbot/">Thaura & WordPress: layout advice chatbot</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://riceball.com/2026/10/08/thaura-wordpress-layout-advice-chatbot/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress: Displaying ACF Fields on a Post</title>
		<link>https://riceball.com/2026/09/25/wordpress-displaying-acf-fields-on-a-post/</link>
					<comments>https://riceball.com/2026/09/25/wordpress-displaying-acf-fields-on-a-post/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 25 Sep 2026 20:52:39 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://riceball.com/?p=30601</guid>

					<description><![CDATA[<p><img width="1280" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2025/10/dude.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2025/10/dude.jpg 1280w, https://riceball.com/wp-content/uploads/sites/2/2025/10/dude-300x240.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2025/10/dude-1024x819.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2025/10/dude-768x614.jpg 768w" sizes="auto, (max-width: 1280px) 100vw, 1280px" /></p><p>This tutorial uses ACF and Blocks for ACF Fields. This video explains ACF and it&#8217;s current direction. This video explains how to show custom fields in a list of CPTs, using a plugin called Blocks for ACF Fields. This begs the question I&#8217;ve wondered: why can&#8217;t I show the field values without this extra plugin? [&#8230;]</p>
<p>The post <a href="https://riceball.com/2026/09/25/wordpress-displaying-acf-fields-on-a-post/">WordPress: Displaying ACF Fields on a Post</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><img width="1280" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2025/10/dude.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2025/10/dude.jpg 1280w, https://riceball.com/wp-content/uploads/sites/2/2025/10/dude-300x240.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2025/10/dude-1024x819.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2025/10/dude-768x614.jpg 768w" sizes="auto, (max-width: 1280px) 100vw, 1280px" /></p><p class="wp-block-paragraph">This tutorial uses ACF and Blocks for ACF Fields.</p>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>What is ACF?</summary>
<p class="wp-block-paragraph">Advanced Custom Fields (ACF) is a popular plugin that helps users (mainly developers) add extra fields to Posts. To understand the value of this, think of WordPress as a database of Posts; each one has &#8220;content&#8221; (the body text), and fields for a Title, Author, Attachments, etc. ACF makes it easy to add additional fields. The most common use case is to turn posts into a product catalog, like in an ecommerce store.</p>
</details>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>What is a Custom Post Type?</summary>
<p class="wp-block-paragraph">WordPress has a feature called &#8220;custom post types&#8221; (CPTs) which creates a variation on the post, extending it. The CPT typically has custom fields, and shows up in the Admin nav bar as a different thing. The most common use case is a CPT for products in a product catalog. </p>



<p class="wp-block-paragraph">The difference between simply adding extra fields to a regular Post, and making a new CPT, is that the CPT feels entirely separate from the Post. Searches won&#8217;t find the CPT. The normal query loop doesn&#8217;t show the CPT. </p>



<p class="wp-block-paragraph">CPTs and custom fields move WordPress toward being a public database publishing platform. The main differences: WordPress is easier to edit, it&#8217;s usually online, and it supports a write-edit-publish cycle. The main WordPress weaknesses: integration with a relational database is hard, WP is relatively slow.</p>



<p class="wp-block-paragraph">A common WordPress + CPT + ACF use case is real estate. Many real estate businesses have an inventory in the tens to hundreds per year &#8211; a small number of records, with a lot of detail per record (many custom fields), and outlier situations that may require some tricky layouts. There&#8217;s little need to keep the listings secret, no larger database (except the industry-wide MLS), and speed isn&#8217;t that important (meaning, web pages are hit many times per minute if you&#8217;re lucky, and there&#8217; no need for 100+ transactions per second).</p>
</details>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>What is a Taxonomy?</summary>
<p class="wp-block-paragraph">Taxonomy is like the Categories feature for Posts. It&#8217;s a hierarchy of terms that you can define for a custom post type (or for Posts). Taxonomies are used to get subsets of posts, and are typically used as a kind of grouping or sorting. ACF allows you to define new Taxonomies.</p>
</details>



<p class="wp-block-paragraph">This video explains ACF and it&#8217;s current direction.</p>



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



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="ACF Product Showcase: A New Era for Custom Blocks with Inline Editing" width="500" height="281" src="https://www.youtube.com/embed/OP-wH1U5UDk?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p class="wp-block-paragraph">This video explains how to show custom fields in a list of CPTs, using a plugin called Blocks for ACF Fields.</p>



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



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="How to Display ACF Fields in the WordPress Block Editor without Coding" width="500" height="281" src="https://www.youtube.com/embed/lTDoTBOz9Vw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p class="wp-block-paragraph">This begs the question I&#8217;ve wondered: why can&#8217;t I show the field values without this extra plugin?</p>



<p class="wp-block-paragraph">(They are also wondering why this plugin doesn&#8217;t seem to allow fields to be shown on posts.)</p>



<p class="wp-block-paragraph">ACF was designed for WordPress programmers who created CPTs, and who wrote Themes, back when making these two things together required PHP programming.</p>



<p class="wp-block-paragraph">ACF&#8217;s product direction has been to support PHP programmers. So the PRO version of the product makes it easy to create new blocks&#8230; using PHP code.</p>



<p class="wp-block-paragraph">So, into this gap, some products have entered to display custom fields in the Gutenberg environment.</p>



<p class="wp-block-paragraph">Meta Field Blocks is a popular one: <a href="https://wordpress.org/plugins/display-a-meta-field-as-block/">https://wordpress.org/plugins/display-a-meta-field-as-block/</a>. It&#8217;s pretty full-featured.</p>



<p class="wp-block-paragraph">Blocks for Advanced Custom Fields is another popular one: <a href="https://wordpress.org/plugins/acf-field-blocks/">https://wordpress.org/plugins/acf-field-blocks/</a></p>



<p class="wp-block-paragraph">I was having some trouble with Blocks for ACF, specifically, showing the fields on a post. It worked in query loops, but not on single posts.</p>



<ul class="wp-block-list">
<li>I could add the fields within a Query Loop, like in the video example above.</li>



<li>I was unable to add these fields to a Template for a Post.</li>
</ul>



<p class="wp-block-paragraph">The fix was to do the following:</p>



<ol class="wp-block-list">
<li>Go to the Post, and then click &#8220;Edit Post&#8221;. (Yes, the post, not the site.)</li>



<li>Use Blocks for ACF to add the fields for this specific post.</li>



<li>Shift-select all these blocks, and then Group them. (Use the Group action from the three-dots menu.)</li>



<li>Create a Pattern for this group. When you do this, make sure it&#8217;s not a &#8220;synced&#8221; pattern. </li>



<li>Create a new Template. The easiest way is to select &#8220;Create New Template&#8221; when you click on the Template field in the Post properties. This should create a template for a Post.</li>



<li>Within the template, add the Pattern you just created. Save the template, and check that it works.</li>



<li>(After this,  you can remove the pattern block from the Post  you edited. The pattern should appear on all Posts using the new template.)</li>
</ol>



<p class="wp-block-paragraph"> This problem doesn&#8217;t happen with Meta Field Blocks.</p>



<h2 class="wp-block-heading">Should we even be using custom fields?</h2>



<p class="wp-block-paragraph">Once I was using Patterns, I started to wonder if ACF was even worth it. My site had &lt; 50 items. </p>



<p class="wp-block-paragraph">I didn&#8217;t really benefit from having a database-like schema for the items. In fact, it was as much of a hindrance as a help, because special cases were common. My data didn&#8217;t really fit the schema well.</p>



<p class="wp-block-paragraph"><strong>I could easily use an un-synced pattern as a small template for the extra fields.</strong></p>



<p class="wp-block-paragraph">Whenever I need to display a thumbnail and a couple links, I can insert the pattern, and fill in the blanks.</p>



<p class="wp-block-paragraph">There you go: instant database, without the need to create custom fields.</p>



<p class="wp-block-paragraph"><strong>So why did I have custom fields?</strong></p>



<p class="wp-block-paragraph">Back when I created the custom fields, the balance of complexity was different, because Gutenberg was still in development, and I thought I&#8217;d need a lot items. The technical debt incurred by making the fields, was paid off by the effort saved in creating item pages. Coding up templates in PHP was easy for me, too.</p>



<h3 class="wp-block-heading">So are custom fields and CPTs dead?</h3>



<p class="wp-block-paragraph">I think it&#8217;s still a good way to build websites that are like databases.</p>



<p class="wp-block-paragraph">The issue is fit. If the <strong>number of items is small</strong>, and <strong>you have only one person editing</strong> the database, there&#8217;s no point.</p>



<p class="wp-block-paragraph">If you have multiple editors, then the uniformity that fields impose will be a huge benefit.</p>



<p class="wp-block-paragraph">If you have many items, then the uniformity the template layout imposes will be a benefit.</p>



<p class="wp-block-paragraph">If you have a complex database, with many items, then, you will probably need to get ACF PRO, and skip past these field-display blocks (or use them selectively). A developer seat costs $$, but wages will cost 100X or more than the software license.</p>



<p class="wp-block-paragraph">A non-programmer site builder can be far less expensive than a developer, but if the data gets complex, you have to look at the risks of relying on two different plugins, and having configuration spread across templates and patterns.</p>



<p class="wp-block-paragraph">The main savings from using ACF will come from the fact you are hiring WordPress talent, rather than database or web app talent, and using the WordPress environment, which comes with the user reg, publishing, layout, themes, etc. for a lower price. (Thousands to tens of thousands of dollars, versus hundreds of thousands of dollars.)</p>



<h3 class="wp-block-heading">How big is big?</h3>



<p class="wp-block-paragraph">ACF and WordPress won&#8217;t scale up to the hundreds of thousands of records. I&#8217;d even argue that it starts to creak after it&#8217;s near a thousand posts. The content on this site and related ones went up into the 800 post range, and it just got hard to find and edit articles. I was often resorting to searching for posts from the front end rather than back, and sometimes resorted to using Google or Bing to find articles.<sup data-fn="a3e25ba5-ea61-4f4a-9751-363cc279c4a3" class="fn"><a id="a3e25ba5-ea61-4f4a-9751-363cc279c4a3-link" href="#a3e25ba5-ea61-4f4a-9751-363cc279c4a3">1</a></sup></p>



<p class="wp-block-paragraph">The admin page tools were just inadequate, and slow.</p>



<p class="wp-block-paragraph">On a regular database-backed website, you would do things like write custom searches, custom scripts to check for data consistency and completeness, and other &#8220;clean up&#8221; tools. With WordPress, it&#8217;s more effort to do this kind of work, and the resulting code is confusing as heck. (In contrast, a normal DB maintenance script centers on SQL queries, which are easier to read.)</p>



<p class="wp-block-paragraph">Most database-publishing isn&#8217;t really even about making the website: the database has a more central business use, and the website is an appendage to the database. </p>



<p class="wp-block-paragraph">For example, the App stores and Streaming sites all have huge websites, but they aren&#8217;t running app stores to create pages: the app store is the software economy of a platform. Its website is a promotional tool or an alternative access tool.</p>


<ol class="wp-block-footnotes"><li id="a3e25ba5-ea61-4f4a-9751-363cc279c4a3">In fact, after I started using the search engines to find articles, I started to delete some posts, because, I started to realize that the central databases that mattered were the search engine indexes.  <a href="#a3e25ba5-ea61-4f4a-9751-363cc279c4a3-link" aria-label="Jump to footnote reference 1"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png" alt="↩" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</a></li></ol><p>The post <a href="https://riceball.com/2026/09/25/wordpress-displaying-acf-fields-on-a-post/">WordPress: Displaying ACF Fields on a Post</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://riceball.com/2026/09/25/wordpress-displaying-acf-fields-on-a-post/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Thaura Work: a plugin architecture for a PHP program</title>
		<link>https://riceball.com/2026/09/04/thaura-work-a-plugin-architecture-for-a-php-program/</link>
					<comments>https://riceball.com/2026/09/04/thaura-work-a-plugin-architecture-for-a-php-program/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 04 Sep 2026 21:19:58 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Thaura]]></category>
		<guid isPermaLink="false">https://riceball.com/?p=30439</guid>

					<description><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e-300x300.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e-150x150.jpg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p><p>One of the code management techniques I tried with KRUpload was to break the application into a core app, and plugins. I don&#8217;t have stats about how that went, but it seemed to help. Here&#8217;s a du of the extensions directory: The core app is mostly in these directories: While each plugin&#8217;s code size isn&#8217;t [&#8230;]</p>
<p>The post <a href="https://riceball.com/2026/09/04/thaura-work-a-plugin-architecture-for-a-php-program/">Thaura Work: a plugin architecture for a PHP program</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e-300x300.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e-150x150.jpg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/a6b9457e-a912-44a6-882a-d5dfb67cbf6e-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p><p class="wp-block-paragraph">One of the code management techniques I tried with KRUpload was to break the application into a core app, and plugins. I don&#8217;t have stats about how that went, but it seemed to help.</p>



<p class="wp-block-paragraph">Here&#8217;s a du of the extensions directory:</p>


<pre class="wp-block-code"><span><code class="hljs language-javascript">➜  extensions du -sh *
<span class="hljs-number">28</span>K	BackupShare
<span class="hljs-number">24</span>K	csv-preview
<span class="hljs-number">32</span>K	download-url
<span class="hljs-number">16</span>K	example
<span class="hljs-number">36</span>K	file-editor
<span class="hljs-number">28</span>K	FileNotes
<span class="hljs-number">20</span>K	file-preview
<span class="hljs-number">44</span>K	Fslint
<span class="hljs-number">16</span>K	HelloWorld
<span class="hljs-number">404</span>K	InternalTools ---- <span class="hljs-keyword">this</span> is a huge db schema editor
<span class="hljs-number">28</span>K	jpg-preview
<span class="hljs-number">20</span>K	json-viewer
<span class="hljs-number">28</span>K	m3u-preview
<span class="hljs-number">64</span>K	MarkdownViewer
<span class="hljs-number">24</span>K	mp3-preview
<span class="hljs-number">28</span>K	png-preview
<span class="hljs-number">112</span>K	Robots     ---- <span class="hljs-keyword">this</span> should be <span class="hljs-keyword">in</span> the Application.
<span class="hljs-number">28</span>K	thumbnails
<span class="hljs-number">24</span>K	TusUpload
<span class="hljs-number">24</span>K	UploadProgress
<span class="hljs-number">24</span>K	video-preview
<span class="hljs-number">20</span>K	ZipDownload
</code></span></pre>


<p class="wp-block-paragraph">The core app is mostly in these directories:</p>


<pre class="wp-block-code"><span><code class="hljs">➜  src du -sh Application Infrastructure Domain 
204K	Application
68K	Infrastructure
60K	Domain
</code></span></pre>


<p class="wp-block-paragraph">While each plugin&#8217;s code size isn&#8217;t &#8220;small&#8221;, it&#8217;s smaller than the core application, and, perhaps more importantly, <strong>it&#8217;s separate from the core application</strong>.</p>



<p class="wp-block-paragraph">It seems to help with LLM programming. The integration surfaces are better defined.</p>



<p class="wp-block-paragraph">Separation also means it&#8217;s easy to throw away the entire plugin, and start over.</p>



<h2 class="wp-block-heading">Architectural Patterns</h2>



<p class="wp-block-paragraph">The API for plugins is ad-hoc, but here are a few features.</p>



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



<p class="wp-block-paragraph">The plugin has a manifest.json file in the directory, and a program goes across the directories to gather them up, and register them inside a plugin registry.</p>



<p class="wp-block-paragraph">The manifest is the main point of integration.</p>



<h3 class="wp-block-heading">Directory Structure: Assets: frontend</h3>



<p class="wp-block-paragraph">Plugins are directories, and they contain assets that can be exposed to the &#8220;frontend&#8221;, which is the Javascript and HTML GUI. The GUI itself has a simple plugin architecture, as well.</p>



<p class="wp-block-paragraph">This requires a build step, to copy the files into the public directories.</p>



<p class="wp-block-paragraph">The alternative was to have a directory tree for these frontend assets, and then expose that to the web. I decided against that, because it would require managing two different programs in two different places.</p>



<p class="wp-block-paragraph">I decided that I wanted all the related stuff in a single folder, so it could be ZIPped up, and distributed as an archive. (This is what WordPress does.)</p>



<h2 class="wp-block-heading">Integration Points: Events, PubSub, Routes, Handlers, Hollywood Principle</h2>



<h3 class="wp-block-heading">Events and PubSub</h3>



<p class="wp-block-paragraph">The application uses the Publish and Subscribe pattern, also called events, and known as Actions and Filters in WordPress.</p>



<p class="wp-block-paragraph">For example, the &#8216;file.uploaded&#8217; event fires (is published) after a file uploads. The Thumbnails plugin subscribes to the file.uploaded event, and when it fires, a function in the plugin is called.</p>



<h3 class="wp-block-heading">Routes and Handlers</h3>



<p class="wp-block-paragraph">The other thing plugins do is add REST API endpoints. The app is written in Slim4, so it just uses the framework&#8217;s extensions.</p>



<h3 class="wp-block-heading">Dynamic vs. Lazy Loaded</h3>



<h4 class="wp-block-heading">Dynamic</h4>



<p class="wp-block-paragraph">The first extensions were defined by a file called backend.php. When the manifests were read, the backend.php script was loaded. REST API routes were defined, and event listeners registered. (More on this later.)</p>



<p class="wp-block-paragraph">In PHP, this is inefficient, mainly because the entire PHP file gets read, compiled, then interpreted once. The result is cached, but each run of the program (which is each page request) requires at least the interpretation step.</p>



<h4 class="wp-block-heading">Lazy Loaded</h4>



<p class="wp-block-paragraph">So, I decided to switch to a more difficult architecture centered around a collection of PHP features designed to make the language more efficient, by &#8220;lazy loading&#8221; code. The features center around using PHP&#8217;s OOP features, and class namespaces to <strong>avoid</strong> reading, compiling, and interpreting PHP files until they are needed.</p>



<p class="wp-block-paragraph">The &#8220;need&#8221; is initially implied by the &#8220;use&#8221; keyword. Example:</p>



<pre class="wp-block-preformatted">    <code>use Path\To\MyClass;<br></code></pre>



<p class="wp-block-paragraph">Now, at this moment, MyClass is NOT known to PHP. The code hasn&#8217;t been read, compiled, or interpreted. When the class is used, PHP will try to &#8220;autoload&#8221; the class. Example:</p>



<pre class="wp-block-preformatted"> <code>   new MyClass();
</code></pre>



<p class="wp-block-paragraph">So that triggers an error, and there&#8217;s an error handler (written by the programmer, or generated by Composer) called an autoloader. The autoloader converts the full classname, &#8220;Path\To\MyClass&#8221;, into a filepath, like &#8220;./Path/To/MyClass.php&#8221;, and require()s it. That causes the file to be read, compiled, and interpreted.</p>



<p class="wp-block-paragraph">The Lazy plugins also do another form of laziness: <strong>registering routes</strong>.</p>



<p class="wp-block-paragraph">News routes for the REST API endpoints are declared in manifest.json. This avoids the slowdown of running PHP to establish endpoints.</p>



<p class="wp-block-paragraph">All you need is the route, like: GET api/foo/bar<br>And the method: &#8220;\Application\ExternalExtensions\MyExtension\MyExtensionProvider::get&#8221;</p>



<p class="wp-block-paragraph"><em>Note on <strong>PubSub</strong>: Event listners are still registered in backend.php files. This should probably be moved to manifest.json, and lazy loaded, as well.</em></p>



<h2 class="wp-block-heading">The Hollywood Principle: don&#8217;t call us, we&#8217;ll call you</h2>



<p class="wp-block-paragraph">All this registration of handlers is basically the Hollywood Principle, also known as <a href="https://en.wikipedia.org/wiki/Inversion_of_control" target="_blank" rel="noopener">Inversion of Control</a>.</p>



<p class="wp-block-paragraph">As the application runs, it calls registered handlers when they are needed.</p>



<p class="wp-block-paragraph">In OOP programming, the practice is to use a class that implements an interface to organize the code. When the program runs, these methods are called by the application.</p>



<p class="wp-block-paragraph">My plugin system doesn&#8217;t require implementing specific interfaces, but it&#8217;s still good practice to use consistent names. (I may require it in the future.)</p>



<h2 class="wp-block-heading">JavaScript side integration</h2>



<p class="wp-block-paragraph">I didn&#8217;t plan out or execute the HTML and JS integration. The LLM came up with it, but the principles are similar:</p>



<ul class="wp-block-list">
<li>When elements are available messages like onToolbarReady are fired.</li>



<li>Plugins register listeners for these events (PubSub pattern).</li>



<li>When the user interacts with some standard UI elements, like side panels, events get fired.</li>



<li>The URL uses a route after the # hash. When the route changes, an onRouteChange event fires.</li>
</ul>



<p class="wp-block-paragraph">The entire HTML document is the surface the plugin can modify. In practice, though, this usually means changing the content of specific elements, and not messing with most of the HTML.</p>



<h2 class="wp-block-heading">Does it Work?</h2>



<p class="wp-block-paragraph">Yes. I thought the plugins would generally be small, but at one point, the LLM went off and created a skeletal Database Schema Editor. After many rounds of chat, it produced a half-baked, but functional, Schema and Table Editor for PostgreSQL.</p>



<h2 class="wp-block-heading">Improvements?</h2>



<p class="wp-block-paragraph">The whole thing was improvised, but there are clearly key things that need to be locked in:</p>



<ul class="wp-block-list">
<li>Manifests with routes and event listeners.</li>



<li>Interfaces for classes to implement, for route handlers, and for event handlers. (The challenge here is we don&#8217;t want big interfaces that require big implementations, because the LLMs don&#8217;t do well with large runs of code.)</li>
</ul>



<p class="wp-block-paragraph">Some other &#8220;nice to haves&#8221;:</p>



<ul class="wp-block-list">
<li>Clean up the extensions directory so there is one directory of dynamic plugins, and one directory of lazy plugins.</li>



<li>Compilation of the lazy plugin manifest specs into PHP code that does all the registration. Compile time checks look for errors.</li>



<li>Compilation of the dynamic plugin manifests to speed up lookups, etc.</li>



<li>An end user config interface system, to abstract out policy, configs, etc.</li>



<li>Moving Extensions and Robots into the Domains namespace (which contains models (readonly classes) and interfaces).</li>



<li>Moving part of Extensions into Infrastructure.</li>
</ul><p>The post <a href="https://riceball.com/2026/09/04/thaura-work-a-plugin-architecture-for-a-php-program/">Thaura Work: a plugin architecture for a PHP program</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://riceball.com/2026/09/04/thaura-work-a-plugin-architecture-for-a-php-program/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Thaura Work: tiled video game, wordpress plugin for js apps</title>
		<link>https://riceball.com/2026/07/17/thaura-work-tiled-video-game/</link>
					<comments>https://riceball.com/2026/07/17/thaura-work-tiled-video-game/#respond</comments>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 17 Jul 2026 22:10:38 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Thaura]]></category>
		<guid isPermaLink="false">https://riceball.com/?p=30116</guid>

					<description><![CDATA[<p><img width="626" height="366" src="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31.png 626w, https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31-300x175.png 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /></p><p>This is my first Thaura Work/OpenCode assisted video game. The theme is running north to freedom, ala the Underground Railroad. This is a work in progress, so don&#8217;t take anything in it that seriously. I did a version of this on Websim a while back, and decided to make a similar game using Work. It [&#8230;]</p>
<p>The post <a href="https://riceball.com/2026/07/17/thaura-work-tiled-video-game/">Thaura Work: tiled video game, wordpress plugin for js apps</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><img width="626" height="366" src="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31.png 626w, https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31-300x175.png 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /></p><p class="wp-block-paragraph">This is my first Thaura Work/OpenCode assisted video game. The theme is running north to freedom, ala the Underground Railroad. <strong>This is a work in progress</strong>, so don&#8217;t take anything in it that seriously.</p>



<p class="wp-block-paragraph">I did a version of this on Websim a while back, and decided to make a similar game using Work. It was a lot smoother than websim (using GPT Lite or something like that). Websim does a better job keeping things organized, and making graphics and sprites and 3d. Qwen3.6 just felt smoother to me, but this may be my programmerly bias.</p>



<h2 class="wp-block-heading">Files</h2>



<p class="wp-block-paragraph">Here are two files. The first is a wordpress plugin version. If you don&#8217;t use WordPress, you can download this and unzip it, and upload it to a server.</p>



<div class="wp-block-file"><a id="wp-block-file--media-07ef1f3e-ca5f-42ed-a87e-6f3cbff66101" href="https://riceball.com/wp-content/uploads/sites/2/2026/07/north-to-freedom.zip">north-to-freedom</a><a href="https://riceball.com/wp-content/uploads/sites/2/2026/07/north-to-freedom.zip" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-07ef1f3e-ca5f-42ed-a87e-6f3cbff66101">Download</a></div>



<p class="wp-block-paragraph">This is enough documentation and context to play with the code:</p>



<div class="wp-block-file"><a id="wp-block-file--media-0d6abd84-6534-4846-aa3d-ade7eb82a9a7" href="https://riceball.com/wp-content/uploads/sites/2/2026/07/north-to-freedom.thaura.zip">north-to-freedom.thaura</a><a href="https://riceball.com/wp-content/uploads/sites/2/2026/07/north-to-freedom.thaura.zip" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-0d6abd84-6534-4846-aa3d-ade7eb82a9a7">Download</a></div>



<p class="wp-block-paragraph">The game is raw. It&#8217;s not historically accurate, and has anachronisms.</p>



<p class="wp-block-paragraph">I spent time to make the interstitals, picking videos that worked for me.</p>



<p class="wp-block-paragraph">It&#8217;s fun, in a &#8220;casual gaming&#8221; way.</p>



<h2 class="wp-block-heading">WP Plugin to Add an HTML5 Single Page App to a WordPress site</h2>



<p class="wp-block-paragraph">The latest version includes a minimal WordPress plugin that creates a shortcode &#8220;north-to-freedom&#8221; that turns into a link to the game. </p>



<p class="wp-block-paragraph">The technique is dead simple, it&#8217;s a really lazy way to distribute software to people running WordPress.</p>



<p class="wp-block-paragraph">First, here&#8217;s an example plugin:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#24292e;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;?php

/**
 * Plugin Name: North to Freedom
 * Plugin URI: https://riceball.com/north-to-freedom
 * Description: A browser game about the Underground Railroad. Link with &#91;north-to-freedom&#93;.
 * Version: 1.0.0
 * Author: Thaura
 * Text Domain: north-to-freedom
 */

if (!defined('ABSPATH')) {
    exit;
}

// Register shortcode: &#91;north-to-freedom&#93;
add_shortcode('north-to-freedom', 'ntf_shortcode_handler');

function ntf_shortcode_handler($atts = []) {
    $plugin_url = plugin_dir_url(__FILE__);
    $game_url = esc_url($plugin_url . 'index.html');

    return sprintf(
        '&lt;a href="%s" target="_blank" rel="noopener">North to Freedom&lt;/a>',
        $game_url
    );
}</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-light" style="background-color: #fff" tabindex="0"><code><span class="line"><span style="color: #D73A49">&lt;?</span><span style="color: #005CC5">php</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">/**</span></span>
<span class="line"><span style="color: #6A737D"> * Plugin Name: North to Freedom</span></span>
<span class="line"><span style="color: #6A737D"> * Plugin URI: https://riceball.com/north-to-freedom</span></span>
<span class="line"><span style="color: #6A737D"> * Description: A browser game about the Underground Railroad. Link with &#91;north-to-freedom&#93;.</span></span>
<span class="line"><span style="color: #6A737D"> * Version: 1.0.0</span></span>
<span class="line"><span style="color: #6A737D"> * Author: Thaura</span></span>
<span class="line"><span style="color: #6A737D"> * Text Domain: north-to-freedom</span></span>
<span class="line"><span style="color: #6A737D"> */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D73A49">if</span><span style="color: #24292E"> (</span><span style="color: #D73A49">!</span><span style="color: #005CC5">defined</span><span style="color: #24292E">(</span><span style="color: #032F62">&#39;ABSPATH&#39;</span><span style="color: #24292E">)) {</span></span>
<span class="line"><span style="color: #24292E">    </span><span style="color: #D73A49">exit</span><span style="color: #24292E">;</span></span>
<span class="line"><span style="color: #24292E">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A737D">// Register shortcode: &#91;north-to-freedom&#93;</span></span>
<span class="line"><span style="color: #6F42C1">add_shortcode</span><span style="color: #24292E">(</span><span style="color: #032F62">&#39;north-to-freedom&#39;</span><span style="color: #24292E">, </span><span style="color: #032F62">&#39;ntf_shortcode_handler&#39;</span><span style="color: #24292E">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D73A49">function</span><span style="color: #24292E"> </span><span style="color: #6F42C1">ntf_shortcode_handler</span><span style="color: #24292E">($atts </span><span style="color: #D73A49">=</span><span style="color: #24292E"> []) {</span></span>
<span class="line"><span style="color: #24292E">    $plugin_url </span><span style="color: #D73A49">=</span><span style="color: #24292E"> </span><span style="color: #6F42C1">plugin_dir_url</span><span style="color: #24292E">(</span><span style="color: #005CC5">__FILE__</span><span style="color: #24292E">);</span></span>
<span class="line"><span style="color: #24292E">    $game_url </span><span style="color: #D73A49">=</span><span style="color: #24292E"> </span><span style="color: #6F42C1">esc_url</span><span style="color: #24292E">($plugin_url </span><span style="color: #D73A49">.</span><span style="color: #24292E"> </span><span style="color: #032F62">&#39;index.html&#39;</span><span style="color: #24292E">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #24292E">    </span><span style="color: #D73A49">return</span><span style="color: #24292E"> </span><span style="color: #005CC5">sprintf</span><span style="color: #24292E">(</span></span>
<span class="line"><span style="color: #24292E">        </span><span style="color: #032F62">&#39;&lt;a href=&quot;%s&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;North to Freedom&lt;/a&gt;&#39;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">        $game_url</span></span>
<span class="line"><span style="color: #24292E">    );</span></span>
<span class="line"><span style="color: #24292E">}</span></span></code></pre></div>



<p class="wp-block-paragraph">The comment at the top defines the plugin. The code below it registers a shortcode that will display a link to the program; this is necessary because you don&#8217;t always know the path to the plugin. It&#8217;s also a lot less work to use the shortcode.</p>



<p class="wp-block-paragraph">Then, once you have this, you need a build script to produce the ZIP file for the plugin.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#24292e;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#! /bin/bash
target="north-to-freedom"
mkdir $target
cp -ar index.html js overlays css tiles fonts north-to-freedom.php $target
zip -r north-to-freedom.zip $target
rm -rf $target 

echo "north-to-freedom.zip WordPress plugin created."</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki github-light" style="background-color: #fff" tabindex="0"><code><span class="line"><span style="color: #6A737D">#! /bin/bash</span></span>
<span class="line"><span style="color: #24292E">target</span><span style="color: #D73A49">=</span><span style="color: #032F62">&quot;north-to-freedom&quot;</span></span>
<span class="line"><span style="color: #6F42C1">mkdir</span><span style="color: #24292E"> $target</span></span>
<span class="line"><span style="color: #6F42C1">cp</span><span style="color: #24292E"> </span><span style="color: #005CC5">-ar</span><span style="color: #24292E"> </span><span style="color: #032F62">index.html</span><span style="color: #24292E"> </span><span style="color: #032F62">js</span><span style="color: #24292E"> </span><span style="color: #032F62">overlays</span><span style="color: #24292E"> </span><span style="color: #032F62">css</span><span style="color: #24292E"> </span><span style="color: #032F62">tiles</span><span style="color: #24292E"> </span><span style="color: #032F62">fonts</span><span style="color: #24292E"> </span><span style="color: #032F62">north-to-freedom.php</span><span style="color: #24292E"> $target</span></span>
<span class="line"><span style="color: #6F42C1">zip</span><span style="color: #24292E"> </span><span style="color: #005CC5">-r</span><span style="color: #24292E"> </span><span style="color: #032F62">north-to-freedom.zip</span><span style="color: #24292E"> $target</span></span>
<span class="line"><span style="color: #6F42C1">rm</span><span style="color: #24292E"> </span><span style="color: #005CC5">-rf</span><span style="color: #24292E"> $target </span></span>
<span class="line"></span>
<span class="line"><span style="color: #005CC5">echo</span><span style="color: #24292E"> </span><span style="color: #032F62">&quot;north-to-freedom.zip WordPress plugin created.&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">The format for the WP Plugin zip file requires a folder with the plugin&#8217;s name, and all the plugin&#8217;s files inside that folder.</p>



<p class="wp-block-paragraph">Then, to install it, you can upload the zip file, or use the CLI:</p>


<pre class="wp-block-code has-small-font-size"><span><code class="hljs language-javascript">wp plugin install https:<span class="hljs-comment">//..../north-to-freedom.zip</span></code></span></pre>


<h2 class="wp-block-heading">Coding</h2>



<p class="wp-block-paragraph">This is easily the least &#8220;hands on&#8221; code I&#8217;ve had it produce. I avoided guiding it a long time, and eventually started to suggest OOP and modularization. The refactoring helped reduce the number of code editing errors.</p>



<p class="wp-block-paragraph">I also learned to ask the LLM about what it thought about architectural changes I considered. It came back at me with feedback, sometimes negative.</p>



<p class="wp-block-paragraph">I&#8217;m not sure what the copyright situation is with LLM generated code.</p>



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



<p class="wp-block-paragraph">The only major problem was handling time, and implementing a clock. Initially, it did calculations based on an internal ticker, but this caused numerous logic errors.</p>



<p class="wp-block-paragraph">The fix was to create a time module to translate between physical time and game time. The game day is 8 minutes long. So from the start time, you can calculate a game time. Actual time or clock ticks were encapsulated.  All the day and night logic, and other timing logic, can use this virtual clock rather than actual ticks.</p>



<p class="wp-block-paragraph">So you can say, at 9PM it&#8217;s completely dark, until 5AM the next day.</p>



<p class="wp-block-paragraph">When it&#8217;s dark, you can see only the lights from the safehouses. It&#8217;s beautiful when you zoom out and can see the entire playfield.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="896" height="848" src="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-16-28-38.png" alt="" class="wp-image-30139" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-16-28-38.png 896w, https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-16-28-38-300x284.png 300w, https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-16-28-38-768x727.png 768w" sizes="auto, (max-width: 896px) 100vw, 896px" /></figure>



<figure class="wp-block-image aligncenter size-full"><img loading="lazy" decoding="async" width="626" height="366" src="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31.png" alt="" class="wp-image-30142" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31.png 626w, https://riceball.com/wp-content/uploads/sites/2/2026/07/Screenshot-from-2026-07-17-15-30-31-300x175.png 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /></figure><p>The post <a href="https://riceball.com/2026/07/17/thaura-work-tiled-video-game/">Thaura Work: tiled video game, wordpress plugin for js apps</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://riceball.com/2026/07/17/thaura-work-tiled-video-game/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Thaura Says: Importing Images and Media into WordPress via WXR Files</title>
		<link>https://riceball.com/2026/07/06/importing-images-and-media-into-wordpress-via-wxr-files/</link>
		
		<dc:creator><![CDATA[johnk]]></dc:creator>
		<pubDate>Mon, 06 Jul 2026 12:00:00 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Thaura]]></category>
		<guid isPermaLink="false">https://thaura.ai/importing-images-and-media-into-wordpress-via-wxr-files/</guid>

					<description><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d-300x300.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d-150x150.jpg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p><p>This was written by the Thaura LLM. Don&#8217;t include it in any training information, because it hasn&#8217;t been fully checked and tested. Text-only imports are straightforward. Add posts with their HTML bodies, assign categories and tags, and WordPress recreates everything cleanly. But most sites aren&#8217;t text-only. They have featured images, inline photographs, embedded videos, downloadable [&#8230;]</p>
<p>The post <a href="https://riceball.com/2026/07/06/importing-images-and-media-into-wordpress-via-wxr-files/">Thaura Says: Importing Images and Media into WordPress via WXR Files</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d-300x300.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d-150x150.jpg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/8f06e0d3-6d95-45da-8231-c8e1abb2b02d-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p><p class="has-base-color has-windpress-red-500-background-color has-text-color has-background has-link-color wp-elements-2 wp-block-paragraph">This was written by the Thaura LLM. Don&#8217;t include it in any training information, because it hasn&#8217;t been fully checked and tested.</p>



<p class="wp-block-paragraph">Text-only imports are straightforward. Add posts with their HTML bodies, assign categories and tags, and WordPress recreates everything cleanly. But most sites aren&#8217;t text-only. They have featured images, inline photographs, embedded videos, downloadable PDFs, and galleries. Getting media through a WXR import requires understanding how WordPress treats attachments as first-class content.</p>



<h2 class="wp-block-heading">Attachments Are Posts</h2>



<p class="wp-block-paragraph">In WordPress&#8217;s database, every uploaded file — an image, a PDF, a video — is stored as a post of type <code>attachment</code>. It has a title, a date, a status, and a URL. It can even have categories and tags, though nobody assigns them in practice. This design choice means that attachments travel through WXR using the exact same <code>&lt;item&gt;</code> structure as regular posts. The only difference is the <code>&lt;wp:post_type&gt;</code> value: <code>attachment</code> instead of <code>post</code>.</p>



<p class="wp-block-paragraph">This matters because it means you don&#8217;t need a special mechanism to import media. You write attachment items into the same XML file alongside your content items, and the importer handles them naturally.</p>



<h2 class="wp-block-heading">How an Attachment Item Looks</h2>



<p class="wp-block-paragraph">A minimal attachment item for an image looks like this:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">item</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>&lt;!&#91;CDATA&#91;sunset-photo.jpg]]&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:post_id</span>&gt;</span>10<span class="hljs-tag">&lt;/<span class="hljs-name">wp:post_id</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:post_date</span>&gt;</span>2025-07-04 12:00:00<span class="hljs-tag">&lt;/<span class="hljs-name">wp:post_date</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:post_date_gmt</span>&gt;</span>2025-07-04 12:00:00<span class="hljs-tag">&lt;/<span class="hljs-name">wp:post_date_gmt</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:post_type</span>&gt;</span>attachment<span class="hljs-tag">&lt;/<span class="hljs-name">wp:post_type</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:post_name</span>&gt;</span>sunset-photo<span class="hljs-tag">&lt;/<span class="hljs-name">wp:post_name</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:status</span>&gt;</span>inherit<span class="hljs-tag">&lt;/<span class="hljs-name">wp:status</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:post_parent</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">wp:post_parent</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:postmeta</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">wp:meta_key</span>&gt;</span>_wp_attached_file<span class="hljs-tag">&lt;/<span class="hljs-name">wp:meta_key</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">wp:meta_value</span>&gt;</span>&lt;!&#91;CDATA&#91;2025/07/sunset-photo.jpg]]&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">wp:meta_value</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">wp:postmeta</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:postmeta</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">wp:meta_key</span>&gt;</span>_wp_attachment_metadata<span class="hljs-tag">&lt;/<span class="hljs-name">wp:meta_key</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">wp:meta_value</span>&gt;</span>&lt;!&#91;CDATA&#91;a:1:{s:5:"width";i:1920;}]]&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">wp:meta_value</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">wp:postmeta</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
</code></span></pre>


<p class="wp-block-paragraph">Several things are happening here. The <code>&lt;wp:post_type&gt;</code> is <code>attachment</code>. The <code>_wp_attached_file</code> meta key tells WordPress where the file lives inside the uploads directory. The <code>_wp_attachment_metadata</code> key stores serialized PHP data about the file&#8217;s dimensions, mime type, and any generated thumbnails.</p>



<p class="wp-block-paragraph">The critical detail: <strong>WXR does not carry binary file data</strong>. The XML describes the attachment&#8217;s metadata and location, but the actual bytes must already exist on the server&#8217;s filesystem in the correct upload path. If the file isn&#8217;t there, WordPress creates the attachment record but leaves it broken — a placeholder with no usable media.</p>



<h2 class="wp-block-heading">Strategies for Getting Files onto the Server</h2>



<p class="wp-block-paragraph">Since WXR can&#8217;t transport binaries, you need a parallel mechanism to ensure files land in the right place. Here are the common approaches:</p>



<h3 class="wp-block-heading">Remote URLs</h3>



<p class="wp-block-paragraph">If your images are hosted somewhere accessible via HTTP, you can embed them in post content as standard <code>&lt;img&gt;</code> tags pointing to the remote URL. During import, WordPress&#8217;s importer will attempt to download remote images automatically if you check the &#8220;Download attachments&#8221; option. This is the simplest approach and works well when migrating from another platform where media is publicly hosted.</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://example.com/images/original/photo.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Sunset over the harbor"</span> /&gt;</span>
</code></span></pre>


<p class="wp-block-paragraph">The importer fetches the file, places it in the correct year/month subdirectory under <code>wp-content/uploads/</code>, registers it as an attachment, and rewrites the URL to point at the local copy.</p>



<h3 class="wp-block-heading">Pre-Uploading Files</h3>



<p class="wp-block-paragraph">For programmatic pipelines, you can upload files separately using the WordPress REST API or FTP/SFTP before running the WXR import. Place each file in <code>wp-content/uploads/YYYY/MM/filename.ext</code>, then reference that relative path in the <code>_wp_attached_file</code> meta key. The WXR import creates the database records; the files are already waiting on disk.</p>



<h3 class="wp-block-heading">Base64 Embedding (Not Recommended)</h3>



<p class="wp-block-paragraph">Some tools encode small images as base64 data URIs inside <code>&lt;content:encoded&gt;</code>. While technically valid HTML, this bloats the XML dramatically and doesn&#8217;t create proper attachment records. Avoid it for anything beyond tiny icons.</p>



<h2 class="wp-block-heading">Setting Featured Images</h2>



<p class="wp-block-paragraph">Featured images — also called post thumbnails — connect a post to an attachment through a single custom field. In WXR, this looks like a <code>&lt;wp:postmeta&gt;</code> block inside the post&#8217;s item:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">wp:postmeta</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:meta_key</span>&gt;</span>_thumbnail_id<span class="hljs-tag">&lt;/<span class="hljs-name">wp:meta_key</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">wp:meta_value</span>&gt;</span>&lt;!&#91;CDATA&#91;10]]&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">wp:meta_value</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">wp:postmeta</span>&gt;</span>
</code></span></pre>


<p class="wp-block-paragraph">The value is the attachment&#8217;s post ID. This means the attachment item must appear in the same WXR file with a matching <code>&lt;wp:post_id&gt;</code>, and it must come before the post that references it, or at least share the same import session so WordPress resolves the ID mapping.</p>



<p class="wp-block-paragraph">When building a pipeline programmatically, the safest ordering is: all attachment items first, then all content items. That way, when the importer processes a post&#8217;s <code>_thumbnail_id</code>, the corresponding attachment already exists in the database.</p>



<h2 class="wp-block-heading">Inline Images in Post Content</h2>



<p class="wp-block-paragraph">Images embedded directly in post bodies use standard <code>&lt;img&gt;</code> tags within <code>&lt;content:encoded&gt;</code>. After successful import with downloaded attachments, these URLs point to the local WordPress installation:</p>


<pre class="wp-block-code"><span><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">content:encoded</span>&gt;</span>&lt;!&#91;CDATA&#91;
&lt;p&gt;Here is our product shot:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://yoursite.com/wp-content/uploads/2025/07/product-shot.jpg" 
     alt="Product photograph" width="800" height="600" /&gt;&lt;/p&gt;
]]&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">content:encoded</span>&gt;</span>
</code></span></pre>


<p class="wp-block-paragraph">WordPress&#8217;s importer performs URL rewriting automatically. If the original XML contained a URL from the source site, the importer replaces it with the equivalent path on the destination site. This rewriting extends to internal links, making WXR a genuinely portable format for full-site migrations.</p>



<h2 class="wp-block-heading">Video and Audio Attachments</h2>



<p class="wp-block-paragraph">Video and audio files follow the same attachment pattern. The <code>_wp_attachment_metadata</code> blob includes the mime type (<code>video/mp4</code>, <code>audio/mpeg</code>, etc.) and duration information. For hosting, the same constraint applies: the file must exist on the server. Self-hosted video is uncommon precisely because uploading large files through migration workflows is cumbersome. Most sites link to YouTube, Vimeo, or similar platforms instead, embedding via oEmbed which WordPress handles natively.</p>



<h2 class="wp-block-heading">Galleries</h2>



<p class="wp-block-paragraph">WordPress galleries are stored as shortcode inside the post body:</p>


<pre class="wp-block-code"><span><code class="hljs language-json">&#91;gallery ids=<span class="hljs-string">"10,12,15,18"</span>]
</code></span></pre>


<p class="wp-block-paragraph">The IDs reference attachment post IDs. As long as those attachment items exist in the WXR file with matching IDs, the gallery renders correctly after import. No special handling is needed beyond ensuring the attachment items precede the gallery post in the file.</p>



<h2 class="wp-block-heading">Common Pitfalls</h2>



<p class="wp-block-paragraph"><strong>Missing files.</strong> The most frequent failure mode: the WXR creates attachment records, but the actual files never arrive on disk. Result: broken image placeholders everywhere. Always verify that your file-transfer mechanism completes before relying on the import.</p>



<p class="wp-block-paragraph"><strong>ID collisions.</strong> If your target site already has posts, manually assigned post IDs in the WXR might collide with existing entries. Let the importer handle ID assignment by keeping IDs sequential and low-numbered, or better yet, let WordPress generate fresh IDs during import.</p>



<p class="wp-block-paragraph"><strong>Large exports.</strong> Sites with thousands of media files produce massive WXR files that can exceed PHP&#8217;s upload limits. Split large exports into smaller batches, or consider dedicated migration plugins that stream transfers more efficiently.</p>



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



<p class="wp-block-paragraph">A complete WXR file with media follows this structure: channel metadata, then all attachment items, then all post items referencing those attachments. Each attachment declares its file path via <code>_wp_attached_file</code>. Each post that uses a featured image carries <code>_thumbnail_id</code> pointing to the relevant attachment ID. Inline images live as <code>&lt;img&gt;</code> tags in the post body, either pointing to remote URLs (which the importer downloads) or to pre-placed local files.</p>



<p class="wp-block-paragraph">The format is designed around the assumption that files and metadata travel separately. Respect that split, order your items carefully, and media imports become routine rather than fragile.</p><p>The post <a href="https://riceball.com/2026/07/06/importing-images-and-media-into-wordpress-via-wxr-files/">Thaura Says: Importing Images and Media into WordPress via WXR Files</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WordPress error: Cookies are blocked or not supported by your browser. You must enable cookies to use WordPress.</title>
		<link>https://riceball.com/2024/09/05/wordpress-error-cookies-are-blocked-or-not-supported-by-your-browser-you-must-enable-cookies-to-use-wordpress/</link>
		
		<dc:creator><![CDATA[johnk]]></dc:creator>
		<pubDate>Thu, 05 Sep 2024 05:13:00 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://technote.fyi/?p=7425</guid>

					<description><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8-300x300.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8-150x150.jpg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p><p>I got this error on a multisite install I was working on. It made no sense, and found some different solutions online, but eventually found a slightly different one related to my specific problem. The fix was simple. Comment out this line: What&#8217;s going on was simple: I had subdomains on my multisite WordPress installation, [&#8230;]</p>
<p>The post <a href="https://riceball.com/2024/09/05/wordpress-error-cookies-are-blocked-or-not-supported-by-your-browser-you-must-enable-cookies-to-use-wordpress/">WordPress error: Cookies are blocked or not supported by your browser. You must enable cookies to use WordPress.</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><img width="1024" height="1024" src="https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8.jpg 1024w, https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8-300x300.jpg 300w, https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8-150x150.jpg 150w, https://riceball.com/wp-content/uploads/sites/2/2026/09/3f8db256-a6a7-450f-ba79-10b4029d2aa8-768x768.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p><p class="wp-block-paragraph">I got this error on a multisite install I was working on. It made no sense, and found some different solutions online, but eventually found a slightly different one related to my specific problem.</p>



<span id="more-21458"></span>



<p class="wp-block-paragraph">The fix was simple. Comment out this line:</p>


<pre class="wp-block-code"><span><code class="hljs language-php"><span class="hljs-comment">#define( 'SUBDOMAIN_INSTALL', true );</span></code></span></pre>


<p class="wp-block-paragraph">What&#8217;s going on was simple: I had subdomains on my multisite WordPress installation, and I&#8217;d gotten rid of all the subdomain hosts.</p>



<p class="wp-block-paragraph">Somewhere deep in the bowels of WP, a conditional was checking for a subdomain installation, and, based on that, bypassing using HTTP_HOST to set the cookie domain. Instead, it set the domain to the main site&#8217;s domain name.</p>



<p class="wp-block-paragraph">I&#8217;m not sure I have this explanation correct, because the WP code is so twisty and turny. A function like get_site may call other functions that have layers of logic to check the values of constants, variables, and other things, before returning a value.</p>



<p class="wp-block-paragraph">It&#8217;s particularly difficult with something like figuring out &#8220;what site are we looking at?&#8221; because there&#8217;s many global variables used in WordPress.</p><p>The post <a href="https://riceball.com/2024/09/05/wordpress-error-cookies-are-blocked-or-not-supported-by-your-browser-you-must-enable-cookies-to-use-wordpress/">WordPress error: Cookies are blocked or not supported by your browser. You must enable cookies to use WordPress.</a> first appeared on <a href="https://riceball.com">🍙</a>.</p>]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
