<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:georss="http://www.georss.org/georss" xmlns:media="http://search.yahoo.com/mrss/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">

<channel>
	<title>PLEASE change feed URL to http://blog.ouseful.info/feed/</title>
	<atom:link href="https://blog.ouseful.info/feed/" rel="self" type="application/rss+xml"/>
	<link>https://blog.ouseful.info</link>
	<description>In the expectation that Google will axe feedburner, please change any subscriptions to this feed to http://blog.ouseful.info/feed/</description>
	<lastBuildDate>Fri, 25 Sep 2026 17:47:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<site xmlns="com-wordpress:feed-additions:1">325417</site><cloud domain="blog.ouseful.info" path="/?rsscloud=notify" port="80" protocol="http-post" registerProcedure=""/>
<source:cloud xmlns:source="https://source.scripting.com/">https://blog.ouseful.info/?rsscloud=notify</source:cloud>
<image>
		<url>https://s2.wp.com/i/webclip.png</url>
		<title>ouseful.info, the blog…</title>
		<link>https://blog.ouseful.info</link>
	</image>
	<atom:link href="https://blog.ouseful.info/osd.xml" rel="search" title="ouseful.info, the blog..." type="application/opensearchdescription+xml"/>
	<atom:link href="https://blog.ouseful.info/?pushpress=hub" rel="hub"/>
	<xhtml:meta content="noindex" name="robots" xmlns:xhtml="http://www.w3.org/1999/xhtml"/><item>
		<title>Prerendering Javascript Powered Webpages Using Cloudflare Workers</title>
		<link>https://blog.ouseful.info/2026/09/25/prerendering-javascript-powered-webpages-using-cloudflare-workers/</link>
					<comments>https://blog.ouseful.info/2026/09/25/prerendering-javascript-powered-webpages-using-cloudflare-workers/#respond</comments>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Fri, 25 Sep 2026 17:16:07 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29414</guid>

					<description><![CDATA[Having move my storytelling and punk folk events site to its own domain at newtroubadours.org, I&#8217;ve continued using Claude to build bits of it out (other free agents just don&#8217;t seem to cut it), and also started thinking about SEO. The web has changed so much I don&#8217;t really know how discovery works any more, &#8230; <a href="https://blog.ouseful.info/2026/09/25/prerendering-javascript-powered-webpages-using-cloudflare-workers/" class="more-link">Continue reading<span class="screen-reader-text"> "Prerendering Javascript Powered Webpages Using Cloudflare&#160;Workers"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Having move my storytelling and punk folk events site to its own domain at <code><a href="https://newtroubadours.org/">newtroubadours.org</a></code>, I&#8217;ve continued using Claude to build bits of it out (other free agents just don&#8217;t seem to cut it), and also started thinking about SEO.</p>



<p class="wp-block-paragraph">The web has changed so much I don&#8217;t really know how discovery works any more, if I ever did, but I thought I&#8217;d have a poke around <a href="https://www.bing.com/webmasters/siteexplorer">Bing webmaster tools</a> and <a href="https://search.google.com/search-console/">Google Search Console</a> to see if I could at least try to get my pages indexed there, not that anyone uses search any more —and given that web search itself doesnlt really seem to work very well any more anyway&#8230;</p>



<p class="wp-block-paragraph">The pages on New Troubadours are typically paramterised — things like <a href="https://newtroubadours.org/performers.html?performer=hannah-moore">https://newtroubadours.org/performers.html?performer=hannah-moore</a> and <a href="https://newtroubadours.org/venues.html?venue=exeter-phoenix">https://newtroubadours.org/venues.html?venue=exeter-phoenix</a> — and javascript does the job of rendering the content into the page from a JSON data feed. The Google live page previewer shows that the Google crawler will have a go at running the js and then indexing the rendered page, but Bing just seems to to show the skeleton <code>body</code>, though js rendered metadata into the <code>head</code> seems to work.</p>



<p class="wp-block-paragraph">Hmmm&#8230; that means, for Bing (and hence Duck Duck Go etc), most of the content won&#8217;t make it into the index, and most of the parametrised pages, even though the parameterised URLs are declared canonical,  won&#8217;t be be discoverable&#8230;</p>



<p class="wp-block-paragraph"><em>(The metadata in the parameterised pages is a bit shonky and I should probably do something about that&#8230;)</em></p>



<p class="wp-block-paragraph">Anyway&#8230; what to do&#8230; Seems like Cloudflare to the rescue again in the form of a <a href="https://developers.cloudflare.com/browser-run/how-to/pre-render-pages/">pre-rendering Cloudflare worker</a>. I didn&#8217;t really have a model of how things work to make use of the few standlaone docs that Cloudflare provides, and very few folk blog how to recipes anymore, so I turned to chatgpt (I was out of free tokens on claude). Then went round in circles with its shonky advice, til I got the next round of free Claude tokens and got a solution&#8230;.</p>



<p class="wp-block-paragraph">&#8230;which seems to be <em>two</em> workers:</p>



<ul class="wp-block-list">
<li>one to render a page using a headless browser and generate the parsed HTML;</li>



<li>one to make that pre-rendering available to web search engines.</li>
</ul>



<p class="wp-block-paragraph">The following is pretty much all Claude, built up from the original demo pre-render code on the Cloudflare blog.</p>



<p class="wp-block-paragraph">In the Cloudflare dashboard, <em>Build</em> menu, there is a <em>Workers and Pages</em> option. From that, Create an Application (i.e. a worker), and go for the Hello World. Give it a name (I used <code>new-troubadours-prerender</code>). From its dashboard page, <em>Settings</em>, select <em>Bindings</em> and add a new one, selecting <em>Browser Run</em> from the menu and naming it <code>BROWSER</code>.</p>



<p class="wp-block-paragraph">From the worker dashboard, select edit (top right) and use code based on the Cloudflare example, tweaked to point to my domain:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
// Only render pages you control. This prevents the Worker from becoming
// an open browser-rendering proxy for arbitrary websites.
const ALLOWED_HOSTNAMES = new Set(&#91;&quot;newtroubadours.org&quot;, &quot;www.newtroubadours.org&quot;]);

const getTargetUrl = (request) =&gt; {
	const requestUrl = new URL(request.url);
	const target = requestUrl.searchParams.get(&quot;url&quot;);

	if (!target) {
		throw new Error(&quot;Missing url query parameter&quot;);
	}

	const targetUrl = new URL(target);

	// Only render HTTP(S) pages. Other protocols are not valid web pages.
	if (!&#91;&quot;http:&quot;, &quot;https:&quot;].includes(targetUrl.protocol)) {
		throw new Error(&quot;Only HTTP and HTTPS URLs are allowed&quot;);
	}

	if (!ALLOWED_HOSTNAMES.has(targetUrl.hostname)) {
		throw new Error(&quot;This hostname is not allowed&quot;);
	}

	return targetUrl;
};

const renderHtml = async (env, targetUrl) =&gt; {
	// The /content Quick Actions endpoint loads the page in Browser Run and returns
	// a JSON envelope containing the rendered HTML in the result field.
	const response = await env.BROWSER.quickAction(&quot;content&quot;, {
		url: targetUrl.toString(),
		gotoOptions: {
			waitUntil: &quot;networkidle2&quot;,
			timeout: 30000,
		},
		// If your page has a specific readiness signal, use waitForSelector
		// instead of relying only on network activity.
		// waitForSelector: { selector: &quot;&#91;data-prerender-ready=&#039;true&#039;]&quot;, timeout: 30000 },
	});

	if (!response.ok) {
		const detail = (await response.text()).slice(0, 500);
		throw new Error(`Browser Run failed with ${response.status}: ${detail}`);
	}

	const data = await response.json();

	if (!data.success || typeof data.result !== &quot;string&quot;) {
		throw new Error(&quot;Browser Run returned an unsuccessful response&quot;);
	}

	return data.result;
};

export default {
	async fetch(request, env) {
		try {
			// Read and validate the URL before sending it to Browser Run.
			const targetUrl = getTargetUrl(request);
			const html = await renderHtml(env, targetUrl);

			// Return the rendered HTML to the crawler or integration.
			return new Response(html, {
				headers: {
					&quot;content-type&quot;: &quot;text/html; charset=utf-8&quot;,
				},
			});
		} catch (error) {
			return Response.json(
				{ error: error instanceof Error ? error.message : &quot;Unknown error&quot; },
				{ status: 400 },
			);
		}
	},
};
</pre></div>


<p class="wp-block-paragraph">That does the browser rendering.</p>



<p class="wp-block-paragraph">Deploy that, go back to the workers page, and create another new one (another new application). Select hellow world template again, and give it a name (I used <code>newtroubadours-gate</code>).</p>



<p class="wp-block-paragraph">Again in the <em>Binding</em>s section (from the flow chart on the <em>Overview</em> or the <em>Settings</em> tab, this time to select a Service binding and select <code>new-troubadours-prerender</code>. This second worker is going to be fed from the first.</p>



<p class="wp-block-paragraph">Also on the <em>Settings</em> page, create a variable (an evironment variable) called <code>DEBUG_SECRET</code> and give it a value, eg <code>letmein</code>.</p>



<p class="wp-block-paragraph">This worker&#8217;s code will parse an http request for a page, and if it comes from a web crawler, will try to render the page via the renderer worker.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const CRAWLER_UA_RE = /bingbot|googlebot|duckduckbot|slurp|baiduspider|yandexbot|facebookexternalhit|twitterbot|linkedinbot|discordbot|slackbot/i;
const ASSET_EXTENSION_RE = /\.(js|mjs|css|png|jpe?g|gif|svg|webp|ico|avif|woff2?|ttf|eot|json|xml|txt|map|mp4|webm|pdf)$/i;
const CACHE_TTL_SECONDS = 60 * 60 * 24;
const DEBUG_HEADER = "x-force-render";
const PURGE_HEADER = "x-purge-cache";

function isCrawler(request) {
  return CRAWLER_UA_RE.test(request.headers.get("user-agent") || "");
}

function isAuthorized(request, env, headerName) {
  return env.DEBUG_SECRET && request.headers.get(headerName) === env.DEBUG_SECRET;
}

function looksLikeHtmlRequest(request, url) {
  if (ASSET_EXTENSION_RE.test(url.pathname)) return false;
  const dest = request.headers.get("sec-fetch-dest");
  if (dest && dest !== "document") return false;
  return true;
}

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    const cache = caches.default;
    const cacheKey = new Request(url.toString(), request);

    // Purge: delete this URL's cached render and stop — doesn't render anything.
    if (isAuthorized(request, env, PURGE_HEADER)) {
      const deleted = await cache.delete(cacheKey);
      return new Response(
        deleted ? `Purged cache for ${url.toString()}` : `No cache entry found for ${url.toString()}`,
        { status: 200 }
      );
    }

    const forced = isAuthorized(request, env, DEBUG_HEADER);

    if (!forced && (!isCrawler(request) || !looksLikeHtmlRequest(request, url))) {
      return fetch(request);
    }

    if (!forced) {
      const cached = await cache.match(cacheKey);
      if (cached) return cached;
    }

    const renderUrl = new URL("https://renderer/");
    renderUrl.searchParams.set("url", url.toString());
    const rendered = await env.RENDERER.fetch(renderUrl);

    if (!rendered.ok) {
      return fetch(request);
    }

    const response = new Response(await rendered.text(), {
      headers: {
        "content-type": "text/html; charset=utf-8",
        "cache-control": forced ? "no-store" : `public, max-age=${CACHE_TTL_SECONDS}`,
        "x-prerendered": "true",
      },
    });

    if (!forced) {
      ctx.waitUntil(cache.put(cacheKey, response.clone()));
    }
    return response;
  },
};
</pre></div>


<p class="wp-block-paragraph">It will also attempt to cache the result. If the renderer can&#8217;t return the rendered page, the original unrendered page is returned.</p>



<p class="wp-block-paragraph">This second worker also needs a <em>route</em> which passes traffic to it. In my case, (with the <code>newtroubadours.org</code> DNS already being served using Cloudlare in a <em>proxied</em> way), from the <em>Domains</em> tab, I added the route <code>newtroubadours.org/*</code>.</p>



<p class="wp-block-paragraph">And that&#8217;s it. When a request is made for a page on <code>newtroubadours.org</code>, Cloudflare intercepts it (it&#8217;s already doing some URL forwarding/rewrites, which I should blog/document) and the <code>newtroubadours-gate</code> worker checks who&#8217;s making the request. If it&#8217;s a search engine indexer, etc, it passes the request to the <code>new-troubadours-prerender</code> which tries to render the page and return the result. (All other requests simply return the original unrendered page.) The worker passes on the pre-rendered page if it can, else falls back to the original unrendered page.</p>



<p class="wp-block-paragraph">Via the gate worker, there are also a couple of diagnostics I can run by passing in my secret. If the secret is correct, I&#8217;m treated as if I were one of the allowed search engine agents.</p>



<p class="wp-block-paragraph">In the first case, inspect the rendered page:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
# View a rendered page (also caches it on Cloudflare)
curl -H "x-force-render: MYSECRET" "https://newtroubadours.org/venues.html?venue=exeter-phoenix"
</pre></div>


<p class="wp-block-paragraph">We can also purge the cached page:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
# Purge one page's cached render
curl -H "x-purge-cache: MYSECRET" "https://newtroubadours.org/venues.html?venue=exeter-phoenix"
</pre></div>


<p class="wp-block-paragraph">P.S. if the renderer has out-quota-ed itself, we can tell the search engine to bacjk off for a bit&#8230;</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
    if (!rendered.ok) {
      // Render failed (e.g. hit the daily Browser Rendering quota).
      if (crawler) {
        // Tell the crawler this response is incomplete/temporary — don't index it.
        return new Response(
          "Prerendering temporarily unavailable — please retry later.",
          {
            status: 503,
            headers: {
              "content-type": "text/plain; charset=utf-8",
              "retry-after": String(RENDER_RETRY_AFTER_SECONDS),
            },
          }
        );
      }
      // Not a crawler (e.g. a debug ping) — fall back to the plain origin page.
      return fetch(request);
    }
</pre></div>]]></content:encoded>
					
					<wfw:commentRss>https://blog.ouseful.info/2026/09/25/prerendering-javascript-powered-webpages-using-cloudflare-workers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29414</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>
	</item>
		<item>
		<title>Moving to Cloudflare DNS</title>
		<link>https://blog.ouseful.info/2026/09/09/moving-to-cloudflare-dns/</link>
					<comments>https://blog.ouseful.info/2026/09/09/moving-to-cloudflare-dns/#respond</comments>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Wed, 09 Sep 2026 15:42:38 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29392</guid>

					<description><![CDATA[A few days ago, I migrated the UK storytelling events site I&#8217;d been building on the newtroubadours subdomain of my storytelling home (montystoryteller.org) to its own domain at https://newtroubadours.org/ . (I really should have been documenting the build over the last few months — pretty much all the HTML/JS/CSS coding has been done using claude, &#8230; <a href="https://blog.ouseful.info/2026/09/09/moving-to-cloudflare-dns/" class="more-link">Continue reading<span class="screen-reader-text"> "Moving to Cloudflare&#160;DNS"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">A few days ago, I migrated the UK storytelling events site I&#8217;d been building on the <code>newtroubadours</code> subdomain of my storytelling home (<a href="https://montystoryteller.org/">montystoryteller.org</a>) to its own domain at <a href="https://newtroubadours.org/">https://newtroubadours.org/</a> .</p>



<p class="wp-block-paragraph"><em>(I really should have been documenting the build over the last few months — pretty much all the HTML/JS/CSS coding has been done using claude, with me exploring features and making the odd code nudge — but will maybe get round to retroposting the process at some point.)</em></p>



<p class="wp-block-paragraph">One of the features of the site is that it supports view switching deep links into a page. So for example, the generic storyclub page with URL <a href="https://newtroubadours.org/storyclub.html">https://newtroubadours.org/storyclub.html</a>:</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2026/09/image.png"><img width="1024" height="520" data-attachment-id="29397" data-permalink="https://blog.ouseful.info/2026/09/09/moving-to-cloudflare-dns/image-260/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2026/09/image.png" data-orig-size="2896,1472" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=1024" alt="" class="wp-image-29397" srcset="https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=2048 2048w, https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=1440 1440w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">also lets you link in to view information about a particular club using a url of the form <a href="https://newtroubadours.org/storyclub.html?club=leicesterstorytree">https://newtroubadours.org/storyclub.html?club=leicesterstorytree</a> :</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png"><img width="1024" height="983" data-attachment-id="29399" data-permalink="https://blog.ouseful.info/2026/09/09/moving-to-cloudflare-dns/image-261/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png" data-orig-size="1500,1440" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=1024" alt="" class="wp-image-29399" srcset="https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=1440 1440w, https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png 1500w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">This use of the path and URL parameters meant that when migrating the subdomain URL to a new domain, any legacy links out there would break: I&#8217;m using a Github static pages to host the site (so no server side redirects) and <em>was</em> using GoDaddy, where the domain is registered, for the DNS hosting; and whilst GoDaddy <em>would</em> be able to silently redirect from <code>newtroubadours.montystoryteller.org</code> to <code>newtroubadours.org</code>, it wouldn&#8217;t be able to pass along the path and URL argument gubbins&#8230; So even though there are very few links out there to the old site, which, along with the new domain, currently has pretty much zero search or genAI presence — <em>(can you find it?!;-) </em>— I&#8217;m still a persistent URL kind of guy and donlt want to break any links that are out there&#8230;</p>



<p class="wp-block-paragraph">Add to that the page names, which originally had the form <code>new_troubadours_storyclub.html</code>, for example, and which I wanted to simplify to the form <code>storyclub.html</code>, whilst not breaking any original links or passed through/redirected page names. Again, a need for a server side redirect.</p>



<p class="wp-block-paragraph">Or not&#8230; because a little poke around suggested that if I moved to Cloudflare free DNS hosting, I <em>would</em> be able to do the forwarding, <em>would</em> be able to pass through arguments, and <em>would</em> be able to do filename rewrites. <em>(I&#8217;ll share some details of how in another post.)</em></p>



<p class="wp-block-paragraph">And as an added bonus, I&#8217;d also be able to write some MX (email) handling records into the DNS and get free email forwarding for emails on the <code>newtroubadours.org</code> domain. <em>(Again, I&#8217;ll post more on that at a later date. Maybe&#8230;)</em></p>



<p class="wp-block-paragraph">But for now, here&#8217;s the site:</p>



<p class="wp-block-paragraph"><a href="https://newtroubadours.org/"><strong>New Troubadours</strong> — <em>Storytelling, Music &amp; Punk Poetry</em> —A comprehensive guide to traditional and performance storytelling in the UK: story clubs, storytelling shows, folk nights, punk poets, acoustic musicians, grass roots venues and touring performers across the UK. Aimed at adults; appropriate all ages</a> — <em><strong><a href="https://newtroubadours.org/">https://newtroubadours.org/</a> </strong></em></p>



<p class="wp-block-paragraph"><em>PS for any old bloggers out there, you know the game&#8230; The web is still about links, so for anyone posting &#8220;ooh, interesting to see Tony (or is it &#8216;Monty&#8217; now?) posting about a new site he has set up to promote tradtional, live, storytelling events, called New Troubadours &#8230;&#8221; etc. etc. <strong>along with a link</strong>, thanks in advance!:-)</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.ouseful.info/2026/09/09/moving-to-cloudflare-dns/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29392</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2026/09/image.png?w=1024"/>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2026/09/image-1.png?w=1024"/>
	</item>
		<item>
		<title>False GenAI Claims</title>
		<link>https://blog.ouseful.info/2026/02/08/false-genai-claims/</link>
					<comments>https://blog.ouseful.info/2026/02/08/false-genai-claims/#comments</comments>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Sun, 08 Feb 2026 21:53:34 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29387</guid>

					<description><![CDATA[Every so often I tinker with Claude.ai to refactor code. It typically makes huge claims about how many lines of code it has refactored out, but diffs rarely back that up. So I challenged, and challenged again about the false claims it made on improvements, and whether this was typical and the sort of thing &#8230; <a href="https://blog.ouseful.info/2026/02/08/false-genai-claims/" class="more-link">Continue reading<span class="screen-reader-text"> "False GenAI Claims"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Every so often I tinker with Claude.ai to refactor code. It typically makes huge claims about how many lines of code it has refactored out, but diffs rarely back that up. So I challenged, and challenged again about the false claims it made on improvements, and whether this was typical and the sort of thing it generally does for other peoples&#8217; code refactoring prompts&#8230;</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2026/02/image.png"><img width="1024" height="263" data-attachment-id="29389" data-permalink="https://blog.ouseful.info/2026/02/08/false-genai-claims/image-259/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2026/02/image.png" data-orig-size="1576,406" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=1024" alt="" class="wp-image-29389" srcset="https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=1440 1440w, https://blog.ouseful.info/wp-content/uploads/2026/02/image.png 1576w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.ouseful.info/2026/02/08/false-genai-claims/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29387</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2026/02/image.png?w=1024"/>
	</item>
		<item>
		<title>Elsewhere…</title>
		<link>https://blog.ouseful.info/2026/01/05/elsewhere/</link>
					<comments>https://blog.ouseful.info/2026/01/05/elsewhere/#comments</comments>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Mon, 05 Jan 2026 10:43:05 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29380</guid>

					<description><![CDATA[Last year, I &#8220;retired&#8221;, taking the early option to leave via a mutual resignation scheme. The break was pretty much a clean one, except for a visiting position to see out getting JupyterLite and browser executed R code deployed to support a student in a secure environment (one of His Majesty&#8217;s pleasure facilities). I&#8217;m not &#8230; <a href="https://blog.ouseful.info/2026/01/05/elsewhere/" class="more-link">Continue reading<span class="screen-reader-text"> "Elsewhere&#8230;"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Last year, I &#8220;retired&#8221;, taking the early option to leave via a mutual resignation scheme.</p>



<p class="wp-block-paragraph">The break was pretty much a clean one, except for a visiting position to see out getting JupyterLite and browser executed R code deployed to support a student in a secure environment (one of His Majesty&#8217;s pleasure facilities).</p>



<p class="wp-block-paragraph">I&#8217;m not sure if any other modules are aware that such a thing is possible — depending on which direction the planned update to the data analysis and management module went, there is no reason at all why that couldn&#8217;t have offered all the student practical activities as runnable via and within the browser, and as such, been offerable from a technical point of view, and from what I&#8217;ve seen of many of the science and other computing modules that include coding activities, they could also in principle execute code solely within the browser (which includes on smart phones) — but I hope that we at least manage to set a precedent showing that it is  technically possible to support student coding activities inside such environments. (The OU is a bit like the old NASA model, where it&#8217;s difficiult to fly things in space that haven&#8217;t already been flown. The very few successes I had in the OU were setting precedents&#8230;)</p>



<p class="wp-block-paragraph">Anyway — this blog is largely now defunt. I was minded to post very briefly just now on a blog I haven&#8217;t looked at for getting on for a decade, the <a href="https://digitalworlds.wordpress.com/">Digital Worlds — Distored Reality</a> blog — <em><a href="https://digitalworlds.wordpress.com/2026/01/05/the-web-as-alternate-reality/">The Web as Alternate Reality</a></em> — and may start to use that as a dumping ground to further document the nightmare descent of that parallel nonsense world, but I spend most of my time now in the world of story.</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2026/01/image.png"><img loading="lazy" width="723" height="1024" data-attachment-id="29384" data-permalink="https://blog.ouseful.info/2026/01/05/elsewhere/image-258/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2026/01/image.png" data-orig-size="1138,1612" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=723" src="https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=723" alt="" class="wp-image-29384" srcset="https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=723 723w, https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=106 106w, https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=212 212w, https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2026/01/image.png 1138w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></figure>



<p class="wp-block-paragraph"><br> </p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.ouseful.info/2026/01/05/elsewhere/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29380</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2026/01/image.png?w=723"/>
	</item>
		<item>
		<title>If you must…</title>
		<link>https://blog.ouseful.info/2025/12/01/if-you-must/</link>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Mon, 01 Dec 2025 15:31:13 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29373</guid>

					<description><![CDATA[I admit to using genAI for coding but I&#8217;m still reluctant to engage with in pretty much any other context except a bit of OCR (particularly with not-quite-Roman alphabets such as Old and Middle English texts), but eben then with a lot of care (genOCR doesnlt like minority positions, preferring the statistically most likely next &#8230; <a href="https://blog.ouseful.info/2025/12/01/if-you-must/" class="more-link">Continue reading<span class="screen-reader-text"> "If you must&#8230;"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I admit to using genAI for coding but I&#8217;m still reluctant to engage with in pretty much any other context except a bit of OCR (particularly with not-quite-Roman alphabets such as Old and Middle English texts), but eben then with a lot of care (genOCR doesnlt like minority positions, preferring the statistically most likely next token; for a digital humanities scholar that could potentially lead to an interesting way of probing biases, but as I don&#8217;t want to contribute to the genAI world, even by being critical of it (which admits of it) &#8217;nuff said.</p>



<p class="wp-block-paragraph"><em>That said, if you must, be critical. Paul Bradshaw is as good a read as anyone I follow in my feeds on being measured in how you make use of such tools. For example, <a href="https://onlinejournalismblog.com/2025/11/28/4-ways-you-can-role-play-with-ai/">4 ways you can ‘role play’ with AI</a> and <a href="https://onlinejournalismblog.com/2025/12/02/journey-prompts-and-destination-prompts-how-to-avoid-becoming-deskilled-when-using-ai/">“Journey prompts” and “destination prompts”: how to avoid becoming deskilled when using AI</a>.</em></p>



<p class="wp-block-paragraph">But even so, pretty much everything about it still all leaves me cold (not even considering the consequences for financial markets in the short term, then social consequences of the bail outs for those who had in the crash aftermath), and I see no real <em>fun</em> in exploring this tech at all, just the potential for misdirection, manipulation, misapprehension and lots of other negatives beginning with <em>m</em>.</p>



<p class="wp-block-paragraph">I&#8217;m so glad I got of out working for an org that, as with most others, feels obliged to engage with it. The tech I embraced over the years, I knew where it fell short / didn&#8217;t cope well, I had a sense of whwre it was likely to go over the next couple of years (and into the five year + horizon that OU courses were developoed and had to deliver into), and I understood why that meant other folk felt they couldn&#8217;t use it (because it didn&#8217;t&#8221;always&#8221; work, or didn&#8217;t necessarily work &#8220;100% properly&#8221;, even if you knew where / how it wouldn&#8217;t work and what its failure modes were). Now, pretty much everyone is <em>embracing</em> something that doesn&#8217;t work &#8220;100% properly&#8221;, etc., and for which it can be really hard to get a proper sense or understanding of what and how it&#8217;s broken. Which it is. Innately. And they&#8217;re rushing into a fog bank of uncertainty about how it will develop and where the risks / harms are, not forgetting that the techbro cos. are using the tobacco bros. playbook when it comes to, yeah, well, harm, whatever. Tobacco / sugar etc. crossed paths with biological evolution. Solcial media has been messing with psychology (which leadds to personal and social harm at the individual and family level). GenAI is messing with culture, which knackers things at a generational level. Turn it off.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29373</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>
	</item>
		<item>
		<title>Onto Amazon with some Island Tales storynotes</title>
		<link>https://blog.ouseful.info/2025/10/28/onto-amazon-with-some-island-tales-storynotes/</link>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Tue, 28 Oct 2025 17:41:46 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29359</guid>

					<description><![CDATA[Noticing that Martin has announced the publication of his first novel — Publication Day! — along with a professionally designed cover, I thlought I might as well mention that I&#8217;ve also announced on my storytelling persona blog that I&#8217;ve started putting together workflows for getting my storynotes onto Amazon for distribution as print-on-demand paperbacks or &#8230; <a href="https://blog.ouseful.info/2025/10/28/onto-amazon-with-some-island-tales-storynotes/" class="more-link">Continue reading<span class="screen-reader-text"> "Onto Amazon with some Island Tales&#160;storynotes"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Noticing that Martin has announced the publication of  his first novel — <a href="https://blog.edtechie.net/fiction-writing/publication-day/">Publication Day!</a> — along with <a href="https://blog.edtechie.net/book-writing/ai-vs-human-designed-book-covers/">a professionally designed cover</a>, I thlought I might as well mention that I&#8217;ve also <a href="https://montystoryteller.org/blog/2025-10-28_island_tales_soft_launch/">announced on my storytelling persona blog</a> that I&#8217;ve started putting together workflows for getting my storynotes onto Amazon for distribution as print-on-demand paperbacks or as Kindle ebooks.</p>



<p class="wp-block-paragraph">This includes scripted book cover generation using GOFC — <em>good old fashioned code</em> — that runs the same way each time, and a quarto publishing route that churns quarto markdown into LaTeX and then PDF or epub format.</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg"><img loading="lazy" width="1024" height="837" data-attachment-id="29365" data-permalink="https://blog.ouseful.info/2025/10/28/onto-amazon-with-some-island-tales-storynotes/island_tales_first_front/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg" data-orig-size="1875,1533" data-comments-opened="1" data-image-meta="{&quot;orientation&quot;:&quot;1&quot;}" data-image-title="island_tales_first_front" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=1024" alt="" class="wp-image-29365" srcset="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=1440 1440w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg 1875w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">Two or three years ago I used Lulu to run off a few copies of an earlier version these booklets using a Jupyer Book initiated production route, but the Amazon pricing is better when buying author copies that the Lulu route, so that was another reason to switch to Amazon.</p>



<p class="wp-block-paragraph"><em>Ideally, I&#8217;d do a larger print run with a printing house, but that requires an up-front order in the hundreds to get the price breaks, which not only means an up-front investment in the hundreds of squids for each booklet, but also storage and sales outlet finding problem, as well as shipping and logistics costs and overheads.</em> </p>



<p class="wp-block-paragraph">Along the way, I did use a bit of AI assist to customise some LaTeX includes to modify the quarto default formatting, to help with some of the regexes in creating a script to convert my legacy Jupyter Book MyST style markdown to qmd, and to fettle image production, such as resizing, autocropping and transparency handling using ImageMagick CLI commands.</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg"><img loading="lazy" width="1024" height="790" data-attachment-id="29367" data-permalink="https://blog.ouseful.info/2025/10/28/onto-amazon-with-some-island-tales-storynotes/island_tales_first_back/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg" data-orig-size="1935,1494" data-comments-opened="1" data-image-meta="{&quot;orientation&quot;:&quot;1&quot;}" data-image-title="island_tales_first_back" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=1024" alt="" class="wp-image-29367" srcset="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=1440 1440w, https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg 1935w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">I&#8217;ve also been exploring generating map related images&#8230;</p>



<p class="wp-block-paragraph">Anyway, the books are in a series — <em><a href="https://www.amazon.co.uk/dp/B0FVYBY4V8">Island Tales</a></em> — and are available as both ebook and paperback from Amazon:</p>



<ul class="wp-block-list">
<li><em>A Legend of Godshill</em> reproduces Elder&#8217;s version of the tale as well as my take on it, Percy Stone&#8217;s lay, excerpts from 19th century tourist guides, and a biographical note on Abraham Elder; <a href="http://(https://www.amazon.co.uk/Legend-Puckaster-Cove-Island-Tales/dp/B0FPN7VCVK/">available here</a>.</li>



<li><em>A Legend of Puckaster Cove</em> includes Elder&#8217;s original version of the tale, something approximating my first retelling of it a couple or more years ago, and some historical notes that once again pull on 19th century travel guides to the Island; <a href="https://www.amazon.co.uk/Legend-Godshill-Island-Tales/dp/B0FPRFD1QS/">available here</a>.<br></li>
</ul>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29359</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_front.jpg?w=1024"/>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/10/island_tales_first_back.jpg?w=1024"/>
	</item>
		<item>
		<title>Running containers on Mac without Docker</title>
		<link>https://blog.ouseful.info/2025/10/06/running-containers-on-mac-without-docker/</link>
					<comments>https://blog.ouseful.info/2025/10/06/running-containers-on-mac-without-docker/#comments</comments>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Mon, 06 Oct 2025 10:23:21 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29354</guid>

					<description><![CDATA[Somehow I missed this, I guess in my run up to &#8220;retirement&#8221;&#8230; container is a tool that you can use to create and run Linux containers as lightweight virtual machines on your Mac. It&#8217;s written in Swift, and optimized for Apple silicon. A native — and official — Apple CLI tool for running containers&#8230; https://github.com/apple/container]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Somehow I missed this, I guess in my run up to &#8220;retirement&#8221;&#8230;  <em><code>container</code> is a tool that you can use to create and run Linux containers as lightweight virtual machines on your Mac. It&#8217;s written in Swift, and optimized for Apple silicon.</em> A native — and official — Apple CLI tool for running containers&#8230; <a href="https://github.com/apple/container">https://github.com/apple/container</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.ouseful.info/2025/10/06/running-containers-on-mac-without-docker/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29354</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>
	</item>
		<item>
		<title>AI shortcuts to nowhere…</title>
		<link>https://blog.ouseful.info/2025/10/01/ai-shortcuts-to-nowhere/</link>
					<comments>https://blog.ouseful.info/2025/10/01/ai-shortcuts-to-nowhere/#comments</comments>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Wed, 01 Oct 2025 15:20:54 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29350</guid>

					<description><![CDATA[Things like https://www.oreilly.com/radar/the-cognitive-shortcut-paradox/ (AI used by novices may give answers but means they miss out on learning etc.) put me in mind of things like telly talent shows, where folk are transported from nowhere to &#8220;stardom&#8221; in an afternoon, rather than spending years putting in the hours, gigging to no-one, and learning craft.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Things like <a href="https://www.oreilly.com/radar/the-cognitive-shortcut-paradox/">https://www.oreilly.com/radar/the-cognitive-shortcut-paradox/</a> (AI used by novices may give answers but means they miss out on learning etc.) put me in mind of things like telly talent shows, where folk are transported from nowhere to &#8220;stardom&#8221; in an afternoon, rather than spending years putting in the hours, gigging to no-one, and learning craft.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.ouseful.info/2025/10/01/ai-shortcuts-to-nowhere/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29350</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>
	</item>
		<item>
		<title>Moving to quarto and LaTeX…</title>
		<link>https://blog.ouseful.info/2025/09/23/moving-to-quarto-and-latex/</link>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Tue, 23 Sep 2025 11:21:28 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29334</guid>

					<description><![CDATA[For several years, I&#8217;ve been creating &#8220;storynotes&#8221;, collections of story variants for particualr folk tales, as well as collections of news stories contemprary to particular historical events that I can then use as the basis for developing my own accounts, and then stories, around particular events. Now that I&#8217;m &#8220;retired&#8221;, I&#8217;m also looking for merch &#8230; <a href="https://blog.ouseful.info/2025/09/23/moving-to-quarto-and-latex/" class="more-link">Continue reading<span class="screen-reader-text"> "Moving to quarto and&#160;LaTeX&#8230;"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">For several years, I&#8217;ve been creating &#8220;storynotes&#8221;, collections of story variants for particualr folk tales, as well as collections of news stories contemprary to particular historical events that I can then use as the basis for developing my own <em>accounts</em>, and then <em>stories</em>, around particular events.</p>



<p class="wp-block-paragraph">Now that I&#8217;m &#8220;retired&#8221;, I&#8217;m also looking for merch opportunities to try to claw back some of the costs associated with telling tales (a 2-3 hour folk night or open mic, at a pint of shandy every 40-50 minutes, = 15 squids of cost&#8230;). So I&#8217;ve started looking at producing booklets I can print-on-demand and then sell for a fiver.</p>



<p class="wp-block-paragraph">I started off with a couple of runs using Lulu, (which I&#8217;d used to test publish some Island Tales storynotes a couple of years ago), using the Lulu book cover desginer to generate simple covers, but now I&#8217;m looking at Amazon, which is as cheap, if not cheaper, for one-off print on demand, plus it has the global reach in terms of marketing not just print-on-demand books but also ebook variants.</p>



<p class="wp-block-paragraph">Up till now I&#8217;ve been using Jupyter Book (sphinx) but publishing, but Jupyter Book never really met its early promise, is a faff when trying to generate non-HTML outputs (PDF, docx, e-book), and, as I understand it, is in the process of moving to a myst/node rather sphinx/python build process. So instead, I&#8217;m moving to quarto, which is well-supported and rich featured, although I haven&#8217;t yet worked out a clean way of generating an index. <em>(That said, the epub doesnlt seem to work for me with Amazon KDP; instaed, I have to load a docx into the KDP app, then generate the KPF file. That may simply be down to how i config the epub in the quarto build, or they may be some other issue.)</em></p>



<p class="wp-block-paragraph">As my main output will be PDF, I&#8217;ve started hacking together LaTeX templates, admittedly with quite a lot of support from Claude.ai and ChatGPT, partly because they can generated the code quick than I can, partly because I don&#8217;t (yet) know how to write LaTex all that well.</p>



<p class="wp-block-paragraph">For the inner book content, I&#8217;ve started putting together core templates for the different booklets I want to strat producing, handling things like page layout, headers, header undlerines, page numbering etc. (I&#8217;ve still not settled on if / how I want to use footnotes; I currently inline footnotes&#8230;)</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/09/image.png"><img loading="lazy" width="1024" height="114" data-attachment-id="29341" data-permalink="https://blog.ouseful.info/2025/09/23/moving-to-quarto-and-latex/image-254/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image.png" data-orig-size="1310,146" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=1024" alt="" class="wp-image-29341" srcset="https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2025/09/image.png 1310w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">I also have templates for blurb pages (copyright / about) and title pages etc.</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png"><img loading="lazy" width="974" height="962" data-attachment-id="29343" data-permalink="https://blog.ouseful.info/2025/09/23/moving-to-quarto-and-latex/image-255/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png" data-orig-size="974,962" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png?w=974" alt="" class="wp-image-29343" srcset="https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png 974w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png?w=768 768w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">For the covers, I&#8217;m using LaTeX templates that allow me to fix a design and then customise it with text, fine-tuned positing, and colour themes. (The idea is that books will be in series, and I want each series to have a similar look and feel.</p>



<p class="wp-block-paragraph">As part of the cover, I can also (optinally) overlay debug lines.</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png"><img loading="lazy" width="1024" height="762" data-attachment-id="29345" data-permalink="https://blog.ouseful.info/2025/09/23/moving-to-quarto-and-latex/image-256/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png" data-orig-size="1354,1008" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=1024" alt="" class="wp-image-29345" srcset="https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png 1354w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">To improve reproducibility further, I&#8217;m using customised <code>.devcontainer</code> in VS Code for the build process so that I can build a book or cover independently of whatever machine I&#8217;m on. (This extends to making sure the fonts I want to use are available. My original tests were done on a Mac and I&#8217;d unwittingly used fonts that ship with Mac but are commercial fonts. Adding fonts into the build process and then using those means I keep that part of the build reporducible too.)</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png"><img loading="lazy" width="1024" height="805" data-attachment-id="29347" data-permalink="https://blog.ouseful.info/2025/09/23/moving-to-quarto-and-latex/image-257/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png" data-orig-size="1272,1000" data-comments-opened="1" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=1024" alt="" class="wp-image-29347" srcset="https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png 1272w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">For the Amazon publishing, the cover needs to mount an ISBN. Again, this is configurable.</p>



<p class="wp-block-paragraph">The designs are rather utlitiarian (I&#8217;ve only just started out on this process too&#8230;), but then, so are the designs in the cover design tools on Lulu and Amazon.</p>



<p class="wp-block-paragraph">The most important point, though, is that while I used genAI to help write the LaTeX, everyhting in the publishing process is scripted and tuned using static configuration files. The process is idempotent. I am in control. There is no genAI in the actual publication route that is likely to give a different result every time you run it.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29334</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/09/image.png?w=1024"/>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/09/image-1.png?w=974"/>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/09/image-2.png?w=1024"/>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/09/image-3.png?w=1024"/>
	</item>
		<item>
		<title>A new website, built with Hugo</title>
		<link>https://blog.ouseful.info/2025/08/27/a-new-website-built-with-hugo/</link>
		
		<dc:creator><![CDATA[Tony Hirst]]></dc:creator>
		<pubDate>Wed, 27 Aug 2025 11:15:48 +0000</pubDate>
				<category><![CDATA[Anything you want]]></category>
		<guid isPermaLink="false">http://blog.ouseful.info/?p=29326</guid>

					<description><![CDATA[Being now rather tired of WordPress and the requirements for hosting, I thought I&#8217;d build my personal stroytelling website using Hugo. I&#8217;ve not looked at Hugo before, but the Hugoplate template made things pretty easy to get going, and with some approriately crafted prompts to the free Claude.ai plan, which seems happy to pull in &#8230; <a href="https://blog.ouseful.info/2025/08/27/a-new-website-built-with-hugo/" class="more-link">Continue reading<span class="screen-reader-text"> "A new website, built with&#160;Hugo"</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Being now rather tired of WordPress and the requirements for hosting, I thought I&#8217;d build my personal stroytelling website using Hugo. I&#8217;ve not looked at Hugo before, but the Hugoplate template made things pretty easy to get going, and with some approriately crafted prompts to the free Claude.ai plan, which seems happy to pull in content from Github repos and elsewhere as additional context, I got enough cribs to make a couple of customistions that I needed for my site.</p>



<p class="wp-block-paragraph">Anywhere, it&#8217;s here at the relaunched <a href="https://montystoryteller.org">montystoryteller.org</a> site&#8230;</p>



<figure class="wp-block-image size-large"><a href="https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png"><img loading="lazy" width="1024" height="667" data-attachment-id="29330" data-permalink="https://blog.ouseful.info/2025/08/27/a-new-website-built-with-hugo/montystoryteller_website_screenshot/" data-orig-file="https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png" data-orig-size="2338,1524" data-comments-opened="1" data-image-title="montystoryteller_website_screenshot" data-image-description="" data-image-caption="" data-large-file="https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=840" src="https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=1024" alt="" class="wp-image-29330" srcset="https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=1024 1024w, https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=2048 2048w, https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=150 150w, https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=300 300w, https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=768 768w, https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=1440 1440w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">Next up, I&#8217;m pondering porting the <em>tistales.org.uk</em> site away from WordPress so I can drop the Reclaim Hosting plan and save pennies now I&#8217;m &#8220;retired&#8221;, particulalry given they&#8217;re stopping email hosting (which has been really unreliable for ages what with being spam blocked etc. Small email providers stand no chance&#8230;); <a href="https://github.com/ashishb/wp2hugo">wp2hugo</a> looks like it might be interesting for this, but that&#8217;s for another day — I&#8217;m really trying to limnit my screentime, and have already spent too long at the keyboard today&#8230;</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">29326</post-id>
		<media:content medium="image" url="https://0.gravatar.com/avatar/9d360a589cccae385a140459c46061e54b63a42931e216dfbe6c48d6a1c0c2fb?s=96&amp;d=https%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content medium="image" url="https://blog.ouseful.info/wp-content/uploads/2025/08/montystoryteller_website_screenshot.png?w=1024"/>
	</item>
	</channel>
</rss>