<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/subscribe/styles.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Robb Knight • Posts • Atom Feed</title>
  <subtitle>Maker of web things, Lego builder, sometimes blogger, sporadic pizzaiolo, fortnightly podcaster. Cat dad and human dad.</subtitle>
  <link href="https://rknight.me/subscribe/posts/atom.xml" rel="self" />
  <updated>2024-02-21T20:47:27Z</updated>
  <id>https://rknight.me/subscribe/posts/atom.xml</id>
  <author>
    <name>Robb Knight</name>
    <uri>http://rknight.me</uri>
  </author>
  
  <entry>
    <title>Using Eleventy to Gobble Up Everything I Do Online</title>
    <link href="https://rknight.me/blog/using-eleventy-to-gobble-up-everything-i-do-online/"/>
    <updated>2024-02-21T20:47:27Z</updated>
    <id>https://rknight.me/blog/using-eleventy-to-gobble-up-everything-i-do-online/</id>
    <content type="html">&lt;p&gt;This post is adapted from the talk I did at &lt;a href=&quot;https://11tymeetup.dev/events/ep-18-building-community-and-online-activity/&quot;&gt;the Eleventy Meetup&lt;/a&gt;. You can also &lt;a href=&quot;https://www.youtube.com/watch?v=e_87IF7KGgo&quot;&gt;watch the talk on YouTube&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is what I look like when I try to explain how my website works:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pepesilvia-11ty.jpg&quot; alt=&quot;Me explaining how my website works&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are three main parts that make up this website: &lt;a href=&quot;https://echo.rknight.me&quot;&gt;Echo&lt;/a&gt;, &lt;a href=&quot;https://github.com/rknightuk/api&quot;&gt;my API server&lt;/a&gt; (and Eleventy data files), and standard Markdown files.&lt;/p&gt;
&lt;h3&gt;Echo and Custom Post Text&lt;/h3&gt;
&lt;p&gt;Echo started life as a cross-posting tool to post from an RSS feed to Micro.blog. Since then I&#39;ve added support for webhooks, Mastodon, &lt;a href=&quot;https://www.linkace.org&quot;&gt;LinkAce&lt;/a&gt;, &lt;a href=&quot;https://omnivore.app/home&quot;&gt;Omnivore&lt;/a&gt;, and GitHub. If we take Letterboxd as an example. I &lt;a href=&quot;https://letterboxd.com/rknightuk/film/the-super-mario-bros-movie/&quot;&gt;post a review&lt;/a&gt; on there that gets added to &lt;a href=&quot;http://letterboxd.com/rknightuk/rss&quot;&gt;the RSS feed&lt;/a&gt;. Echo will fetch that new review and create a new post in the git repository on GitHub, the site rebuilds, and the review now &lt;a href=&quot;/almanac/movies/2024-02-16-the-super-mario-bros-movie/&quot;&gt;exists as a post&lt;/a&gt;. I then use Echo &lt;em&gt;again&lt;/em&gt; to read the RSS feed of my movie reviews and post that &lt;a href=&quot;https://social.lol/@robb/111943358114444166&quot;&gt;to Mastodon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/git-commit-and-mastodon.jpg&quot; alt=&quot;The file commited on GitHub and the post that went to Mastodon&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Rather than just send the title and link to Mastodon, I prefer to include some (or all) of the post content with the toot as well. To do this, I added a &lt;code&gt;makeTootText&lt;/code&gt; filter and a &lt;code&gt;mastodonCounter&lt;/code&gt; function which I got &lt;a href=&quot;https://github.com/mastodon/mastodon/blob/5d5c0f4f4358f4349d9e2db59cf90b1f5de24e81/app/javascript/mastodon/features/compose/util/url_regex.js&quot;&gt;from the Mastodon project&lt;/a&gt;. This filter check the type of post it is, checks if it will fit on Mastodon&#39;s limit of 500 characters, then adds it to the &lt;code&gt;_knightposse&lt;/code&gt; object in the JSON feed.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;_knightposse&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;about&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/about/colophon/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;⭐ Apple is twisting the truth by @manton@manton.org https://www.manton.org/2024/02/16/apple-is-lying.html\n\n\&quot;For example, to comply with the DMA’s requirements on sideloading or marketplaces, Apple could’ve chosen a system similar to installing apps from TestFlight. This would require zero new APIs for developers, just as TestFlight itself has no new APIs when building a beta version of your app.\&quot;\n\nAnother DMA link. All of this is just gross and completely ignores what the DMA was attempting to do.\n\n📌 https://rknight.me/links/apple-is-twisting-the-truth/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the moment I only customise &lt;a href=&quot;/links&quot;&gt;link&lt;/a&gt; and &lt;a href=&quot;/almanac&quot;&gt;Almanac&lt;/a&gt; posts so the filter returns just the title and link if the post isn&#39;t one of those types:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; permalink &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://rknight.me&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;permalink&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;link&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;almanac&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;layout&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;permalink&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then use &lt;a href=&quot;https://www.npmjs.com/package/cheerio&quot;&gt;Cheerio&lt;/a&gt; to get all the content as plain text which I combine with the title and link to check if it will fit on Mastodon. For Almanac posts, the filter also adds year, season, or platform information as relevant:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; $ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cheerio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;div id=&quot;content&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/div&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; allText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#content&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;layout &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;almanac&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;_getTypeEmoji&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;_getVerb&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;season &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Season &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;season&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;platform &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;platform&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;permalink&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentWithReview &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;allText&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mastodonCount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMastodonLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contentWithReview&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; contentWithReview&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; content&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For link posts, I mention the author if they have Mastodon as well as extracting any quotes so I can include those even if my full commentary won&#39;t fit:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mastoUsername &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mastodon&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;author&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mastodon&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    mastoUsername &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;host&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;⭐ &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;mastoUsername &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;mastoUsername&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;link&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;blockquote&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    allText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; allText&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentWithAllText &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;allText&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n\n📌 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;permalink&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; firstQuote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;blockquote&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; contentWithFirstQuote &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n\n&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;firstQuote&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n\n📌 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;permalink&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mastodonCount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMastodonLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contentWithAllText&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; contentWithAllText&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mastodonCount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getMastodonLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;contentWithFirstQuote&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; contentWithFirstQuote&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n\n📌 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;permalink&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; content&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my config in &lt;a href=&quot;https://echo.rknight.me&quot;&gt;Echo&lt;/a&gt; I can then use that data from the JSON feed for the new post on Mastodon:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;rknightalmanac&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;feed&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://rknight.me/subscribe/almanac/feed.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;skipConversion&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;SERVICES&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MASTODON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; presets&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;default&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;getId&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function-variable function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_knightposse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token literal-property property&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date_published&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;API Server and Data Files&lt;/h3&gt;
&lt;p&gt;I have an &lt;a href=&quot;https://api.rknight.me/&quot;&gt;API &amp;quot;server&amp;quot;&lt;/a&gt; of sorts which collects information on various schedules depending on the service. To call it a server is a bit misleading, it&#39;s more like a bucket of node scripts that write JSON files. It fetches from multiple services for me including &lt;a href=&quot;https://overcast.fm&quot;&gt;Overcast&lt;/a&gt;, &lt;a href=&quot;https://www.last.fm/user/rknightuk&quot;&gt;Last.fm&lt;/a&gt;, &lt;a href=&quot;https://social.lol/@robb&quot;&gt;Mastodon&lt;/a&gt;, and &lt;a href=&quot;https://brickset.com/sets/ownedby-rknightuk&quot;&gt;Brickset&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The schedule is set by cron jobs and uses a makefile to define which jobs run when:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;monday:&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/lastfm.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/books.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/psn.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/tv.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/links.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; now/generate.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; now/update.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; utils/backup.js&lt;br /&gt;sunday:&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/overcast/backup.js&lt;br /&gt;	python3 /home/forge/api.rknight.me/services/overcast/fetcher/fetch.py&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/overcast/parser/run.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/overcast/now.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; now/generate.js&lt;br /&gt;daily:&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/github.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/other.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; now/generate.js&lt;br /&gt;hourly:&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/webmentions.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/mastodon.js&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/micro.js&lt;br /&gt;ten:&lt;br /&gt;	&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /home/forge/api.rknight.me&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; services/discussion.js&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://brickset.com/&quot;&gt;Brickset&lt;/a&gt; is a site for managing and tracking a Lego collection. I have somewhere around 200 sets but along with tracking them, I want to show them on my &lt;a href=&quot;/collections/lego&quot;&gt;collections page&lt;/a&gt; rather than linking out to my profile there. I login, fetch my set collection, then map that to a nicer format for handling in Eleventy.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BRICKSET_USERNAME&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BRICKSET_PASSWORD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BRICKSET_API_KEY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://brickset.com/api/v3.asmx/login?apiKey=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BRICKSET_API_KEY&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;amp;username=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BRICKSET_USERNAME&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;amp;password=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BRICKSET_PASSWORD&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ok&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userHash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; setResponse &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://brickset.com/api/v3.asmx/getSets?apiKey=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BRICKSET_API_KEY&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;amp;userHash=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;userHash&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;amp;params={&quot;owned&quot;:1,&quot;pageSize&quot;:500,&quot;orderBy&quot;:&quot;YearFrom&quot;,&quot;orderBy&quot;:&quot;Theme&quot;}&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; rawData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; setResponse&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// format the data&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This data is then written out to &lt;code&gt;api/brickset.json&lt;/code&gt; and pulled into my site when it&#39;s built.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/lego-collection-example.jpg&quot; alt=&quot;A sample of my Lego collection&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Each service on the API works in a similar way: fetch the data, format it, then write it to a file. I won&#39;t go through all of them here but you can &lt;a href=&quot;https://github.com/rknightuk/api&quot;&gt;view the source code here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To give you some idea of how much I pull into my site, here is my &lt;code&gt;_data&lt;/code&gt; directory. Each one of these represents either external data or hard-coded lists of things like projects:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;└── data/&lt;br /&gt;    ├── site/&lt;br /&gt;    │   ├── config.js&lt;br /&gt;    │   ├── explore.js&lt;br /&gt;    │   ├── footerpages.js&lt;br /&gt;    │   ├── links.js&lt;br /&gt;    │   ├── production.js&lt;br /&gt;    │   ├── projects.json&lt;br /&gt;    │   └── save.js&lt;br /&gt;    ├── adn.json&lt;br /&gt;    ├── alfred.js&lt;br /&gt;    ├── blogroll.js&lt;br /&gt;    ├── discussion.js&lt;br /&gt;    ├── fathom.js&lt;br /&gt;    ├── games.json&lt;br /&gt;    ├── micro.js&lt;br /&gt;    ├── microboosts.js&lt;br /&gt;    ├── mypodcasts.js&lt;br /&gt;    ├── now.js&lt;br /&gt;    ├── podcasts.js&lt;br /&gt;    ├── podroll.js&lt;br /&gt;    └── status.js&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which brings me to my next point about using data files: any page that has a list of &lt;em&gt;things&lt;/em&gt; I tend to use data files instead of writing them in the page itself. For example, my &lt;a href=&quot;/projects&quot;&gt;projects page&lt;/a&gt; has a large amount of projects listed so I keep a JSON data file with all the projects and render them out from that.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string-property property&quot;&gt;&quot;featured&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Humonize!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://hum.rknight.me&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;desc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Humonize forever&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;humonize.png&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string-property property&quot;&gt;&quot;current&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Alfred Workflows&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/alfred-workflows&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;desc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;All of my Alfred Workflows&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;alfred.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;JS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;AppleScript&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Python&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string-property property&quot;&gt;&quot;podcasts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Ruminate&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://ruminatepodcast.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;desc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A podcast about what&#39;s on our minds&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ruminate.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;11ty&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Audio&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string-property property&quot;&gt;&quot;profile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;omg.log cli&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;link&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/rknightuk/omglolcli&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;desc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A CLI tool for using omg.lol&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;omgcli.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;tags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;JS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in &lt;code&gt;projects.njk&lt;/code&gt; I can loop through that data and output the HTML as needed:&lt;/p&gt;
&lt;pre class=&quot;language-hbs&quot;&gt;&lt;code class=&quot;language-hbs&quot;&gt;&lt;span class=&quot;token block keyword&quot;&gt;###&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;Current&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cards&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;project&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;projects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;project-card.njk&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endfor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/example-projects.jpg&quot; alt=&quot;Sample of the projects output&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Markdown files and the Command Line Tool&lt;/h3&gt;
&lt;p&gt;The final component of the site is markdown files. These are used for &lt;a href=&quot;/blog&quot;&gt;blog posts&lt;/a&gt;, &lt;a href=&quot;/links&quot;&gt;link posts&lt;/a&gt;, &lt;a href=&quot;/almanac&quot;&gt;media reviews in Almanac&lt;/a&gt;, and the &lt;a href=&quot;/log&quot;&gt;site changelog&lt;/a&gt;. One of the things that&#39;s difficult with different post types like this is making sure to input all the correct metadata that&#39;s required for each type. For example, a blog post looks like this with title, tags, and an excerpt:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;---&lt;br /&gt;title: &quot;Using Eleventy to Gobble Up Everything I Do Online&quot;&lt;br /&gt;permalink: /blog/using-eleventy-to-gobble-up-everything-i-do-online/index.html&lt;br /&gt;date: 2024-02-20T16:47:27.981Z&lt;br /&gt;excerpt: &quot;A blog post about how my site works based on a talk I did at the Eleventy meetup&quot;&lt;br /&gt;layout: post&lt;br /&gt;tags:&lt;br /&gt;    - Development&lt;br /&gt;    - Eleventy&lt;br /&gt;---&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Link posts, on the other hand, have information about the author and the article being linked:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;---&lt;br /&gt;title: &quot;Vision Accessibility on Apple Vision Pro&quot;&lt;br /&gt;permalink: /links/vision-accessibility-on-apple-vision-pro/index.html&lt;br /&gt;link: https://zmknox.com/2024/02/18/vision-accessibility-on-apple-vision-pro&lt;br /&gt;date: 2024-02-20T10:54:56.550Z&lt;br /&gt;author: &lt;br /&gt;  name: Zach Knox&lt;br /&gt;  web: https://zmknox.com&lt;br /&gt;  feed: https://zmknox.com/feed.xml&lt;br /&gt;  mastodon: https://snailedit.social/@zmk&lt;br /&gt;---&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To help with this, I built a CLI tool in Node. The tool uses a combination of &lt;a href=&quot;https://www.npmjs.com/package/commander&quot;&gt;Commander&lt;/a&gt; to create the interface, and &lt;a href=&quot;https://www.npmjs.com/package/inquirer&quot;&gt;@inquirer&lt;/a&gt; to ask questions and grab that data. When I run it, I am presented with a number of options:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;............................................................&lt;br /&gt;............................................................&lt;br /&gt;..................@@@@@@@@@@@@@@,..&amp;amp;@@@@@,..................&lt;br /&gt;..................@@@@@@@@@@@@@...@@@@@@....................&lt;br /&gt;........................@@@@@@...@@@@@@.....................&lt;br /&gt;.......................@@@@@@...@@@@@@......................&lt;br /&gt;.....................%@@@@@*..%@@@@@*.......................&lt;br /&gt;.......................@@@@@@...@@@@@@......................&lt;br /&gt;........................@@@@@@...@@@@@@.....................&lt;br /&gt;..................@@@@@..@@@@@@...@@@@@@....................&lt;br /&gt;..................@@@@@...#@@@@@/..#@@@@@/..................&lt;br /&gt;............................................................&lt;br /&gt;.......................rknight.me...........................&lt;br /&gt;............................................................&lt;br /&gt;&lt;br /&gt;? What do you want to do? (Use arrow keys)&lt;br /&gt;❯ Create a new post&lt;br /&gt;  Create a new link post&lt;br /&gt;  Create a new changelog entry&lt;br /&gt;  Add a new project&lt;br /&gt;  Add a new game&lt;br /&gt;Create a new post&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I choose &amp;quot;Create a new post&amp;quot; I get asked a bunch of questions about the post including title, slug, and tags:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;? What do you want to do? Create a new post&lt;br /&gt;? Post title A New Post&lt;br /&gt;? Post slug a-new-post&lt;br /&gt;? Tags Eleventy, OpenWeb&lt;br /&gt;? Select Project none&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It then takes all this data, formats it to YAML frontmatter, and creates the file in the correct location. In this example, a file named &lt;code&gt;2024-02-21-a-new-post.md&lt;/code&gt; will be created at &lt;code&gt;src/posts/blog&lt;/code&gt; and the front matter will look like this:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;---&lt;br /&gt;title: &quot;A New Post&quot;&lt;br /&gt;permalink: /blog/a-new-post/index.html&lt;br /&gt;date: 2024-02-21T11:36:14.696Z&lt;br /&gt;excerpt: &quot;&quot;&lt;br /&gt;layout: post&lt;br /&gt;tags:&lt;br /&gt;    - Eleventy&lt;br /&gt;    - OpenWeb&lt;br /&gt;---&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don&#39;t ask for the excerpt on the CLI because I&#39;m not always sure what that will be until the post is finished. This is what the (truncated) code looks for creating a new post:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Post title&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; slug &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Post slug&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;slugify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; slugDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;T&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; year &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFullYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; postDate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toISOString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tags &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Tags&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;choices&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ActivityPub&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;ActivityPub&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;AdventOfCode&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;AdventOfCode&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;AI&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;AI&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// the rest of my tags&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; project &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;selectProject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__siteroot&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; meta &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;---&lt;br /&gt;title: &quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;br /&gt;permalink: /blog/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slug&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/index.html&lt;br /&gt;date: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;postDate&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;excerpt: &quot;&quot;&lt;br /&gt;layout: post&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    meta &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;meta&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\ntags:\n&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;tags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;    - &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;tag&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;\n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;none&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    meta &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;meta&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\nproject: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;project&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;link&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;meta &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;meta&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;\n---&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;__siteroot&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/src/posts/blog/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;year&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slugDate&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slug&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.md&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; meta&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;flag&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;wx&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For link posts, I input a link and the CLI tool fetches the page content, then uses &lt;a href=&quot;https://github.com/WebReflection/linkedom&quot;&gt;linkedom&lt;/a&gt; to find the title, author details, and RSS feed if those exist to include them in the front matter.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ask for link, slug, title, etc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; foundTitle&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; feed&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; mastodon&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; utils&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchPageData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;link&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;title&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;author&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;feed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;mastodon&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; meta &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;---&lt;br /&gt;title: &quot;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;title&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;br /&gt;permalink: /links/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;slug&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/index.html&lt;br /&gt;link: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;link&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;date: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;postDate&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;author: &lt;br /&gt;  name: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;author &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; author &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;  web: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;domain&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;  feed: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;feed&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;  mastodon: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;mastodon&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;, &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&lt;br /&gt;---&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// write the file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The source code for the CLI tool is &lt;a href=&quot;https://github.com/rknightuk/rknight.me/tree/master/cli&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So that&#39;s an overview how I&#39;m pulling in all my &lt;em&gt;stuff&lt;/em&gt; from different places on the web into this site. It&#39;s kind of complicated but it works well for me. My site is &lt;a href=&quot;https://github.com/rknightuk/rknight.me&quot;&gt;on GitHub&lt;/a&gt; if you want to look at how I do something specific or feel free to ask me &lt;a href=&quot;https://social.lol/@robb&quot;&gt;on Mastodon&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A blog post about how my site works based on a talk I did at the Eleventy meetup</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>More Things You Can Do on Your Website</title>
    <link href="https://rknight.me/blog/more-things-you-can-do-on-your-website/"/>
    <updated>2024-02-19T12:14:03Z</updated>
    <id>https://rknight.me/blog/more-things-you-can-do-on-your-website/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://jamesg.blog/2024/02/19/personal-website-ideas/&quot;&gt;James wrote a great post&lt;/a&gt; with &lt;s&gt;100&lt;/s&gt; 83 ideas for things to do on a website&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; with a call for people suggest more so here&#39;s another ten suggestions to add to his list, most of which already exist on my site because I have no imagination.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;a href=&quot;/uses&quot;&gt;uses page&lt;/a&gt; with software, tools, whatever you use to do things you enjoy doing&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/collections&quot;&gt;collections page&lt;/a&gt; to show off your games, books, stamps, or anything else you collect&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/about/colophon&quot;&gt;colophon&lt;/a&gt; to explain how your website is created, built, and hosted&lt;/li&gt;
&lt;li&gt;Create a &lt;a href=&quot;/podcasts/roll&quot;&gt;podroll&lt;/a&gt; to list the podcasts you like to listen to&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/intersect&quot;&gt;wiki&lt;/a&gt; or a notes page to write down things you&#39;ve learnt, little snippets of code, or useful website you use&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/log/versions&quot;&gt;version history page&lt;/a&gt; to show what your website has looked like in the past&lt;/li&gt;
&lt;li&gt;As an extension of James&#39; number 33, add a &lt;a href=&quot;/subscribe&quot;&gt;subscribe page&lt;/a&gt; to list all the ways someone can see your blog posts like RSS and Mastodon&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/save&quot;&gt;save page&lt;/a&gt; to list referral links for things you recommend&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/almanac&quot;&gt;log of all&lt;/a&gt; the movies and tv shows you&#39;ve watched, books you&#39;ve read, and games (board or video) you&#39;ve played&lt;/li&gt;
&lt;li&gt;A &lt;a href=&quot;/blog/stats&quot;&gt;stats page&lt;/a&gt; to show how many words you&#39;ve written in total, how many posts, or something else interesting about your site&lt;/li&gt;
&lt;/ol&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I will be consulting a lawyer about the false advertising, James &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>Adding more ideas to James' list of 83 things to do on your website</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Notes on Buying a House</title>
    <link href="https://rknight.me/blog/notes-on-buying-a-house/"/>
    <updated>2024-02-17T15:20:26Z</updated>
    <id>https://rknight.me/blog/notes-on-buying-a-house/</id>
    <content type="html">&lt;p&gt;tl;dr: The process is terrible. Also, these notes are only relevant to the UK.&lt;/p&gt;
&lt;h3&gt;Process&lt;/h3&gt;
&lt;p&gt;This is simplified but, in theory, the process is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Save a deposit&lt;/li&gt;
&lt;li&gt;Work out how much you can borrow - &lt;a href=&quot;https://www.moneysavingexpert.com/mortgages/how-much-mortgage-borrowing/&quot;&gt;this tool on Money Saving Expert&lt;/a&gt; works well&lt;/li&gt;
&lt;li&gt;Find, view, and put in an offer on, a house&lt;/li&gt;
&lt;li&gt;Have an offer accepted&lt;/li&gt;
&lt;li&gt;Wait around needlessly while everyone involved in the process ignores you for days on end and eventually gets everything signed off&lt;/li&gt;
&lt;li&gt;Have a house&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Finding a House&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://rightmove.co.uk&quot;&gt;Right Move&lt;/a&gt; is pretty much the only option for finding houses unless you&#39;re spending over a million.&lt;/p&gt;
&lt;h4&gt;Saved Searches&lt;/h4&gt;
&lt;p&gt;Right Move has two search options: by area/postcode or by drawing an area. For areas you can set a distance from the area which depending on where you&#39;re looking can be useful; for me, it wasn&#39;t because of various islands that are technically within a couple of miles but in reality are ~5 miles away by road. Alternatively, you can draw an area on a map and it will show you all houses within it.&lt;/p&gt;
&lt;p&gt;You can save these searches and then enable email alerts for when new houses get added. The option says &amp;quot;Instantly&amp;quot; but it&#39;s not. In some cases, I would see a new listing and not get an email about it for 2-3 hours. The best advice is, if you can, keep the search page open sorted by recently added and periodically refresh the page.&lt;/p&gt;
&lt;h4&gt;Viewings&lt;/h4&gt;
&lt;p&gt;When you call for a viewing, every estate agent wants to take your details so they can let you know about new houses. In my experience they&#39;ll just send you a few emails of stuff that&#39;s already on Right Move. They might organise a viewing for one that&#39;s in the process of being listed, but the one time this happened to me the house was nothing like what I wanted so it was a waste of time.&lt;/p&gt;
&lt;h3&gt;Stamp Duty&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.gov.uk/stamp-duty-land-tax&quot;&gt;Stamp Duty Land Tax&lt;/a&gt; is a tax you have to pay when buying a house. If you&#39;re a first time buyer you pay no stamp duty if the house is worth less than some threshold, at the moment it&#39;s £500k. The government have a &lt;a href=&quot;https://www.tax.service.gov.uk/calculate-stamp-duty-land-tax/#/intro&quot;&gt;stamp duty calculator&lt;/a&gt; to work out how much you have to pay.&lt;/p&gt;
&lt;h3&gt;Conveyancing Solicitors&lt;/h3&gt;
&lt;p&gt;For solicitors, there are two choices: local firm (although in theory you could use one from anywhere) or an online one. I would recommend a local one as it makes it way easy to get in contact with them, drop paperwork off, and get things signed quickly.&lt;/p&gt;
&lt;h3&gt;Moving In&lt;/h3&gt;
&lt;p&gt;Just get the meter readings as soon as you have the keys otherwise this becomes a real hassle. Everything else can wait.&lt;/p&gt;
</content>
    <summary>My notes on the process of buying a house</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>How I Make a Podcast Episode</title>
    <link href="https://rknight.me/blog/how-i-make-a-podcast-episode/"/>
    <updated>2024-02-17T12:45:47Z</updated>
    <id>https://rknight.me/blog/how-i-make-a-podcast-episode/</id>
    <content type="html">&lt;p&gt;I have recorded and edited over 175 episodes of &lt;a href=&quot;https://www.ruminatepodcast.com/&quot;&gt;my&lt;/a&gt; &lt;a href=&quot;https://wegot.family/&quot;&gt;podcasts&lt;/a&gt; so I know &lt;em&gt;some&lt;/em&gt; things about podcasts but this is basically a list of things I use. If you want to hear from actual professionals I recommend &lt;a href=&quot;https://www.relay.fm/upgrade/200&quot;&gt;episode 200 of Upgrade&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I record using a &lt;a href=&quot;https://www.razer.com/streaming-microphones/razer-seiren-mini/RZ19-03450100-R3M1&quot;&gt;Razer Seiren Mini&lt;/a&gt;. I previously used a &lt;a href=&quot;https://www.bluemic.com/en-gb/products/yeti/&quot;&gt;Blue Yeti&lt;/a&gt;. There are much better microphones available but for what I do, the Razer is fine.&lt;/p&gt;
&lt;p&gt;I record my microphone and the call itself, as a backup, with &lt;a href=&quot;https://rogueamoeba.com/audiohijackpro/&quot;&gt;Audio Hijack Pro&lt;/a&gt;. My setup looks likes this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/audio-hijack.jpg&quot; alt=&quot;Audio Hijack Setup&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The Skype (or Facetime or Zoom) audio is recorded to a file and output to my headphones. My microphone input is then recorded to it&#39;s own file.&lt;/p&gt;
&lt;p&gt;Once recording is done and I have both files (mine and my cohost&#39;s), I edit the show in &lt;a href=&quot;https://www.apple.com/uk/mac/garageband/&quot;&gt;GarageBand&lt;/a&gt;. I mostly just need to remove any cross-talk and little noises. It would probably be easier in &lt;a href=&quot;https://www.apple.com/uk/logic-pro/&quot;&gt;Logic Pro&lt;/a&gt; but I can&#39;t justify paying for it. I then export the edited episode to a &lt;code&gt;.wav&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;To add metadata like titles, descriptions, chapters, and the cover art I use Marco Arment&#39;s &lt;a href=&quot;https://overcast.fm/forecast&quot;&gt;Forecast&lt;/a&gt; and export it to &lt;code&gt;mp3&lt;/code&gt; from there.&lt;/p&gt;
&lt;p&gt;Finally I upload the file to my CDN and add the episode to the podcast website - which is a &lt;a href=&quot;https://github.com/rknightuk/ruminate&quot;&gt;custom-built Eleventy site&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A quick overview of how I record, edit, and release a podcast episode</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Webmentions Redux</title>
    <link href="https://rknight.me/blog/webmentions-redux/"/>
    <updated>2024-02-16T13:05:34Z</updated>
    <id>https://rknight.me/blog/webmentions-redux/</id>
    <content type="html">&lt;p&gt;After thinking on all the issues and &lt;a href=&quot;https://social.lol/@robb/111908222268633475&quot;&gt;discussion around the privacy&lt;/a&gt; of webmentions, I&#39;ve re-done everything about how I show webmentions on my site, more specifically backfeeding Mastodon replies.&lt;/p&gt;
&lt;h3&gt;Follow Up&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://chrismcleod.dev/blog/more-words-on-webmentions-and-backfeed/&quot;&gt;Chris noted in his post&lt;/a&gt;, as &lt;a href=&quot;https://campegg.com/2024/02/11/over-the-last.html&quot;&gt;pointed out by Cam&lt;/a&gt;, that the issue we were actually talking about is &lt;em&gt;backfeed&lt;/em&gt;. That is, pulling in interactions from syndicated copies of posts - in this case, my toots on Mastodon.&lt;/p&gt;
&lt;p&gt;There were a couple of points made in the replies that were interesting. Lots of replies along the lines of &amp;quot;&lt;em&gt;If an ActivityPub server/instance can show replies, why can&#39;t a (non-AP) website do it?&lt;/em&gt;&amp;quot;. I agree in principle but a non-AP website won&#39;t get notified of deletions so those replies exist forever. &lt;a href=&quot;https://sunny.garden/@knowler/111912465243280847&quot;&gt;Nathan replied with an unlisted toot&lt;/a&gt; as a test to see what would happen and Bridgy doesn&#39;t take note of this at all. I don&#39;t know if it &lt;em&gt;should&lt;/em&gt; but &amp;quot;unlisted&amp;quot; is designed to not show a toot in the public/federated timelines so not showing as a reply seems like a reasonable assumption.&lt;/p&gt;
&lt;h3&gt;Webmentions Version Two&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://mariohamann.com/showing-mastodon-reactions-on-a-statamic-website&quot;&gt;Mario Hamann&#39;s solution&lt;/a&gt; of showing just the counts of replies, likes, and boosts caught my eye as a good way of handling this; no one&#39;s data is being pulled, it&#39;s clean, it&#39;s simple. Just what I was looking for.&lt;/p&gt;
&lt;p&gt;My current implementation to show links to my posts on Mastodon was separate from my webmention fetching so I didn&#39;t have data to say &amp;quot;This Mastodon post is related to this blog post and has 12 likes&amp;quot;. So I needed to pull all my Mastodon posts that include a link to one of my blog posts. I grabbed my export from the dashboard of social.lol but that export is in ActivityPub format and doesn&#39;t include reply, like, or boost counts so I switched over to &lt;a href=&quot;https://api.rknight.me/&quot;&gt;my API&lt;/a&gt; and added a new script. I wanted the data keyed by the blog post path so I could easily get all toots for a specific post:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string-property property&quot;&gt;&quot;/blog/post-slug&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string-property property&quot;&gt;&quot;12345678&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token comment&quot;&gt;// toot data&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string-property property&quot;&gt;&quot;12345679&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token comment&quot;&gt;// toot data&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The script to get every one of my posts was easy enough, fetch my statuses, add them to the &lt;code&gt;dicussion&lt;/code&gt; object, and page through until I&#39;ve got them all:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; maxId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; discussion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://social.lol/api/v1/accounts/109523762776095110/statuses?exclude_replies=true&amp;amp;limit=40&amp;amp;exclude_reblogs=true&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;maxId &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;amp;max_id=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;maxId&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; toots &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;toots&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    toots&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; urls &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;extractUrls&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://rknight.me&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isSyndicate &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://rknight.me&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isSyndicate&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                urls&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;br /&gt;                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/blog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OLD_URLS&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                    path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/blog&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;path&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                &lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;discussion&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; discussion&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                discussion&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;t&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; t&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    maxId &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; toots&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;br /&gt;    fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./api/discussion.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;discussion&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I added the 2 second timeout just so I didn&#39;t hit any rate limits (I don&#39;t know what they are and couldn&#39;t be bothered to look). Going forward I will run this script on the latest 40 toots and add them to the data which you &lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/discussion.js&quot;&gt;can see here&lt;/a&gt;. A side note here, the &lt;code&gt;OLD_URLS&lt;/code&gt; part of this code is because I recently moved all my blog posts under the &lt;code&gt;/blog&lt;/code&gt; path so some posts wouldn&#39;t match otherwise.&lt;/p&gt;
&lt;p&gt;Initially, I had a similar design to Mario but I ended up expanding it to be more of a card as if I had embedded the toot in my site manually. This is what the code looks like in &lt;code&gt;webmentions.njk&lt;/code&gt;, included at the end of each post:&lt;/p&gt;
&lt;pre class=&quot;language-hbs&quot;&gt;&lt;code class=&quot;language-hbs&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;discussion&lt;/span&gt;&lt;span class=&quot;token brackets&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;webmentionUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;discussionData&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;discussion&lt;/span&gt;&lt;span class=&quot;token brackets&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;webmentionUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;oValues&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;discussionData&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;toot&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;toot__header&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;icon mastodon-icon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;xlink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#mastodon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;_blank&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ m.url }}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;Discuss&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;Mastodon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;toot__content&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;safe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;toot__data&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;_blank&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ m.url }}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;xlink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#socialreply&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;replies_count&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;_blank&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ m.url }}/reblogs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;xlink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#socialboost&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;reblogs_count&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;_blank&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ m.url }}/favourites&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;xlink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#sociallike&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;favourites_count&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endfor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endif&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I had to add a filter to Eleventy to run &lt;code&gt;Object.values&lt;/code&gt; on the toots so I could map over them in the code:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function-variable function&quot;&gt;oValues&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also include other relevant discussion links where appropriate (like HackerNews) so those are also styled to match the toot card style. The final result looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/post-syndication.png&quot; alt=&quot;Post Syndication&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This new version isn&#39;t webmentions. It doesn&#39;t check for replies or likes or boosts. This is just showing where I&#39;ve posted links to my posts, or &lt;a href=&quot;https://indieweb.org/Category:syndication&quot;&gt;syndication&lt;/a&gt; as it&#39;s called in the indieweb world. This solves all of the privacy issues outlined in &lt;a href=&quot;https://rknight.me/blog/mastodon-webmentions-and-privacy/&quot;&gt;my post&lt;/a&gt; as well as ones &lt;a href=&quot;https://brainbaking.com/post/2023/05/why-i-retired-my-webmention-server/&quot;&gt;Wouter&lt;/a&gt;, &lt;a href=&quot;https://chrismcleod.dev/blog/some-words-on-webmentions/&quot;&gt;Chris&lt;/a&gt;, &lt;a href=&quot;https://campegg.com/2024/02/11/over-the-last.html&quot;&gt;Cam&lt;/a&gt;, and others have mentioned.&lt;/p&gt;
&lt;p&gt;I haven&#39;t turned off webmention collection yet. I may still come back to data to see what &amp;quot;proper&amp;quot; webmentions I get and if it&#39;s worth showing those in the future. I will be turning off the Mastodon integration that Bridgy provides though - I just don&#39;t need to be collecting those replies.&lt;/p&gt;
&lt;p&gt;There is one other reason to remove the old webmentions implementation: it is, quite frankly, a pain in the arse to maintain. Once it&#39;s working in theory it shouldn&#39;t break but it does on occasion. There&#39;s an ongoing bug with emojis showing as &lt;code&gt;????&lt;/code&gt; which I needed to handle, along with a bunch of other edge cases.&lt;/p&gt;
&lt;p&gt;I will miss the little grid of avatars for likes and boosts because I&#39;m quite fond of the design, but I won&#39;t miss the complication webmentions adds to my site. Assuming everything has worked, this post should have the toot embedded below.&lt;/p&gt;
&lt;p&gt;Update 2024-02-19: If you want an even easier way to do this, David Darnes has made &lt;a href=&quot;https://darn.es/mastodon-post-web-component/&quot;&gt;a nice web component to do it&lt;/a&gt; for you.&lt;/p&gt;
</content>
    <summary>I've rethought everything about how I show webmentions on my blog posts and switched to just showing syndicated posts instead</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Three Months of The Johnny Decimal System</title>
    <link href="https://rknight.me/blog/three-months-of-the-johnny-decimal-system/"/>
    <updated>2024-02-15T08:24:22Z</updated>
    <id>https://rknight.me/blog/three-months-of-the-johnny-decimal-system/</id>
    <content type="html">&lt;p&gt;Three months ago I &lt;a href=&quot;https://rknight.me/blog/using-the-johnny-decimal-system/&quot;&gt;wrote about using the Johnny Decimal System&lt;/a&gt; - a system to organise your files, emails, and everything else in a way that means things are findable and storable quickly.&lt;/p&gt;
&lt;p&gt;I had assumed, like a lot of things I try, that given a month or so I&#39;d be back to just dumping files wherever and being annoyed when I couldn&#39;t find things but to my surprise the system is working. &lt;em&gt;Really well&lt;/em&gt;. If I download a podcast episode I&#39;m mentioned in&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; I know it goes in &lt;code&gt;20-29 Podcasts &amp;gt; 22 Follow Out &amp;gt; 22.02 Podcast Mentions&lt;/code&gt;, that gifs go in &lt;code&gt;50-59 Media &amp;gt; 54 Memes &amp;gt; 54.02 Gifs&lt;/code&gt;, and my payslips go in &lt;code&gt;10-19 Home and Family &amp;gt; 13 Legal &amp;gt; 13.05 Payslips&lt;/code&gt;. I can find these quickly regardless of if I use terminal, Finder, or Alfred&#39;s &lt;code&gt;find&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;I still have a fairly substantial downloads folder filled with random things but every now and again I can go through, delete what I don&#39;t need, and file everything else in the right place. I&#39;ve also stuck with keeping &lt;a href=&quot;https://johnnydecimal.com/10-19-concepts/11-core/11.05-the-index/&quot;&gt;my index&lt;/a&gt; in Obsidian where I&#39;ve been keeping it up-to-date with related notes about my files.&lt;/p&gt;
&lt;p&gt;This might be the first time a new system, of any kind, has actually clicked for me. &lt;a href=&quot;https://johnnydecimal.com/10-19-concepts/14-build-your-system/14.02-the-decimal-workbook/&quot;&gt;The workbook&lt;/a&gt;, which I highly recommend, is only $19 now if you think this is something you want to try. And as if we planned this (we definitely didn&#39;t), just as I was about to publish this post Johnny announced &lt;a href=&quot;https://jdcm.al/10-19-concepts/14-build-your-system/14.03-the-decimal-workshop/&quot;&gt;the workshop&lt;/a&gt; which has a pre-launch price of $49.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Don&#39;t at me, I live for validation &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>Looking at my Johnny Decimal System three months into implementing it</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Mastodon Webmentions and Privacy</title>
    <link href="https://rknight.me/blog/mastodon-webmentions-and-privacy/"/>
    <updated>2024-02-10T16:36:01Z</updated>
    <id>https://rknight.me/blog/mastodon-webmentions-and-privacy/</id>
    <content type="html">&lt;p&gt;Wouter&#39;s post about &lt;a href=&quot;https://brainbaking.com/post/2023/05/why-i-retired-my-webmention-server/&quot;&gt;retiring their webmention server&lt;/a&gt; is an interesting write-up on how complicated webmentions and indieweb functionality in general can be but one point from it has stuck with me since reading it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;...people mentioning or replying to your link via Twitter suddenly appear as a mention on your site. Great stuff, right? Except those people have no idea their avatar and text is being yanked. I’ve questioned these practices before and it’s clear that they’re built without thinking too hard about privacy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Until this point I also hadn&#39;t considered the privacy aspect of using webmentions like this. Assume someone, &lt;code&gt;@userX&lt;/code&gt; for example, replies to one of my toots about a post I&#39;ve written. Bridgy will pull in that reply with the avatar, username, and the reply content for me to display on that post as a reply. As it&#39;s setup right now, that reply will live forever on my post regardless of what &lt;code&gt;@userX&lt;/code&gt; does with their original version of the reply. Should I be periodically checking if a reply has been deleted (or edited for that matter)? In theory, that could be hundreds or thousands of links to check.&lt;/p&gt;
&lt;p&gt;Secondly, not everyone even &lt;em&gt;knows&lt;/em&gt; that this is happening when they reply to a toot where the site owner has webmentions enabled. Should there be some extra step to say &amp;quot;Are you happy for this to show up on this post&amp;quot;? That seems like a good way to kill the whole concept but maybe we should? I don&#39;t know.&lt;/p&gt;
&lt;p&gt;Yes the replies are set as &amp;quot;public&amp;quot; (or at least I think Bridgy only picks up public ones) but public doesn&#39;t mean &amp;quot;do whatever you want and copy it forever&amp;quot;.&lt;/p&gt;
&lt;p&gt;For all the effort that&#39;s been &lt;a href=&quot;https://11tybundle.dev/categories/webmentions/&quot;&gt;put into making webmentions work&lt;/a&gt; I&#39;m now wondering if I should even be doing it. I certainly wouldn&#39;t want anyone to feel like their posts are being taken without their permission or used in a way they never intended.&lt;/p&gt;
</content>
    <summary>Some thoughts on the privacy implications of doing Mastodon-based webmentions</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My Favourite Type of Time Travel</title>
    <link href="https://rknight.me/blog/my-favourite-type-of-time-travel/"/>
    <updated>2024-02-06T17:30:00Z</updated>
    <id>https://rknight.me/blog/my-favourite-type-of-time-travel/</id>
    <content type="html">&lt;p&gt;I was recently&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; asked by &lt;a href=&quot;https://zoeaubert.me/&quot;&gt;Zoe&lt;/a&gt; the following question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What&#39;s your preferred type of time travel (like singular timeline where things always where, multiverse when you go back, some other shit)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is &lt;em&gt;quite the question&lt;/em&gt;. We should start with the different types of time travel to even be able to answer this. I&#39;m not covering every possible version from media, just the ones I care or know about. Notably, I have not included Dr Who anywhere here because 1. I&#39;ve never watched it 2. John and Kate in the Relay discord said it does whatever is needed for the plot and isn&#39;t consistent.&lt;/p&gt;
&lt;h3&gt;Types&lt;/h3&gt;
&lt;h4&gt;Self-Correcting/Paradox&lt;/h4&gt;
&lt;p&gt;This is almost anti-time travel, the commonly-known &amp;quot;Grandfather paradox&amp;quot;. If I travel back in time to kill my grandfather, I would never have been born and therefore couldn&#39;t have gone back to kill him in the first place. &lt;em&gt;Anyone&lt;/em&gt; I went back to kill (assuming I chose someone I knew of) would self-correct because by them not existing I wouldn&#39;t know about them so would never have gone back.&lt;/p&gt;
&lt;p&gt;This one also has the honour of being the least fun. Barely even time travel.&lt;/p&gt;
&lt;h4&gt;Single, Changeable Timeline&lt;/h4&gt;
&lt;p&gt;Examples: &lt;a href=&quot;https://en.wikipedia.org/wiki/Back_to_the_Future&quot;&gt;Back to the Future&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Roswell_That_Ends_Well&quot;&gt;Futurama &amp;quot;Roswell That End Well&amp;quot;&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Hot_Tub_Time_Machine&quot;&gt;Hot Tub Time Machine&lt;/a&gt;, &lt;a href=&quot;https://www.imdb.com/title/tt0212579/&quot;&gt;Blackadder Back and Forth&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the most common version seen in media and the one I&#39;m most familiar with, having watched the Back to the Future movies at least once a year for the past 30 years. You go back, do something, and on your return things have changed. Maybe you go back and accidentally stop your mum meeting your dad, come up with an elaborate plan to get them back together even though she&#39;s into you now, turn your dad into a completely different person, play Johnny B. Goode for your parents classmates, then your mum names you after a guy she had the hots for in school and your dad says nothing about this. Or something less...weird.&lt;/p&gt;
&lt;p&gt;The second movie explains these changes further as the timeline &amp;quot;skewing&amp;quot;; to get back to the &amp;quot;original&amp;quot; future you came from you need to fix whatever change you made in the past.&lt;/p&gt;
&lt;h5&gt;Inconsistencies&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Do Marty&#39;s parents just not notice their kid looks a hell of a lot like that guy from when they were at school? Why did they name their third kid Marty and not their first one?&lt;/li&gt;
&lt;li&gt;When Marty goes to the future in Part 2 he would get there to find his kids don&#39;t exist because he&#39;s been missing for 30 years, surely? Or does time travelling create some kind of clone so you keep existing in the timeline? It makes no sense.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Single, Changeable, Always-Happened Timeline&lt;/h4&gt;
&lt;p&gt;Examples: &lt;a href=&quot;https://en.wikipedia.org/wiki/Harry_Potter_and_the_Prisoner_of_Azkaban_(film)&quot;&gt;Harry Potter and the Prisoner of Azkaban&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Bill_%26_Ted%27s_Excellent_Adventure&quot;&gt;Bill and Ted&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is almost identical to above with the exception that the things that someone might do in the past &lt;em&gt;already and always&lt;/em&gt; happened. So if you make a decision to go back in time and throw a rock at yourself, you already did.&lt;/p&gt;
&lt;p&gt;This also happens in Bill and Ted when they need the keys to the police station cells. They think about doing it and the keys are there.&lt;/p&gt;
&lt;p&gt;Notably, there isn&#39;t really anything in Bill and Ted that seems to change the timeline at all - even taking the princesses from medieval England doesn&#39;t change anything, at least that we know of from the movie.&lt;/p&gt;
&lt;h5&gt;Inconsistencies&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;At the point Hermione and Harry decide to time travel they&#39;ve already experienced some of the things they &lt;em&gt;will do&lt;/em&gt; when they travel; What happens if they decide not to go or will they 100% go because it&#39;s happened already?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Multiverse/Branching&lt;/h4&gt;
&lt;p&gt;Examples: &lt;a href=&quot;https://en.wikipedia.org/wiki/Avengers:_Endgame&quot;&gt;Avengers: Endgame&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This one is the easiest to explain away from a plot point of view. You go back, &lt;a href=&quot;https://www.youtube.com/watch?v=PPUPMGdG3PU&quot;&gt;kill baby Thanos&lt;/a&gt;, and now you have two timelines: yours where Thanos is alive and a new one where Thanos is dead. &lt;em&gt;Every action&lt;/em&gt; taken in the past creates a new branched timeline.&lt;/p&gt;
&lt;p&gt;Also worth noting here that every decision made, even in the present, can &lt;em&gt;also&lt;/em&gt; create new branches, it&#39;s not exclusive to when you&#39;re in the past.&lt;/p&gt;
&lt;h5&gt;Inconsistencies&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;None that I can think of. It&#39;s a very &amp;quot;clean&amp;quot; version of time travel.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Stable Time-Apparatus (&amp;quot;The Box&amp;quot;)&lt;/h4&gt;
&lt;p&gt;Examples: &lt;a href=&quot;https://en.wikipedia.org/wiki/Primer_(film)&quot;&gt;Primer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As far as I know the only example of this is in Primer, the 2004 movie. I will try and explain the short version here but &lt;a href=&quot;https://en.wikipedia.org/wiki/Primer_(film)#/media/File:Time_Travel_Method-2.svg&quot;&gt;Wikipedia has a handy diagram too&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Box is turned on by A with a 15 minute delay at 11:45am. A then hides (so as not to affect events and collect useful information like stocks) away until 6pm and which point he enters the box, and waits 6 hours to come out of the box...at midday (11:45 + the 15 minute delay). A is now B, with the original A still hiding away collecting stock info. If you understood this, you won&#39;t once you watch the movie.&lt;/p&gt;
&lt;p&gt;This method only allows travelling back to the point when the box was turned on, no going back to punch Hitler here. Lots of opportunity for personal gain with this.&lt;/p&gt;
&lt;h5&gt;Inconsistencies&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;None&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Time Loop&lt;/h4&gt;
&lt;p&gt;Examples: &lt;a href=&quot;https://en.wikipedia.org/wiki/Groundhog_Day_(film)&quot;&gt;Groundhog Day&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Palm_Springs_(2020_film)&quot;&gt;Palm Springs&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Russian_Doll_(TV_series)&quot;&gt;Russian Doll Season 1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Usually a day, the character is stuck in a loop of the same period over and over, never being able to change what happens or get out of the loop. This isn&#39;t always considered as time travel but the consequences for the characters in the movies/shows are similar: they know what&#39;s going to happen and they can change things using their knowledge of how the loop will play out albeit for only for the current &amp;quot;loop&amp;quot; they&#39;re in.&lt;/p&gt;
&lt;p&gt;The exit methods for the loops are usually vague like &amp;quot;become a better person&amp;quot; except in the case of Palm Springs where they use a bomb.&lt;/p&gt;
&lt;h5&gt;Inconsistencies&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;None&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Forward or Backwards Only&lt;/h4&gt;
&lt;p&gt;Examples: &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Late_Philip_J._Fry&quot;&gt;Futurama: &amp;quot;The Late Philip J. Fry&amp;quot;&lt;/a&gt; (forwards) and &lt;a href=&quot;https://www.imdb.com/title/tt0471711/&quot;&gt;Futurama: &amp;quot;Bender&#39;s Big Score&lt;/a&gt; (backwards)&lt;/p&gt;
&lt;p&gt;Futurama features two machines that only go one way: one for forwards only and one for backwards only.&lt;/p&gt;
&lt;p&gt;We&#39;re all doing the forwards one right now anyway it just happens to take one second to travel one second into the future. But if you want to go faster the &amp;quot;Forwards Time Machine&amp;quot; from Futurama does the trick.&lt;/p&gt;
&lt;p&gt;Not sure of the usefulness of this one. In the Futurama universe if you go to the end of time the universe just starts again as it was before (but a few feet lower than before) so this could be used for backwards time travel but it&#39;s would be annoying to do.&lt;/p&gt;
&lt;p&gt;The backwards-only version is mostly useless for humans unless your goal doesn&#39;t include coming back to the present. In the episode, Bender is the one who does it so he can just wait it out on account of being a robot. This does have a paradox of sorts that all the Benders waiting around to come back are all in the same place at once but that gets corrected evenutally.&lt;/p&gt;
&lt;h5&gt;Inconsistencies&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;None&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;My Favourite&lt;/h3&gt;
&lt;p&gt;Picking a favourite here is hard and would entirely depend on my goals.&lt;/p&gt;
&lt;p&gt;Multiverse is kind of terrifing that every little action is creating a brand new timeline with untold horrors based on my decisions. It&#39;s a handy version if your goal is to steal something without any consequences to your own timeline.&lt;/p&gt;
&lt;p&gt;Primer&#39;s box is useful only in the way the movie presents: for short-term personal gain. I won&#39;t spoil the movie but there are big consequences for making your days 36 hours long instead of 24. I&#39;d want to use this once every now and again but I&#39;m not sure I could be trusted.&lt;/p&gt;
&lt;p&gt;I don&#39;t like the predetermined nature of the already-happened-no-matter-what timeline so I think my favourite, despite having the most paradoxes, is single timeline, Back to the Future style. There&#39;s a reason this is the one that appears more in media than any other: despite the problems, it&#39;s easy to explain quickly without need to sit down and write notes and diagrams (looking at you, Primer).&lt;/p&gt;
&lt;h3&gt;Time Travel Miscellania&lt;/h3&gt;
&lt;p&gt;I am a sucker for time travel media and I&#39;ll pretty much watch anything where it&#39;s involved. I can&#39;t get enough of them like &lt;a href=&quot;https://en.wikipedia.org/wiki/Timeless_(TV_series)&quot;&gt;Timeless&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Legends_of_Tomorrow&quot;&gt;Legends of Tomorrow&lt;/a&gt; even if they are cheesy as hell.&lt;/p&gt;
&lt;p&gt;I would like to see a movie where someone creates a time machine based on the Back to the Future &amp;quot;science&amp;quot; and travels to the future only to find out about the paradoxes and hilarity ensues. Get on it, Hollywood.&lt;/p&gt;
&lt;p&gt;The DeLorean is obviously the coolest time machine.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=d3zTfXvYZ9s&quot;&gt;This Minute Physics video on the topic&lt;/a&gt; is excellent.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This was easily over a year ago now, I only just got around to finishing this article &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>A look at the different types of time travel plus my preferred method</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Things I Like: Pizza the Action Seasoning</title>
    <link href="https://rknight.me/blog/things-i-like-pizza-the-action-seasoning/"/>
    <updated>2024-02-04T15:50:46Z</updated>
    <id>https://rknight.me/blog/things-i-like-pizza-the-action-seasoning/</id>
    <content type="html">&lt;p&gt;I&#39;m going to try doing some quick posts like this going forward about things I like. Being the naming genius I am, I&#39;m calling this series &amp;quot;Things I Like&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pizza-the-action.jpg&quot; alt=&quot;Pizza the Action seasoning&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://condimaniac.com/products/condimaniac-pizza-the-action-pizza-seasoning&quot;&gt;Pizza the Action&lt;/a&gt; is a seasoning from the UK-based company Condimaniac. It’s a seasoning mix designed to, as the name might suggest, go on pizza. There’s nothing particularly surprising or unusual in the ingredients list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tomato Flakes&lt;/li&gt;
&lt;li&gt;Garlic Granules&lt;/li&gt;
&lt;li&gt;Sea Salt&lt;/li&gt;
&lt;li&gt;Onion Granules&lt;/li&gt;
&lt;li&gt;Cayenne Pepper&lt;/li&gt;
&lt;li&gt;Nutritional Yeast Flakes&lt;/li&gt;
&lt;li&gt;Basil&lt;/li&gt;
&lt;li&gt;Oregano&lt;/li&gt;
&lt;li&gt;Smoked Paprika&lt;/li&gt;
&lt;li&gt;Thyme&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Who doesn&#39;t love a &amp;quot;nutritional yeast flake&amp;quot;? Ignoring that one, whatever their exact combination of the ingredients is makes pizzas taste fantastic. Even some cheap store-brand ones I’ve had in the past month tasted &lt;em&gt;way&lt;/em&gt; better with a sprinkling of it. They suggest using it as seasoning for pizza sauce which I will definiely try with &lt;a href=&quot;https://rknight.me/blog/one-year-of-pizza-making/&quot;&gt;my current sauce recipe&lt;/a&gt; once the Ooni oven comes out again this summer.&lt;/p&gt;
&lt;p&gt;Anyway, it’s tasty and I love it. I bought it from Ooni because I had some credit but they also sell it, along with a bunch of other pizza-related condiments, direct &lt;a href=&quot;https://condimaniac.com/collections/all&quot;&gt;on their website&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A pizza seasoning I bought recently that I've been enjoying</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Tech is Annoying Me This Week</title>
    <link href="https://rknight.me/blog/tech-is-annoying-me-this-week/"/>
    <updated>2024-02-04T10:35:52Z</updated>
    <id>https://rknight.me/blog/tech-is-annoying-me-this-week/</id>
    <content type="html">&lt;p&gt;Computers are not my friend this week and I am basically ready to throw my computer into the sea. Here is an incomplete list of things annoying me at the moment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discord not marking a channel as read no matter how many times I look at it. Only force quitting fixes it.&lt;/li&gt;
&lt;li&gt;Open source projects that say they’re “Built with Docker” with no other information about the stack meaning I have to go hunting in the code base just to find out how it’s actually built and if it’s something I’d be willing to maintain/fix if I decide to use it. This is like saying my house is “built with foundations”.&lt;/li&gt;
&lt;li&gt;The fact that I’m forced to use Instagram’s shitty app to see my friend’s photos.&lt;/li&gt;
&lt;li&gt;The share sheet on Apple Music on my Mac stops working at least once a day meaning I have to quit and restart it just to copy a link to an album or track.&lt;/li&gt;
&lt;li&gt;Apple’s stupid EU DMA proposals. If what they’ve proposed gets accepted by the EU the DMA is a waste of time and they might as well not have bothered with it in the first place. Third party app stores except Apple still controls the whole thing? I can’t even.&lt;/li&gt;
&lt;li&gt;Notifications on my wife’s Apple Watch have just stopped working for almost every app. I’ve tried everything and nothing fixes it.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>An incomplete list of tech things that are annoying me this week</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Quick Thoughts on Crisps</title>
    <link href="https://rknight.me/blog/quick-thoughts-on-crisps/"/>
    <updated>2024-01-25T17:17:34Z</updated>
    <id>https://rknight.me/blog/quick-thoughts-on-crisps/</id>
    <content type="html">&lt;p&gt;Now &lt;em&gt;this&lt;/em&gt; is a theme I can get behind. If my specialist subject for Mastermind couldn&#39;t be Back to the Future, &amp;quot;Crisps of the UK&amp;quot; might be a close second. Following in the footsteps of &lt;a href=&quot;https://lynnandtonicblog.com/2024/01/25/my-quick-thoughts-on-chips/&quot;&gt;Lynn&lt;/a&gt;, &lt;a href=&quot;https://daverupert.com/2023/08/quick-thoughts-on-chips/&quot;&gt;Dave&lt;/a&gt;, &lt;a href=&quot;https://snook.ca/archives/personal/quicker-thoughts-on-chips&quot;&gt;Jonathan&lt;/a&gt;, and &lt;a href=&quot;https://pmullen.com/posts/more-quick-thoughts-on-chips/&quot;&gt;Peter&lt;/a&gt; here are my thoughts on &lt;s&gt;chips&lt;/s&gt; crisps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Prawn Cocktail is one of the finest flavours available and I&#39;m sad this mostly doesn&#39;t exist outside the UK.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://inews.co.uk/inews-lifestyle/food-and-drink/brannigans-crisps-discontinued-pub-classic-britons-mourning-657852&quot;&gt;Brannigans beef and mustard&lt;/a&gt; were the best crisp ever made. The flavour, texture, everything. RIP.&lt;/li&gt;
&lt;li&gt;Of course Pringles are crisps. Sorry Peter.&lt;/li&gt;
&lt;li&gt;Salt and Vinegar crisps should have enough salt to make my mouth numb for a day.&lt;/li&gt;
&lt;li&gt;The pretending-to-be-artisnal crisps like Kettle are better eaten out of a bowl each time you walk past said bowl.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Related to this: my &lt;a href=&quot;/blog/food-graveyard/&quot;&gt;food graveyard&lt;/a&gt; post.&lt;/p&gt;
</content>
    <summary>Crisps: My specialist subject that isn't Back to the Future</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My First Mac</title>
    <link href="https://rknight.me/blog/my-first-mac/"/>
    <updated>2024-01-25T07:47:37Z</updated>
    <id>https://rknight.me/blog/my-first-mac/</id>
    <content type="html">&lt;p&gt;Apologies for the terrible filtered photos but the only versions I have are from my Instagram archive when we all thought filters were the best thing ever. They were not.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;My first Mac was a 2009 27” iMac. It was a Christmas present from my parents. I had asked for a Mac Mini so a iMac was a big upgrade. I asked for the mini partly because it was cheaper and partly because I already had a (really crappy) monitor. I think it technically belonged to my dad’s company for &lt;em&gt;tax reasons&lt;/em&gt; and I &lt;em&gt;did&lt;/em&gt; do some work for him at least once so all good Mr tax man, nothing to see here.&lt;/p&gt;
&lt;p&gt;Having been on hand-me-down crappy Windows laptops prior to the iMac I was blown away. The screen, the OS in general, and the third party apps. In particular, Panic’s Coda is the one I remember the most - I even used their font for my HTML and CSS tattoos.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/css-tattoo.jpg&quot; alt=&quot;css tattoo&quot; /&gt;&lt;/p&gt;
&lt;p&gt;That iMac lasted me a long time as both my general computer and my “TV”. Then a few years in the hard drive failed which meant I had to take it apart and replace the drive. If you don’t know, to get to anything in one of these iMacs, you need to get the glass off the front, ideally with specialised tools that I didn’t have, so I used a toilet plunger instead&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/imac-maintenance.jpg&quot; alt=&quot;iMac maintenence&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Another fun thing about this; the hard drives in these iMac also include temperature sensors. At the time, I couldn’t afford one with the sensor so I installed a normal drive and then used a third party app called something like “fan control pro”. When it booted up and the app wasn’t running, the fans would run on full until the app launched. Good times.&lt;/p&gt;
&lt;p&gt;The iMac got retired when I bought a real TV like a grown up and the Mac itself was replaced with a MacBook Air and since then a series of MacBook Pros. You can see my current setup on &lt;a href=&quot;/uses&quot;&gt;my uses page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These days I still love my Mac but I’m not so enamoured with the company but that’s a post for another day.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Don&#39;t worry, I cleaned it &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>It's the Mac's 40th anniversary so here's the story of my first Mac</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Creating an OPML File for my Blogroll</title>
    <link href="https://rknight.me/blog/creating-an-opml-file-for-my-blogroll/"/>
    <updated>2024-01-21T07:10:16Z</updated>
    <id>https://rknight.me/blog/creating-an-opml-file-for-my-blogroll/</id>
    <content type="html">&lt;p&gt;Last night I updated my &lt;a href=&quot;/blog/roll&quot;&gt;blogroll&lt;/a&gt; and &lt;a href=&quot;/podcasts/roll&quot;&gt;podroll&lt;/a&gt; to include a description about the sites instead of just showing the latest post; this is much more useful to someone who lands on that page. Then I realised I could add an OPML file so anyone could subscribe to all of the feeds in the roll all at once.&lt;/p&gt;
&lt;p&gt;OPML stands for &amp;quot;Outline Processor Markup Language&amp;quot; which isn&#39;t useful to explain what it does in this context. At it&#39;s core, it&#39;s a XML document that has a list of RSS feeds you can import into a feed reader or podcast app. It looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;opml&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1.0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;A title&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dateCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Sun, 21 Jan 2024 08:13:40 +0000&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dateCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;outline&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A Cool Blog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;A Cool Blog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;rss&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlUrl&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/rss&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;htmlUrl&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;opml&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each &lt;code&gt;outline&lt;/code&gt; element is a feed with some attributes to describe it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt; - The title of the feed/site&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text&lt;/code&gt; - This is what will be shown by feed readers when importing an OPML. This can be different to &lt;code&gt;title&lt;/code&gt; but I keep them the same&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt; - the type of feed. I&#39;m not sure it matters if you set an Atom feed with the type set as &lt;code&gt;rss&lt;/code&gt;, most feed readers will handle this anyway&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xmlUrl&lt;/code&gt; - a link to the feed&lt;/li&gt;
&lt;li&gt;&lt;code&gt;htmlUrl&lt;/code&gt; - a link to the site&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My rolls are configured with a &lt;a href=&quot;https://www.11ty.dev/docs/data-global/&quot;&gt;data file&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// src/_data/blogroll.js&lt;/span&gt;&lt;br /&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;A Blog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://example.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;feed&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://example.com/rss&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;A cool blog about things&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// the rest of the sites&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To generate an OPML file from the roll in Eleventy, I added an &lt;code&gt;opml.njk&lt;/code&gt; file and configured it like this:&lt;/p&gt;
&lt;pre class=&quot;language-hbs&quot;&gt;&lt;code class=&quot;language-hbs&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;permalink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;blog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;roll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;opml&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;xml&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;eleventyExcludeFromCollections&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;---&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;?xml&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1.0&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;opml&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;RSS&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;Feeds&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;Robb&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;Knight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;Blogroll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;dateCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;dateToRfc822&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;dateCreated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;site&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;blogroll&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;outline&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ site.name }}&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ site.name }}&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;rss&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;xmlUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ site.feed }}&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;htmlUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ site.url }}&quot;&lt;/span&gt;&lt;span class=&quot;token block keyword&quot;&gt;/&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endfor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;opml&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;dateToRfc822&lt;/code&gt; filter used in &lt;code&gt;dateCreated&lt;/code&gt; is a filter provided by the &lt;a href=&quot;https://www.11ty.dev/docs/plugins/rss/&quot;&gt;Eleventy RSS plugin&lt;/a&gt;. Then I loop through all of the sites in my blogroll and output an &lt;code&gt;outline&lt;/code&gt; element for each one.&lt;/p&gt;
&lt;p&gt;Finally I added a link to the file on each of the roll pages. Note I include a &lt;code&gt;download&lt;/code&gt; attribute so browsers will (hopefully) download the file rather than show the XML file directly:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;opml.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;download&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;download&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Download the OPML file&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can view my &amp;quot;rolls&amp;quot; here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/roll&quot;&gt;Blogroll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/podcasts/roll&quot;&gt;Podroll&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>How I'm creating OPML files for my blog, and pod, rolls so people can subscribe to all of the sites in one go</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>What Even is a Webmention?</title>
    <link href="https://rknight.me/blog/what-even-is-a-webmention/"/>
    <updated>2024-01-20T16:11:08Z</updated>
    <id>https://rknight.me/blog/what-even-is-a-webmention/</id>
    <content type="html">&lt;p&gt;My post about &lt;a href=&quot;https://rknight.me/blog/adding-webmentions-to-your-site/&quot;&gt;implementing webmentions on this site&lt;/a&gt; has been fairly popular and I get quite a few questions about something I don&#39;t think I explained properly in the post which all boil down to &amp;quot;what &lt;em&gt;is&lt;/em&gt; a webmention though and what has that got to do with Mastodon?&amp;quot;.&lt;/p&gt;
&lt;p&gt;Before we get started I will say I found the different pages explaining the technical details of webmentions to be lacking in terms of real-world use cases so I am basing this on what I can piece together from those sites.&lt;/p&gt;
&lt;h3&gt;&amp;quot;Real&amp;quot; Webmentions&lt;/h3&gt;
&lt;p&gt;A webmention is &amp;quot;&lt;em&gt;a simple way to notify any URL when you link to it from your site.&lt;/em&gt;&amp;quot;. The use of &amp;quot;simple&amp;quot; here is stretching the definition but it does at least explain what they are, sort of. There are different types of webmentions but the one typically used by a website is &lt;code&gt;mention-of&lt;/code&gt;. Basically, &amp;quot;&lt;em&gt;I wrote this post and I have mentioned your or your website in it&lt;/em&gt;&amp;quot;. These need to be sent from the poster to the website being mentioned. For my site I use the CLI version of &lt;a href=&quot;https://webmention.app&quot;&gt;webmention.app&lt;/a&gt;; each time a new post appears in my RSS feed, I use the command line package to send mentions to any supported site that I&#39;ve included in the post:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx webmention path/to/feed.xml &lt;span class=&quot;token parameter variable&quot;&gt;--limit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--send&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You might be thinking I&#39;d link to an example of one of these types of webmentions on my site but I don&#39;t show them. I checked my webmentions for this type and out of the ~40 or so that were there, only a handful were actually legitimate, the rest were either now-dead sites or spam. If I can come up with a system for approving them in the future, I will add them to the site. The open nature of webmentions means there&#39;s very little to stop someone from sending spam webmentions. These can be blocked in &lt;a href=&quot;http://webmention.io&quot;&gt;webmention.io&lt;/a&gt; but I would never remember to do that. I also had two &lt;code&gt;bookmark-of&lt;/code&gt; webmentions but both of those links were dead and I don&#39;t know what type of post they should refer to.&lt;/p&gt;
&lt;p&gt;I do get &lt;em&gt;some&lt;/em&gt; legitimate ones though so here is an example of one from &lt;a href=&quot;https://localghost.dev&quot;&gt;Sophie&lt;/a&gt;, truncated for the sake of legibility:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;entry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// author info&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://localghost.dev/blog/everything-should-have-an-api-adventures-in-trying-to-automate-stuff/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-01-24T00:00:00&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-received&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2024-01-19T20:43:30Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1769280&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-source&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://localghost.dev/blog/everything-should-have-an-api-adventures-in-trying-to-automate-stuff/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/automating-my-now-page/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-protocol&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;webmention&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Everything should have an API: adventures in trying to automate stuff&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;html&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;p&gt;Inspired by &amp;lt;a href=\&quot;https://rknight.me/automating-my-now-page/\&quot;&gt;Robb Knight&amp;lt;/a&gt; I want to build my own &amp;lt;a href=\&quot;https://nownownow.com/about\&quot;&gt;/now page&amp;lt;/a&gt;...&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;mention-of&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/automating-my-now-page/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-property&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mention-of&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-private&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice it has the type of &lt;code&gt;mention-of&lt;/code&gt; and the URL for &lt;a href=&quot;https://localghost.dev/blog/everything-should-have-an-api-adventures-in-trying-to-automate-stuff/&quot;&gt;the post I&#39;m being mentioned in&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Based on my understanding, there no reason you &lt;em&gt;couldn&#39;t&lt;/em&gt; send a webmention about a post you&#39;ve written as a reply or repost type but I haven&#39;t seen this being used, outside of how Bridgy converts Mastodon interactions.&lt;/p&gt;
&lt;h3&gt;Mastodon &amp;quot;Webmentions&amp;quot;&lt;/h3&gt;
&lt;p&gt;Calling what I show at the bottom of my blog posts &amp;quot;webmentions&amp;quot; is a bit misleading because they&#39;re actually posts, likes, and boosts &lt;em&gt;from Mastodon&lt;/em&gt;; nothing to do with webmentions.&lt;/p&gt;
&lt;p&gt;What&#39;s actually happening is those interactions are being &lt;em&gt;converted&lt;/em&gt; to webmentions by &lt;a href=&quot;https://brid.gy&quot;&gt;Brid.gy&lt;/a&gt; which then forwards them on to &lt;a href=&quot;http://webmention.io&quot;&gt;webmention.io&lt;/a&gt;. As an example &lt;a href=&quot;https://fediverse.zachleat.com/@zachleat/109780757249677343&quot;&gt;this toot on Mastodon from Zach&lt;/a&gt; is a reply to &lt;a href=&quot;https://social.lol/@robb/109780686521180648&quot;&gt;my toot&lt;/a&gt; which includes a link to one of my blog posts. Bridgy will see this reply and convert it to a webmention of the type &lt;code&gt;in-reply-to&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;entry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;card&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Zach Leatherman :11ty:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;photo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://webmention.io/avatar/media.social.lol/f4e48698b4079b12cff61448419d6cf2a13293b27bdaa0a551de22a70e402f70.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://fediverse.zachleat.com/@zachleat&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://fediverse.zachleat.com/@zachleat/109780757249677343&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-01-30T23:30:17&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-received&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-01-30T23:48:08Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1611442&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-source&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://brid.gy/comment/mastodon/@robb@social.lol/109780686521180648/109780761774871086&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/adding-webmentions-to-your-site/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;html&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;p&gt;&amp;lt;span class=\&quot;h-card\&quot;&gt;&amp;lt;a href=\&quot;https://social.lol/@robb\&quot; class=\&quot;u-url\&quot;&gt;@&amp;lt;span&gt;robb&amp;lt;/span&gt;&amp;lt;/a&gt;&amp;lt;/span&gt; awesome!&amp;lt;/p&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@robb awesome!&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;in-reply-to&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/adding-webmentions-to-your-site/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-property&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;in-reply-to&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string-property property&quot;&gt;&quot;wm-private&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see it has a &lt;code&gt;target&lt;/code&gt; attribute which is my blog post, the details of the author of the toot, as well as some other metadata including the &lt;code&gt;in-reply-to&lt;/code&gt; type. The same thing will happen for likes (&lt;code&gt;like-of&lt;/code&gt;) and boosts (&lt;code&gt;repost-of&lt;/code&gt;). I then use this to show this at the bottom of my posts.&lt;/p&gt;
&lt;p&gt;What Bridgy doesn&#39;t do, and I&#39;m not even sure how this could work given the federated nature of Mastdon, is pull in a toot from &lt;em&gt;someone else&lt;/em&gt; posting a link to one of my posts. In theory, I could monitor the &lt;a href=&quot;https://social.lol/public&quot;&gt;federated feed of social.lol&lt;/a&gt; and see if something pops up but it&#39;s not guaranteed to find all, if any, mentions.&lt;/p&gt;
&lt;h3&gt;Shouldn&#39;t all this be easier?&lt;/h3&gt;
&lt;p&gt;If you&#39;ve read &lt;a href=&quot;https://rknight.me/blog/adding-webmentions-to-your-site/&quot;&gt;my post&lt;/a&gt;, or &lt;a href=&quot;https://coryd.dev/posts/2023/webmentions-in-eleventy/&quot;&gt;Cory&#39;s post&lt;/a&gt;, or one of the &lt;a href=&quot;https://11tybundle.dev/categories/webmentions/&quot;&gt;many other posts about webmentions in Eleventy&lt;/a&gt; you&#39;ll know this isn&#39;t as simple or easy as it should be.&lt;/p&gt;
&lt;p&gt;First off given how few &amp;quot;real&amp;quot; webmentions I have, I&#39;m tempted to skip that part entirely and just pull Mastodon interactions directly. I&#39;m not a fan of relying on other services that I don&#39;t control so this would solve that for me. I haven&#39;t looked at the API too much for this, but I can&#39;t imagine it would be &lt;em&gt;too&lt;/em&gt; difficult&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Secondly, to my point above about relying on other services, I&#39;ve yet to see a good implementation of something that can be easily self-hosted. I want to explore that a more in the future. Let me know if there is something you&#39;re aware of.&lt;/p&gt;
&lt;p&gt;As for &lt;em&gt;sending&lt;/em&gt; webmentions I could imagine a service for sending webmentions where you just point your RSS feed at it and it deals with sending webmentions for you, rather than using something like webmention.app which is &lt;em&gt;very&lt;/em&gt; good but either requires manually entering each blog post, or setting up something on each build of your site; not the most user friendly solution.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Famous last words &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>In which I try to explain what a "real" webmention is compared to a Mastodon "webmention"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Deleting S3 Files with Spaces in the Name</title>
    <link href="https://rknight.me/blog/deleting-s3-files-with-spaces-in-the-name/"/>
    <updated>2024-01-17T15:26:31Z</updated>
    <id>https://rknight.me/blog/deleting-s3-files-with-spaces-in-the-name/</id>
    <content type="html">&lt;p&gt;This is a fun one: I had a file, lets say it was originally called &lt;code&gt;mycoolfile (2).png&lt;/code&gt;, it&#39;s been uploaded to S3, and then stored in our database. Except at some point it&#39;s become URL encoded so it looks like this instead: &lt;code&gt;mycoolfile%20%282%29.png&lt;/code&gt;. Now I want to delete that file using the &lt;a href=&quot;https://aws.amazon.com/sdk-for-php/&quot;&gt;AWS SDK for PHP&lt;/a&gt; which you can do, in theory, like so:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;s3&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;deleteObjects&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Bucket&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;coolbucket&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Delete&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Objects&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;key&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;mycoolfile%20%282%29.png&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Except, no. AWS will &lt;em&gt;not&lt;/em&gt; find that file, won&#39;t delete it, and won&#39;t give you an error message&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. Add a &lt;code&gt;urldecode&lt;/code&gt; and it deletes the file with no issues.&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;$this-&gt;s3-&gt;deleteObjects([&lt;br /&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   &#39;Bucket&#39; =&gt; &#39;coolbucket&#39;,&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   &#39;Delete&#39; =&gt; [&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   &#39;Objects&#39; =&gt; [&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;       [&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;            &#39;key&#39; =&gt; &#39;mycoolfile%20%282%29.png&#39;,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;            &#39;key&#39; =&gt; \urldecode(&#39;mycoolfile%20%282%29.png&#39;),&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;       ]&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   ],&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;]);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I guess I should have checked this sooner but I was looking for the bug in completely the wrong place so this took longer to find than expected. This blog post is definitely going to save me pain again in the future.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;This might be a limitation of the PHP SDK rather than the API in general &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>An issue I came across at work deleting files that had spaces in the filename</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Fetching Package Dependents from GitHub</title>
    <link href="https://rknight.me/blog/fetching-package-dependents-from-github/"/>
    <updated>2024-01-16T20:50:28Z</updated>
    <id>https://rknight.me/blog/fetching-package-dependents-from-github/</id>
    <content type="html">&lt;p&gt;A conversation in the &lt;a href=&quot;https://www.11ty.dev/blog/discord/&quot;&gt;Eleventy Discord&lt;/a&gt; led me to remember about the &lt;a href=&quot;https://github.com/rknightuk/eleventy-plugin-post-graph/network/dependents&quot;&gt;dependents page&lt;/a&gt; of a GitHub repository. That is, a list of other repositories that are depending on a package, in this case my &lt;a href=&quot;https://postgraph.rknight.me/&quot;&gt;Post Graph plugin&lt;/a&gt;. I wanted to show which people are using the package on the post graph website.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/post-graph-dependents.png&quot; alt=&quot;Post graph dependents&quot; /&gt;&lt;/p&gt;
&lt;p&gt;GitHub don&#39;t offer an API endpoint for this so I made a new data file in Eleventy, installed &lt;a href=&quot;https://www.npmjs.com/package/linkedom&quot;&gt;&lt;code&gt;linkedom&lt;/code&gt;&lt;/a&gt;, and got to inspecting the elements of that page. The dependents list is an element with an id of &lt;code&gt;dependents&lt;/code&gt; with two links per repo. The first leads to the author&#39;s profile and the second to the repository: this second link is the one I care about. To narrow it down I had to target both the class (&lt;code&gt;text-bold&lt;/code&gt;) and the data attribute (&lt;code&gt;data-hovercard-type&lt;/code&gt;) then grab the &lt;code&gt;href&lt;/code&gt; from it:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://github.com/rknightuk/eleventy-plugin-post-graph/network/dependents&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; html &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; document &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dependents &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#dependents .text-bold[data-hovercard-type]&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;el&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://github.com&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once this was done I could output the list on the Post Graph site at the top:&lt;/p&gt;
&lt;pre class=&quot;language-njk&quot;&gt;&lt;code class=&quot;language-njk&quot;&gt;&lt;span class=&quot;token delimiter punctuation&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;token tag keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;dependents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;Used&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;dependents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;dependents&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{ d.link }}&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endfor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;endif&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
    <summary>Using linkedom to grab all repositories that are depending on my post graph plugin</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Snippets I Use Regularly</title>
    <link href="https://rknight.me/blog/snippets-i-use-regularly/"/>
    <updated>2024-01-13T14:17:27Z</updated>
    <id>https://rknight.me/blog/snippets-i-use-regularly/</id>
    <content type="html">&lt;style&gt;
    th { width: 30%; }
    table { text-align: center; font-size: 0.9em; }
&lt;/style&gt;
&lt;p&gt;Someone recently asked me how I was able to respond to a message so quickly to a keyboard shortcut question using the command and shift symbols (&lt;kbd&gt;⌘&lt;/kbd&gt; &lt;kbd&gt;⇧&lt;/kbd&gt;) in my response. Snippets is the answer and I thought it would be a good idea to post the ones I use regularly.&lt;/p&gt;
&lt;p&gt;These all run through &lt;a href=&quot;https://www.alfredapp.com&quot;&gt;Alfred&lt;/a&gt; which is my favourite Mac app by a longshot but there are other options that do similar things like &lt;a href=&quot;https://textexpander.com/&quot;&gt;TextExpander&lt;/a&gt;, &lt;a href=&quot;https://espanso.org/&quot;&gt;Espanso&lt;/a&gt;, and &lt;a href=&quot;https://ergonis.com/typinator&quot;&gt;Typinator&lt;/a&gt;. I always prefix my snippets with &lt;code&gt;;&lt;/code&gt; so I don&#39;t accidentally trigger them during normal typing&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Exported snippets from Alfred are in an &lt;code&gt;.alfredsnippets&lt;/code&gt; file which is a wrapper around a sqlite database. Instead of copy and pasting these I used the &lt;a href=&quot;https://alfred.app/workflows/alfredapp/snippet-transformer/&quot;&gt;Snippet Transformer&lt;/a&gt; workflow to convert them to CSV for easier copying.&lt;/p&gt;
&lt;h3&gt;General Snippets&lt;/h3&gt;
&lt;p&gt;These are mostly used when write code, or git commits. The date ones I probably used 20 times a day.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto&quot;&gt;
&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;keyword&lt;/th&gt;
            &lt;th&gt;output&lt;/th&gt;
            &lt;th&gt;notes&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;em&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;email address&lt;/td&gt;
            &lt;td&gt;I also have one of these for my work email&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;dn&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;1955-11-05&lt;/td&gt;
            &lt;td&gt;Alfred syntax: &lt;code&gt;{date:Y-MM-dd}&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;cl&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;[1955-11-05]&lt;/td&gt;
            &lt;td&gt;I used this a lot for adding entries to changelogs at work&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;dtn&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;1955-11-05 06:16&lt;/td&gt;
            &lt;td&gt;Alfred syntax: &lt;code&gt;{date:Y-MM-dd HH:mm}&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;sel&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;select * from&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;cl&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;console.log()&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;uuid&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;A41861B4-3EF1-4161-B080-2F9CA025D78A&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;Alfred syntax: &lt;code&gt;{random:UUID}&lt;/code&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h3&gt;Symbols&lt;/h3&gt;
&lt;p&gt;These are ones that I really don&#39;t &lt;em&gt;need&lt;/em&gt; but it&#39;s nice to use the trademark or multiplication symbols when &lt;s&gt;shitposting on Mastodon&lt;/s&gt; having very serious conversations with my friends. Quality Jokes™: a robb × mastodon collab.&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto&quot;&gt;
&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;keyword&lt;/th&gt;
            &lt;th&gt;output&lt;/th&gt;
            &lt;th&gt;notes&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;shrug&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;bull&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;•&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;deg&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;°&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;x&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;×&lt;/td&gt;
            &lt;td&gt;This is the symbol that &lt;em&gt;should&lt;/em&gt; be used for multiplication. And collabs of course.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;tm&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;™&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;ctrl&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;⌃&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;shift&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;⇧&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;opt&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;⌥&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;cmd&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;⌘&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;kall&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;⌃⌥⇧⌘&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;kopt&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;&amp;lt;kbd&amp;gt;⌥&amp;lt;/kbd&amp;gt;&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;*&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;kcmd&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;&amp;lt;kbd&amp;gt;⌘&amp;lt;/kbd&amp;gt;&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;*&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;kshift&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;&amp;lt;kbd&amp;gt;⇧&amp;lt;/kbd&amp;gt;&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;*&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;code&gt;;kctrl&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;&lt;code&gt;&amp;lt;kbd&amp;gt;⌃&amp;lt;/kbd&amp;gt;&lt;/code&gt;&lt;/td&gt;
            &lt;td&gt;*&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;* &lt;code&gt;kbd&lt;/code&gt; is the rarely-seen &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd&quot;&gt;keyboard input element&lt;/a&gt;. Example which I definitely didn&#39;t just add to my css for this blog post: &lt;kbd&gt;⌘&lt;/kbd&gt;&lt;/p&gt;
&lt;p&gt;Update: I reordered the modifier key symbols to be in the correct &lt;a href=&quot;https://leancrew.com/all-this/2017/11/modifier-key-order/&quot;&gt;modifier key order&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It still happens on occasion &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>A list of my most-used snippets in Alfred</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>A Birthday Poem I&#39;m Sure Jason Actually Wrote and Didn&#39;t Get AI to Generate For Him</title>
    <link href="https://rknight.me/blog/a-birthday-poem-im-sure-jason-actually-wrote-and-didnt-get-ai-to-generate-for-him/"/>
    <updated>2024-01-09T22:35:07Z</updated>
    <id>https://rknight.me/blog/a-birthday-poem-im-sure-jason-actually-wrote-and-didnt-get-ai-to-generate-for-him/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/happy-birthday-robb-from-jason.jpg&quot; alt=&quot;Happy Birthday card from Jason&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s my birthday today and &lt;a href=&quot;https://grepjason.sh&quot;&gt;Jason&lt;/a&gt; has been more enthusiastic than anyone about it, including me. He sent me this e-card and email which I&#39;m sure he definitely hand-crafted himself. It&#39;s a response to &lt;a href=&quot;https://social.lol/@robb/111727140488170177&quot;&gt;this toot about my home insurance company emailing me&lt;/a&gt; which totally wasn&#39;t a &amp;quot;&lt;em&gt;thinly-veiled “please wish me a happy birthday, people of Mastodon” post&lt;/em&gt;&amp;quot;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In the dance of the years, another twirl,&lt;br /&gt;
A special day unfolds for you, Robb, in this world.&lt;br /&gt;
With laughter, joy, and dreams anew,&lt;br /&gt;
May this birthday bring delights, bright and true.&lt;/p&gt;
&lt;p&gt;From morning&#39;s light to evening&#39;s starry view,&lt;br /&gt;
May each moment sparkle with happiness through.&lt;br /&gt;
With friends like stars and memories to weave,&lt;br /&gt;
A year of wonders is what we believe.&lt;/p&gt;
&lt;p&gt;So blow out the candles, make a wish, take a slice,&lt;br /&gt;
In the journey of life, each year is a new spice.&lt;br /&gt;
From all of us at Hemispheric Views, near and far,&lt;br /&gt;
Happy Birthday, Robb, you&#39;re our shining star!&lt;/p&gt;
&lt;p&gt;*This email is GDPR compliant.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It really wasn&#39;t but I guess also it was &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>I got a poem and a picture via email from Jason that he definitely lovingly made all by himself</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Styling RSS and Atom Feeds</title>
    <link href="https://rknight.me/blog/styling-rss-and-atom-feeds/"/>
    <updated>2024-01-07T15:08:15Z</updated>
    <id>https://rknight.me/blog/styling-rss-and-atom-feeds/</id>
    <content type="html">&lt;p&gt;Styled XML? Well, I never. Look at my RSS feeds all styled and fancy:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/rss-feed-styled.png&quot; alt=&quot;My RSS feed preview&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This is done with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/XSLT/Element/stylesheet&quot;&gt;XSLT stylesheets&lt;/a&gt;. A truly exciting phrase. I would recommend reading &lt;a href=&quot;https://darekkay.com/blog/rss-styling/&quot;&gt;Darek Kay&#39;s post&lt;/a&gt; on how to do this as well as mine. I won&#39;t be repeating everything Darek wrote in his post but I do have some additional details I wanted to note down.&lt;/p&gt;
&lt;p&gt;To style an RSS or Atom feed you neeed to add a reference to an &lt;code&gt;xsl&lt;/code&gt; file which is the styling document for the feed.&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-arrow deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; &amp;lt;?xml-stylesheet href=&quot;/subscribe/styles/rss.xsl&quot; type=&quot;text/xsl&quot;?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I grabbed &lt;a href=&quot;https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl&quot;&gt;&lt;code&gt;pretty-feed-v3&lt;/code&gt;&lt;/a&gt; which is what Darek used as base for his as well. I removed all the Tailwind classes, removed the inline styles, and added a new &lt;code&gt;feeds.css&lt;/code&gt; stylesheet to Eleventy. I pulled in &lt;a href=&quot;https://andy-bell.co.uk/a-modern-css-reset/&quot;&gt;Andy Bell&#39;s CSS reset&lt;/a&gt;, my site variables, and added a few rules to make the feed look nice.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_reset.css&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* https: //andy-bell.co.uk/a-modern-css-reset/ */&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;_variables.css&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1em 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;h2, h3&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 1em 0 0 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--primary-links&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;a:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--offwhite&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.rss-feed&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--nearblack&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--offwhite&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0 auto&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 800px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; system-ui&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sans-serif&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; normal&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.nav__notice&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;--primary&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.summary&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;font-style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; italic&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;pretty-feed-v3&lt;/code&gt; works for RSS and Darek&#39;s example works for Atom but I &lt;em&gt;really&lt;/em&gt; didn&#39;t want to have to &lt;code&gt;xsl&lt;/code&gt; files for each format. What I noticed was if a value wasn&#39;t found, it would output nothing, so I could just output the value for RSS &lt;em&gt;and&lt;/em&gt; Atom to keep it to one file. See this example with the title and description:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;xsl:&lt;/span&gt;value-of&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/rss/channel/title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;xsl:&lt;/span&gt;value-of&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/atom:feed/atom:title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;xsl:&lt;/span&gt;value-of&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/rss/channel/description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;xsl:&lt;/span&gt;value-of&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/atom:feed/atom:subtitle&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another change I wanted to make was to only show the most recent five posts, rather than all of them. A bit of digging around and I found the answer to limit &lt;code&gt;xsl:for-each&lt;/code&gt; to the first five:&lt;/p&gt;
&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- atom --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;xsl:&lt;/span&gt;for-each&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/atom:feed/atom:entry[position() &lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt; 6]&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- rss --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token namespace&quot;&gt;xsl:&lt;/span&gt;for-each&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/rss/channel/item[position() &lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;lt;&quot;&gt;&amp;amp;lt;&lt;/span&gt; 6]&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally to make this work with Safari, as noted in the &lt;code&gt;pretty-feed-v3&lt;/code&gt; comments, the header must be set as &lt;code&gt;Content-Type: application/xml; charset=utf-8&lt;/code&gt;. I added this to my Nginx config:&lt;/p&gt;
&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;location&lt;/span&gt; ^.xml&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;: &lt;span class=&quot;token string&quot;&gt;&quot;application/xml; charset=utf-8&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there we go. This is &lt;em&gt;much&lt;/em&gt; nicer than showing a generic XML file or worse like on iOS where it tries to open the file in whatever application has decided it handles feeds.&lt;/p&gt;
</content>
    <summary>Some notes on how to style RSS and Atom feeds with XSLT stylesheets</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Netcraft, Facebook, and Digital Ocean</title>
    <link href="https://rknight.me/blog/netcraft-facebook-and-digital-ocean/"/>
    <updated>2024-01-06T12:18:26Z</updated>
    <id>https://rknight.me/blog/netcraft-facebook-and-digital-ocean/</id>
    <content type="html">&lt;p&gt;Now I’ve calmed down after &lt;a href=&quot;https://social.lol/@robb/111704215593992932&quot;&gt;my tootstorm&lt;/a&gt;, here’s what happened yesterday with Netcraft, Facebook, Digital Ocean, and &lt;a href=&quot;https://rknight.me/blog/convert-spotify-facebook-to-email-login/&quot;&gt;this blog post&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;At 4:06pm I received an email from DigitalOcean that said the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We’ve received a report that there may be phishing material hosted on your Droplet at 164.92.144.168 .&lt;/p&gt;
&lt;p&gt;You can review the report that’s caused this ticket to be generated at &lt;a href=&quot;https://digitalocean.abusehq.net/share/lG5vYXDEhSgX8VhNqkLfLp9YQSXQPSR680kmsD2DGMKpMdQg__0vduxKMLfCXEHh&quot;&gt;this link&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We’re currently reviewing this complaint, but wanted to notify you as soon as possible so that you can investigate and remove the content, as it is extremely harmful.&lt;/p&gt;
&lt;p&gt;After you’ve reviewed the above report and removed the listed content - should you determine the content is phishing - we’d appreciate it if you would update this ticket so we can mark the matter as resolved.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then this one three minutes later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We have not taken any action at this time regarding this complaint, but request you address it within the next 24 hours.  Please note that if we do not hear from you and the content is still active at that time we may take additional action to prevent access to the phishing material, up to and including temporary suspension of the Droplet involved.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So what&#39;s happened here:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Netcraft are contracted by Facebook to look for phishing sites related to Facebook, fair enough.&lt;/li&gt;
&lt;li&gt;Netcraft have decided through whatever method that my blog post is attempting to phish Facebook login details.&lt;/li&gt;
&lt;li&gt;They have sent an abuse report to Digital Ocean, without a human reviewing it.&lt;/li&gt;
&lt;li&gt;Digital Ocean received this report and sent me the report claiming the post is &amp;quot;&lt;em&gt;extremely harmful&lt;/em&gt;&amp;quot;. No human involved again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So Netcraft, on behalf of Facebook, had decided that my blog post was phishing and Digital Ocean have taken that at face value. Note the wording from here: &amp;quot;&lt;em&gt;...so you can investigate and remove the content, as it is extremely harmful.&lt;/em&gt;&amp;quot; and &amp;quot;&lt;em&gt;...if we do not hear from you and the content is still active at that time we may take additional action to prevent access to the phishing material&lt;/em&gt;&amp;quot;. So I&#39;m hosting dangerous phishing content and also my droplet will be suspended if I don&#39;t remove the post? Why has this email been sent before &lt;em&gt;anyone&lt;/em&gt; at DO even reviewed it.&lt;/p&gt;
&lt;p&gt;Had I not done anything because I was busy, or whatever I might have been doing, my droplet would have been suspended on a baseless claim? These emails, quite frankly, are shitty.&lt;/p&gt;
&lt;p&gt;I reported this on Netcraft&#39;s abuse page as as false positive and got these two generic responses back a while later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Opsgenie] Ben Golding acknowledged alert: False positive report for takedown incident 3ee0db5c9a6a&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;We have reviewed the site and agree that it was incorrectly identified as phishing. We have now halted the takedown process and sent retraction messages to all parties contacted. We have also removed the site from our phishing blocklist.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;quot;&lt;em&gt;...agree that it was incorrectly identified&lt;/em&gt;&amp;quot;. Wow how do you do it with only &lt;a href=&quot;https://www.helpnetsecurity.com/2023/07/18/netcraft-funding-100-million/&quot;&gt;$100m in funding&lt;/a&gt;. Truly incredible.&lt;/p&gt;
&lt;p&gt;I replied to Digital Ocean with the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The page mentioned in the abuse report (&lt;a href=&quot;https://rknight.me/blog/convert-spotify-facebook-to-email-login/&quot;&gt;https://rknight.me/blog/convert-spotify-facebook-to-email-login/&lt;/a&gt;) is not in any way related to phishing or targeting Facebook customers. It is a blog post outlining how to unlink a Facebook account from Spotify. At no point does it request user information, or advise sharing personal details with myself or any third party.&lt;/p&gt;
&lt;p&gt;No action should be taken here. The abuse report from Netcraft is completely frivolous and inaccurate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And they did reply, four hours later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thanks for sharing that update. It looks like this was a false positive, sent over via Netcraft. There&#39;s no reason to worry, this won&#39;t be suspended. Sometimes, entities will go through these brand protection agencies a bit overzealously. We just ask that folks share a timely update to any reports of this type, as noted in that original messaging. I&#39;ll close this ticket out. If we receive any future reports, we&#39;ll always forward those along in the spirit of transparency.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;quot;&lt;em&gt;Sometimes, entities will go through these brand protection agencies a bit overzealously&lt;/em&gt;&amp;quot;. And yet you take them at face value anyway? Not good enough.&lt;/p&gt;
&lt;p&gt;The same person&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; then replied again, having seen my tootstorm probably from &lt;a href=&quot;https://news.ycombinator.com/item?id=38880713&quot;&gt;Hacker News&lt;/a&gt;, a few hours later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just wanted to loop back around here since I saw the Mastodon thread and realized that there&#39;s likely a bit more information that can be useful here. Couldn&#39;t share it publicly, since it&#39;d be inappropriate to share details related to your personal account and ticket. I also realize that &amp;quot;there&#39;s no need to worry&amp;quot; can sound inconsiderate in a medium that lacks accent, tone, and the usual mannerisms that provide context to our speech. I do apologize if that read as dismissive. That is certainly not the intent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Okay I can agree with that. Intent isn&#39;t easy to convey in email. I think this was a direct response to &lt;a href=&quot;https://social.lol/@robb/111705237720008830&quot;&gt;this toot&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To be a bit more specific, there was never a risk of this Droplet being deleted, blocked or of your account having any restrictions in place.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Really? Because the previous email says &amp;quot;...&lt;em&gt;up to and including temporary suspension of the Droplet&lt;/em&gt;&amp;quot;. Sure sounds like restrictions to me. Then some more general information about how the reporting system works, included here for the sake of completeness.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In instances of reported phishing, we automatically pass along the initial report to maintain transparency and ask for either a response or the content removed. I don&#39;t think it&#39;d be appropriate of us to withhold details of companies issuing such reports against our customers, and this ask is typically a reasonable one, allowing us to easily sort out the issue with the customer taking a look and sharing their perspective on the matter if they feel the report is unreasonable. Without response or the content being removed, we don&#39;t have automated actioning at this stage and would require our team to manually review the report, the content in dispute, as well as the whole of your customer account. We have the discretion to throw out any report that doesn&#39;t align with our expectations, which would naturally occur here.&lt;/p&gt;
&lt;p&gt;Beyond phishing, our abuse team has a number of safeties baked into our infrastructure that intentionally limit us from taking action against Droplets or accounts like yours. I totally get that it can be alarming to get an alert like this, and that without the understanding shared, it can seem a bit scarier than it is. Also, worth emphasizing that no one twisted my arm to share this. I just wanted to make sure we could be as transparent as possible with you as possible and represent the work our team does in a better light, since it&#39;s certainly a hard-working group of folks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To be clear on that last point, I don&#39;t think any single person is to blame here, nor do I think the staff at Digital Ocean are being deliberately malicious. I do, however, think the wording of the initial emails are outrageously threatening and don&#39;t line up with what allegedly would have happened if I&#39;d done nothing.&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;is&lt;/em&gt; all resolved now; my droplet isn&#39;t being suspended but I&#39;m already in the process of moving my sites to &lt;a href=&quot;https://www.hetzner.com/&quot;&gt;Hetzner&lt;/a&gt;. Maybe their abuse process is just as bad as Digital Ocean, maybe it&#39;s not but that&#39;s not the point. On principle, I&#39;m moving everything.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I&#39;m sure this has happened before on this blog post but I can’t find any toots, tweets, or emails from me to confirm this. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I say &amp;quot;the same person&amp;quot; but the email is signed off as &amp;quot;Security Operations DigitalOcean Security&amp;quot; so I don&#39;t know 100% if it was the same person or not. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>Facebook, via Netcraft, falsely reported a blog post of mine as phishing and Digital Ocean threatened to suspend my server</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My Home Screen (January 2024)</title>
    <link href="https://rknight.me/blog/my-home-screen-january-2024/"/>
    <updated>2024-01-03T14:22:04Z</updated>
    <id>https://rknight.me/blog/my-home-screen-january-2024/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/homescreen-jan-2024.png&quot; alt=&quot;Homescreen&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Since the last time I &lt;a href=&quot;/blog/homescreen-november-2017/&quot;&gt;posted my homescreen&lt;/a&gt; in 2017 the main change is widgets. I still kind of dislike them and wish I could customise them more but it&#39;s better than not having them.&lt;/p&gt;
&lt;p&gt;Top left is &lt;a href=&quot;https://apps.apple.com/gb/app/marvis-pro/id1447768809&quot;&gt;Marvis Pro&lt;/a&gt; which aside from being a nice music player, also integrates with &lt;a href=&quot;http://Last.fm&quot;&gt;Last.fm&lt;/a&gt;; the main reason I use it. The other widgets are Fantastical and Reminders.&lt;/p&gt;
&lt;p&gt;Most of the apps have been on my homescreen for long time with the exception of two. &lt;a href=&quot;https://huckleberrycare.com&quot;&gt;Huckleberry&lt;/a&gt; is a baby tracking app for keeping track of feeds, sleeps, meds, and poops. It&#39;s pretty crap but my wife chose it and it&#39;s free for what we need. &lt;a href=&quot;https://omnivore.app/home&quot;&gt;Omnivore&lt;/a&gt; is my current read-later app. It&#39;s lovely, and free, but doesn&#39;t &lt;em&gt;quite&lt;/em&gt; do what I want so I&#39;m in the research phase of trying some other services.&lt;/p&gt;
&lt;p&gt;My wallpaper is Baby Knight and I have the large photo widget on the screen to the left&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. And dark mode is on always.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I have no idea what this screen is called. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>My iPhone home screen as of January 2024</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>New Old Posts</title>
    <link href="https://rknight.me/blog/new-old-posts/"/>
    <updated>2024-01-03T13:31:33Z</updated>
    <id>https://rknight.me/blog/new-old-posts/</id>
    <content type="html">&lt;p&gt;Yesterday &lt;a href=&quot;https://chrismcleod.dev/blog/new-year-old-posts/&quot;&gt;Chris imported 470 old posts of his&lt;/a&gt; into his website and I was inspired to do the same.&lt;/p&gt;
&lt;p&gt;The earliest posts I could think of were when I was writing reviews of various iPhone apps for &lt;a href=&quot;http://iPhoneWorld.ca&quot;&gt;iPhoneWorld.ca&lt;/a&gt; in 2009. Sadly the site has been offline a long time so I fired up &lt;a href=&quot;https://archive.org&quot;&gt;the internet archive&lt;/a&gt; and managed to find 14 of those reviews. It&#39;s a goldmine of glorious pre-iOS7 design, check out all the posts with the &lt;a href=&quot;https://rknight.me/blog/tags/iphoneworldca/&quot;&gt;#iPhoneWorldCA&lt;/a&gt; tag.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/iphone-3gs.png&quot; alt=&quot;iPhone 3GS homescreen&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After that I wrote for a while for &lt;a href=&quot;https://appadvice.com&quot;&gt;AppAdvice&lt;/a&gt; which &lt;em&gt;does&lt;/em&gt; still exist but all my reviews are gone. Thankfully I had archived the 15 reviews previously which you can view on the &lt;a href=&quot;https://rknight.me/blog/tags/appadvice/&quot;&gt;#AppAdvice&lt;/a&gt; tag.&lt;/p&gt;
&lt;p&gt;Deep in my computer archives I found a Tumblr backup from 2010. Most of these posts were just link posts and basically all of the links were dead. I did manage to save a few posts though:&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/blog/6-things-i-want-in-os4/&quot;&gt;6 Things I want in OS 4.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/blog/my-top-five-bookmarklets/&quot;&gt;My Top Five Bookmarklets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/blog/6-things-i-want-in-os4-updated/&quot;&gt;6 Things I want in OS 4.0 [Updated]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/blog/quick-tip-rotate-photos-in-evernote/&quot;&gt;Quick Tip: Rotate Photos in Evernote&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/blog/my-home-screen-january-2010/&quot;&gt;My Home Screen (January 2010)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally I found an old version of this site which had a lot of posts from 2010 and 2011 that weren&#39;t here for some reason, so that added another 82 posts.&lt;/p&gt;
&lt;p&gt;I updated my &lt;code&gt;postsForFeed&lt;/code&gt; collection in Eleventy so that posts older than 2013 won&#39;t show up and spam everyone&#39;s feed reader&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function-variable function&quot;&gt;postsForFeed&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;collectionApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; collectionApi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getFilteredByGlob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src/posts/blog/**/*.md&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;date&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isAfter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;2012-12-12&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;None of these posts are particularly exciting but I want to keep as much of it as I can online. As far as I know, this site now contains every article I&#39;ve ever written.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;lol Evernote &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Not a dig at you, Chris. More of a &amp;quot;thank fuck someone else did it first&amp;quot; &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>I dug into the internet archives and imported a shedload of old posts</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Making a Word Cloud for App Defaults</title>
    <link href="https://rknight.me/blog/making-a-word-cloud-for-app-defaults/"/>
    <updated>2024-01-02T12:32:59Z</updated>
    <id>https://rknight.me/blog/making-a-word-cloud-for-app-defaults/</id>
    <content type="html">&lt;p&gt;Since I last &lt;a href=&quot;https://rknight.me/blog/so-many-default-apps/&quot;&gt;blogged about&lt;/a&gt; the &lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;App Defaults&lt;/a&gt; project the number of blog posts has more than doubled; there are 320 now!&lt;/p&gt;
&lt;p&gt;A few people have said something along the lines of &amp;quot;It would be cool to see what the most popular apps are&amp;quot; and I told them I&#39;d been working on a way to do it. I shipped the best approximation I can do given the blog posts don&#39;t have a standard format: a word cloud.&lt;/p&gt;
&lt;p&gt;I created a new script called &lt;a href=&quot;https://github.com/rknightuk/app-defaults/blob/main/_wordcloud/extract.js&quot;&gt;&lt;code&gt;extract.js&lt;/code&gt;&lt;/a&gt; and used &lt;a href=&quot;https://github.com/extractus/article-extractor&quot;&gt;&lt;code&gt;@extractus/article-extractor&lt;/code&gt;&lt;/a&gt; to extract the main article content from everyone&#39;s blog posts and write that to an HTML file.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; extract &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;@extractus/article-extractor&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; fs &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;fs&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sites &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;../_data/sites.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;utf8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; sites&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; input &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sites&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;running for &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;existsSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;./_output/_&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;i&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.html&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; article &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;extract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;./_output/_&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;i&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.html&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; article&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;error caught, writing blank file&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;./_output/_&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;i&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.html&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once I had the HTML, I needed to extract the words. The initial version used a combination of regex, find-and-replace, and generally nonsense to try to get a clean set of words. This did not work; I ended up with words joined together and punctuation where it shouldn&#39;t be. I showed the demo on the &lt;a href=&quot;https://www.youtube.com/live/uMtl7hxBOJA?si=6Xr0wjxWX3e9G5dU&amp;amp;t=20064&quot;&gt;Hemispheric Views hangout&lt;/a&gt; and Jason was &lt;em&gt;very&lt;/em&gt; excited so I knew I had to get this working.&lt;/p&gt;
&lt;p&gt;This morning I realised I was making this too difficult, I just wanted the text. Javascript can do that with &lt;code&gt;innerText&lt;/code&gt; and &lt;code&gt;jQuery&lt;/code&gt; can do it with &lt;code&gt;text()&lt;/code&gt;. So I installed &lt;a href=&quot;https://www.npmjs.com/package/cheerio&quot;&gt;Cheerio&lt;/a&gt;. I used Cheerio in the past to do &lt;a href=&quot;https://rknight.me/blog/web-scraping-with-node-and-cheerio/&quot;&gt;some web scraping&lt;/a&gt;. I needed to remove some rogue punctuation after the fact, and do some splitting and joining but the output is much better than before:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; sites&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// grab the html as above&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; htmlWords &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// remove emoji&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;\n&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;?&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;endsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            wf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replaceAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;(&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replaceAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; wf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; w &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;stopWords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;w&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    htmlWords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;wordMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;word&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; wordMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;word&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;        wordMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;word&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice I&#39;m also filtering out words shorter than 3 characters, removing some common punctuation, as well as checking against a list of &lt;a href=&quot;https://en.wikipedia.org/wiki/Stop_word&quot;&gt;stop words&lt;/a&gt;. I expanded this stop words list to include some common words these blog posts all tend to have like &lt;code&gt;hemispheric&lt;/code&gt;, &lt;code&gt;duel&lt;/code&gt;, and &lt;code&gt;defaults&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To make the word cloud I&#39;m using &lt;a href=&quot;https://github.com/timdream/wordcloud2.js/?tab=readme-ov-file&quot;&gt;&lt;code&gt;wordCloud2.js&lt;/code&gt;&lt;/a&gt; which requires the words to be in this format: &lt;code&gt;[[&#39;foo&#39;, 12], [&#39;bar&#39;, 6]]&lt;/code&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. Once I had extracted all the words, I sort them by frequency, map them to the correct format, the write them to Eleventy&#39;s data directory:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// write the output of all the words&lt;/span&gt;&lt;br /&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./_output/wordMap.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wordMap&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// sort by cound&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sorted &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wordMap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; a&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; outputForWordCloud &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sorted&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    outputForWordCloud&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;word&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// write both files to the data directory&lt;/span&gt;&lt;br /&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;../_data/wordsRaw.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;wordMap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;writeFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;../_data/words.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;outputForWordCloud&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once I had my data I added it to the window object on &lt;a href=&quot;https://defaults.rknight.me/wordcloud/&quot;&gt;the Word Cloud page&lt;/a&gt; and initialised the library:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;    window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;WordCloudWords &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; words &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; stringify &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; safe &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;.canvas&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 20px solid white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;canvas&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;wordcloud-canvas&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;canvas&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;600&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;1200&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;canvas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// - 70 here to account for padding&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerWidth &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1200&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1200&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerWidth&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;70&lt;/span&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wordcloud-canvas&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;width &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; width&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wordcloud-canvas&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;height &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;600&lt;/span&gt;&lt;br /&gt;       &lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;WordCloud&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wordcloud-canvas&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;WordCloudWords&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;rotateRatio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;shrinkToFit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final result as of this writing (&lt;a href=&quot;https://defaults.rknight.me/wordcloud/&quot;&gt;view the live version here&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/app-defaults-word-cloud.jpg&quot; alt=&quot;App Defaults word cloud&quot; /&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;What a strange format choice &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>How I extracted all the words used in over 300 blog posts to make a word cloud</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Creating Permanent and Temporary Redirects with Nginx</title>
    <link href="https://rknight.me/blog/creating-permanent-and-temporary-redirects-with-nginx/"/>
    <updated>2024-01-01T13:16:10Z</updated>
    <id>https://rknight.me/blog/creating-permanent-and-temporary-redirects-with-nginx/</id>
    <content type="html">&lt;p&gt;As part of a change to move my blog posts from &lt;code&gt;/slug-of-post&lt;/code&gt; to &lt;code&gt;/blog/slug-of-post&lt;/code&gt; I needed to set permanent redirects in my Nginx config so the old post links wouldn&#39;t 404. &lt;a href=&quot;https://forge.laravel.com&quot;&gt;Forge&lt;/a&gt; has a UI for this but it only allows doing one redirect at a time and I had ~130 to do. So I grabbed a list of all my post slugs and formatted them with multi-line edit in Sublime Text&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Add the following to your Nginx config to do a redirect for a specific URL. In my case, this lives at &lt;code&gt;/etc/nginx/sites-available/rknight.me&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# 301 Moved Permanently&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;rewrite&lt;/span&gt; ^/slug-of-post /blog/slug-of-post permanent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# 302 Found/Moved Temporarily&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;rewrite&lt;/span&gt; ^/slug-of-post /blog/slug-of-post redirect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# the rest of your nginx config here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also do this for a whole domain. Although I didn&#39;t need to do this, it&#39;s worth noting here as well.&lt;/p&gt;
&lt;pre class=&quot;language-nginx&quot;&gt;&lt;code class=&quot;language-nginx&quot;&gt;&lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;server&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# redirect the root of the domain&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;rewrite&lt;/span&gt; ^/$ http://new.example.com permanent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# preserve paths&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token directive&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;rewrite&lt;/span&gt; ^/(.*)$ http://new.example.com/&lt;span class=&quot;token variable&quot;&gt;$1&lt;/span&gt; permanent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;# the rest of your nginx config here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I use VSCode for most things, but Sublime is still the best at handling multi-line editing &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>How to create redirects in Nginx</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Roast Potato Recipe</title>
    <link href="https://rknight.me/blog/roast-potato-recipe/"/>
    <updated>2023-12-30T23:52:12Z</updated>
    <id>https://rknight.me/blog/roast-potato-recipe/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/roast-potatoes.jpg&quot; alt=&quot;Roast Potatoes&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I tried this recipe on boxing day this year and it was fantastic so we made some more tonight which were, unsurprisingly, also fantastic.&lt;/p&gt;
&lt;p&gt;You will need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Maris Piper potatoes. 2kg is a reasonable amount for 4-6 people but we ate all those between three of us so do as many as you &lt;s&gt;want&lt;/s&gt; can fit in your oven&lt;/li&gt;
&lt;li&gt;Goose fat&lt;/li&gt;
&lt;li&gt;Olive oil (optional)&lt;/li&gt;
&lt;li&gt;Salt&lt;/li&gt;
&lt;li&gt;Garlic&lt;/li&gt;
&lt;li&gt;Fresh rosemary&lt;/li&gt;
&lt;li&gt;Fresh thyme&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Peel the potatoes and chop them into four (or more if you have exceptionally large potatoes). Give them a rinse to remove some of the starch. Pre-heat the oven to 180°c.&lt;/p&gt;
&lt;p&gt;Boil them in water with salt, crushed garlic, and a bit of rosemary and thyme for 15-20 minutes until they &lt;em&gt;just&lt;/em&gt; start become soft. Drain them and leave them to dry for about 10 minutes.&lt;/p&gt;
&lt;p&gt;While the potatoes are draining, pop a generous amount of goose fat (I use somewhere around 100g) in a roasting tray, along with a drizzle of olive oil if you&#39;re feeling fancy, and stick it in the oven to get the fat nice and hot.&lt;/p&gt;
&lt;p&gt;After the potatoes have dried out and the goose fat is hot, put all the potatoes in the roasting tray and make sure they all get a good covering with the fat, then into the oven with them. All told these should cook for around 90 minutes. Every 30 minutes take them out and turn them to make sure they&#39;re cooking evenly. For the last 20 minutes, sprinkle some salt on them, and pop some garlic cloves, rosemary, and thyme into the tray. Serve them up and eat all the potatoes you can.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This recipe came from a Facebook reel which I&#39;m not linking to for two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I had to OCR the steps out of the comments on the video so I worked hard for this&lt;/li&gt;
&lt;li&gt;I can&#39;t find it anymore because searching for reels is impossible&lt;/li&gt;
&lt;li&gt;Who puts a recipe in a video comment, come on&lt;/li&gt;
&lt;/ol&gt;
</content>
    <summary>A delicious roast potato recipe</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Letters with Kev Quirk</title>
    <link href="https://rknight.me/blog/letters-with-kev-quirk/"/>
    <updated>2023-12-30T23:24:40Z</updated>
    <id>https://rknight.me/blog/letters-with-kev-quirk/</id>
    <content type="html">&lt;p&gt;Just as I started the year writing back and forth &lt;a href=&quot;/blog/letters&quot;&gt;with Jason Becker&lt;/a&gt;, this month I was part of &lt;a href=&quot;https://kevquirk.com/penpals&quot;&gt;Kev&#39;s PenPals project&lt;/a&gt;. This is the conversation we had covering all kinds of topics including Christmas food, weddings, and &lt;a href=&quot;https://indieweb.org/POSSE&quot;&gt;POSSE&lt;/a&gt;. You can see Kev&#39;s &lt;a href=&quot;https://kevquirk.com/penpals/robb-knight&quot;&gt;post about this conversation here&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;1st December&lt;/h3&gt;
&lt;p&gt;Hey Robb,&lt;/p&gt;
&lt;p&gt;Hope you&#39;re doing well? Thanks for agreeing to be my PenPal for December - I&#39;m looking forward to getting to know you better. With Christmas coming up, I don&#39;t know how much opportunity we will have to email one another, but I hope it works out. If nothing else, we should have plenty to talk about. :-)&lt;/p&gt;
&lt;p&gt;No point in beating around the bush...let&#39;s dive right in, shall we? Can you tell me a little bit about yourself please? I&#39;ve been doing a bit of cyber stalking to see what I can learn about you, I don&#39;t know why, but I thought you were American. Looking at your Social.lol page it seems you&#39;re in Portsmouth? Being in the same timezone should make emailing a little easier.&lt;/p&gt;
&lt;p&gt;I also see that you got married recently. Congratulations! My and I got married around 3.5 years ago, in the summer before the pandemic hit. We&#39;ve been together for, like 16 years now I think, and we never really intended to get married. We decided to once we made the decision the adopt - we figured it would be less confusing for the kids if we all had the same surname. 🤷‍♂️&lt;/p&gt;
&lt;p&gt;Romance is not dead in the Quirk household!&lt;/p&gt;
&lt;p&gt;OK, I&#39;ve held off long enough...please please please tell me about &lt;a href=&quot;https://rknight.me&quot;&gt;your site&lt;/a&gt;. I LOVE the design of it. The colours, the typography, the subtle texture on the background. It&#39;s just lovely. What are you using at the backend?&lt;/p&gt;
&lt;p&gt;I notice you&#39;re using &lt;a href=&quot;https://home.omg.lol&quot;&gt;social.lol&lt;/a&gt; too; have you ever thought about using their platform to host your site? I have an account there too, more to explore it than anything else. The sheer number of services available for the price is great value, and they&#39;re always adding new stuff. I think if I ever left &lt;a href=&quot;https://fosstodon.org&quot;&gt;Fosstodon&lt;/a&gt;, I&#39;d probably switch to their Mastodon instance.&lt;/p&gt;
&lt;p&gt;I think this is more than enough to get us started. Looking forward to your reply.&lt;/p&gt;
&lt;p&gt;Kev&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;1st December&lt;/h3&gt;
&lt;p&gt;Hi Kev,&lt;/p&gt;
&lt;p&gt;Firstly, this is a nice bookend to the year because I started January with a similar project with &lt;a href=&quot;https://json.blog/letters/&quot;&gt;Jason Becker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You are right that I&#39;m in Portsmouth. I was born here, then lived for most of my school years in Southampton, and moved back here afterwards. I work as a developer for a property software company here in Portsmouth. I live with my wife, cat, and nearly-nine month old daughter. We were &lt;em&gt;supposed&lt;/em&gt; to get married in September 2020 but because of &lt;em&gt;the event&lt;/em&gt; we moved it to May 2021. Then the restrictions made it difficult to have the day we wanted we decided to move house instead and so we got married this year. I would not recommend having a baby and getting married in the same year 😅&lt;/p&gt;
&lt;p&gt;To your point about getting married for more &amp;quot;practical&amp;quot; reasons, we totally get that - if we&#39;d been able to get deposits back from various vendors we may have gone for the cheaper registry office wedding instead of what we had. That said we had a great day even if it was the hottest day of the year.&lt;/p&gt;
&lt;p&gt;Now, to the real questions: my website. We&#39;ve crossed paths &lt;em&gt;just&lt;/em&gt; as I pushed a new design. My previous design I had for a couple of years (which is &lt;a href=&quot;https://2023.rknight.me&quot;&gt;archived here&lt;/a&gt;) and as much as I loved it, the &amp;quot;boxy&amp;quot; design was pushing me into a corner where I was struggling to make big changes to layouts so I knew I wanted a new design but I didn&#39;t know &lt;em&gt;what&lt;/em&gt; I wanted. Until I saw the &lt;a href=&quot;https://simplebits.shop/collections/fonts/products/cartridge&quot;&gt;Cartridge font from Simplebits&lt;/a&gt; and I knew I wanted a site that was reminiscent of the Atari 2600-type designs from the game covers.&lt;/p&gt;
&lt;p&gt;Speaking of design, a friend and I were discussing monogram logos recently and how we have awkward letters to make a nice monogram with. Then I remembered yours and showed it to her and she was &lt;em&gt;furious&lt;/em&gt; at how good it is. I love it.&lt;/p&gt;
&lt;p&gt;I&#39;m using &lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt; for my site hosted on Digital Ocean and have done for maybe five years. I love the flexibility it gives me to pull in data from a bunch of different sources and manipulate it however I want. It&#39;s what I use for most of my side projects if I can. I&#39;m a big fan of using as little as possible to build websites; if I can avoid a database or javascript, I will. Speaking of which, I recently used simple.css on a project and it saved me a lot of time so thanks for that.&lt;/p&gt;
&lt;p&gt;How do you like Kirby? I saw your post about the custom forms for the penpals project and it looks like an excellent CMS but I&#39;ve not had occasion to use it.&lt;/p&gt;
&lt;p&gt;As for hosting my site on omg.lol I don&#39;t use it for similar reasons that you mentioned for not using micro.blog: I want &lt;em&gt;a lot&lt;/em&gt; more control over everything I can. I like to automate things, like &lt;a href=&quot;https://rknight.me/automating-my-now-page/&quot;&gt;my now page&lt;/a&gt;, and generally be able to control as much as I can with my own code. Weblog.lol is an excellent blogging platform, but it&#39;s not for me. I &lt;em&gt;do&lt;/em&gt; swear by social.lol as an instance though: I&#39;ve been burned twice by instances (one Mastodon and one Lemmy) just shutting down overnight and not being able to export my data. I need to be on an instance where I know who&#39;s running it and that I can pay money to so that instance continues to run.&lt;/p&gt;
&lt;p&gt;I can talk about open web protocols until the cows come home so I&#39;ll stop for now.&lt;/p&gt;
&lt;p&gt;Speak soon,&lt;br /&gt;
Robb&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3rd December&lt;/h3&gt;
&lt;p&gt;Hey Robb,&lt;/p&gt;
&lt;p&gt;Thanks for the reply. I originally said in the first post that I&#39;d exchange 1 email per week with my PenPal, but if you&#39;re happy with whatever cadence suite our schedule at the time (i.e. we just email back and forth whenever it suits) I&#39;m good with that if you are?&lt;/p&gt;
&lt;p&gt;Young children seem like such hard work. Our boys are adopted - we decided early on in our relationship that we didn&#39;t want kids, but later decided that we wanted a family, but still didn&#39;t feel the need to have biological kids, so we decided to adopt - anyway, I digress...our kids are adopted and they came home when they were 5 and 2, so we never experienced the baby part of bringing up kids. Which feels like a double edge sword; on the one hand, se dodged all the long nights etc. but on the other, we missed out on making that early bond with them. So simultaneously envy and don&#39;t envy you. :)&lt;/p&gt;
&lt;p&gt;Ah, don&#39;t get me started on how expensive weddings are. My wife and I decided early on that we wanted to keep it small, so we set the budget at £10k (&lt;em&gt;ten thousand pounds&lt;/em&gt; for a &lt;strong&gt;single&lt;/strong&gt; day!) and so we started looking at venues. Slowly but surely the budget began to creep up until we were having conversations about £30k weddings.&lt;/p&gt;
&lt;p&gt;Luckily we both saw sense, reeled it back in and ended having a lovely wedding for around the original budget. Pissed it down the whole day though haha.&lt;/p&gt;
&lt;p&gt;You previous &amp;quot;boxy&amp;quot; design is quite similar to the design I have now on my site, actually. I&#39;ve considered using the &lt;code&gt;box-shadow&lt;/code&gt; on things like cards etc. but decided against over-using them and just having them on buttons instead.&lt;/p&gt;
&lt;p&gt;The Cartridge font is really nice - and not obnoxiously priced like many fonts. I&#39;ve never heard of Simplebits before - they have some great fonts, and all seem to be very reasonably priced.&lt;/p&gt;
&lt;p&gt;Thanks for the kind words about my monogram. I&#39;m really happy with how it turned out, but I suppose K &amp;amp; Q are easy to put together in this way.&lt;/p&gt;
&lt;p&gt;I&#39;m similar to you - I prefer to use no JavaScript on my site. I&#39;ve been thinking about introducing a colour switcher so it doesn&#39;t only rely on &lt;code&gt;prefers-color-scheme&lt;/code&gt; so would need to introduce some JS for that, but I&#39;m still on the fence. I used Jekyll when this site was on an SSG, but did consider a move to 11ty more than once. I&#39;ll definitely use it on a project at some point.&lt;/p&gt;
&lt;p&gt;I&#39;m really enjoying Kirby. Like &lt;em&gt;really&lt;/em&gt; enjoying it. I always liked WP, but the sheer amount of noise in the control panel frustrated me. Kirby is really bare bones by default, and allows you to build panels that make sense to you.Once you have it nailed, it&#39;s like having a custom build CMS, just for you. And because it&#39;s not DB driven, if I want to create content in a text editor, I can do that too. It&#39;s so flexible, I really love it.&lt;/p&gt;
&lt;p&gt;I&#39;m with you on the omg.lol thing. I think it&#39;s a great out-of-box solution for someone who&#39;s just getting started, or someone who doesn&#39;t want to manage their own site. I&#39;m going to be penpalling (is that even a word?) with &lt;a href=&quot;https://gabz.blog&quot;&gt;Gabz&lt;/a&gt; in June; he used omg.lol for his blog for a while, so I&#39;ll be interested to hear what he says about it.&lt;/p&gt;
&lt;p&gt;Oof this is SUCH a long email already, but I&#39;d love to talk about open protocols too, so I&#39;ll just bullet out some of my thoughts and we can dig into them more (along with your thoughts) in our next exchange:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I think ActivityPub has the potential to be &lt;em&gt;great&lt;/em&gt; but I wonder how well it will scale. Fosstodon only has like 60k users and it&#39;s really expensive to run already. Goodness knows what it must cost Eugen to run .social&lt;/li&gt;
&lt;li&gt;If I were ever to run my own instance, I think I&#39;d go with GoToSocial, as it seems to be quite lightweight and it supports most of the spec&lt;/li&gt;
&lt;li&gt;I don&#39;t understand why BlueSky tried to re-invent the wheel? Why not just on the AP bandwagon?&lt;/li&gt;
&lt;li&gt;I don&#39;t think Threads will ever support AP - that&#39;s just a pipedream&lt;/li&gt;
&lt;li&gt;I used to run the IndieWeb stack on my site, but it&#39;s so convoluted to plug it all together, that I decided to abandon it. I think if it&#39;s ever going to gain traction, there needs to be either a hosted solution that supports it natively, or it needs to be hugely simplified&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, this email ended up being WAY longer than I intended it to be. Sorry about that. Looking forward to hearing your thoughts on the open protocols.&lt;/p&gt;
&lt;p&gt;Kev&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;10th December&lt;/h3&gt;
&lt;p&gt;Hey Kev,&lt;/p&gt;
&lt;p&gt;Firstly, our wedding came out around the same price as yours and that was considered &amp;quot;cheap&amp;quot; in comparison to some of my friends. I try not to think about the money and just remember the day which was wonderful.&lt;/p&gt;
&lt;p&gt;I&#39;m looking forward to seeing what you and Gabz talking about, he&#39;s a great guy.&lt;/p&gt;
&lt;p&gt;Now onto the meaty stuff: open protocols.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fosstodon only has like 60k users and it&#39;s really expensive to run&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was one of the reasons I built &lt;a href=&quot;https://bugle.lol/&quot;&gt;Bugle&lt;/a&gt; - I wanted something I could run easily on my server to create accounts for little side projects and such., Even for a single user who has a few hundred followers, or uploads a lot of photos, it can get expensive quick with Mastodon. The way it handles files and the duplication that happens is a huge problem in getting smaller instances up and running and probably why we see so many users on the main four or five instances. Building Bugle did give me a good insight into how a lot of the protocols work but it&#39;s &lt;em&gt;hard&lt;/em&gt;. The lack of documentation, or more specifically, examples of how the spec should work make it difficult. The developer of Pixelfed, Dan, was incredibly helpful in pointing me in the right direction for things I was stuck on.&lt;/p&gt;
&lt;p&gt;How do you find running an instance with that many users? Does moderation take up a lot of time or is it generally pretty good for Fosstodon?&lt;/p&gt;
&lt;p&gt;I hadn&#39;t heard of GoToSocial until you mentioned it but that looks much closer to what I was trying to achieve with Bugle and I&amp;quot;m adding that to my list to investigate. I don&#39;t have much to say on BlueSky or Threads, neither of them interest me if they don&#39;t support AP so I don&#39;t pay them much attention (although I do have accounts on both). The one thing I do like with Bluesky is the domain-as-a-username. That is something that does excite me and I know Mastodon has talked about implementing something similar in the future.&lt;/p&gt;
&lt;p&gt;I agree with you on the IndieWeb stuff, I&#39;ve implemented webventions and recently some other metadata-type things, but like AP it just doesn&#39;t feel like it&#39;s that well documented. &lt;a href=&quot;https://getindiekit.com/&quot;&gt;IndieKit&lt;/a&gt; looks promising in that it&#39;s runs separately from your site and handles all the IndieWeb stuff one might need. It doesn&#39;t have everything yet but it&#39;s one to keep an eye on.&lt;/p&gt;
&lt;p&gt;We are now just about two weeks from Christmas, how are you plans coming along for the day?&lt;/p&gt;
&lt;p&gt;Speak soon,&lt;br /&gt;
Robb&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;12th December&lt;/h3&gt;
&lt;p&gt;Hey Robb,&lt;/p&gt;
&lt;p&gt;It&#39;s crazy how expensive weddings can get. My sister-in-law is married to an Indian and they had a traditional Indian wedding, with a TONNE of people. I dread to think how much theirs cost.&lt;/p&gt;
&lt;p&gt;Scalability of Mastodon does concern me. The way in which is caches everything from every server/account it&#39;s connected to means things spiral quickly. I remember speaking with Hugo, who runs Masto.host, and he said with me having around 26k followers, a single-user instance would be around $50/month just because of the amount of other instances it would have to connect to.&lt;/p&gt;
&lt;p&gt;When Mike and I started Fosstodon, we decided early on to go with a hosted solution, as it would be one less thing for us to worry about. Turns out it was the best decision, as I really wouldn&#39;t want to be managing the infrastructure myself with so many people relying on it. We&#39;ve since grown out &lt;a href=&quot;https://hub.fosstodon.org/team/&quot;&gt;the moderation team&lt;/a&gt; so that Mike and I can take a step back from the moderation stuff and can focus on other things, like dealing with the various parts that make up the service etc.&lt;/p&gt;
&lt;p&gt;At the same time, we also decided to go invite-only. Mainly to force people to go to other servers, and we&#39;re far bigger than we ever thought we would be, and honestly, it worries me. I don&#39;t want to be responsible for the social network of so many people. But also for moderation - previously we were approving every account that signed up, and we moderate heavily. It&#39;s a large burden, but it keeps the timeline (I think) clean and friendly. I have a test account on .social and local timeline over there is a hot mess.&lt;/p&gt;
&lt;p&gt;I was listening &lt;a href=&quot;https://ruminatepodcast.com/&quot;&gt;Ruminate&lt;/a&gt; this morning on my way to work; you and Johnny were talking about blog posts vs micro/social posts and what belongs where. Have you ever thought about integrating social with your blog?&lt;/p&gt;
&lt;p&gt;I decided that they&#39;re 2 different use cases, and I personally dislike it when my RSS feeds contain multiple hot takes per day, as that&#39;s not what I want it for - my RSS feeds are for longer form content. I enjoy both hot takes and longer articles, but I have to be in a different frame of mind to consume each, so mangling them both together makes no sense to me.&lt;/p&gt;
&lt;p&gt;Ah, Christmas. We&#39;re doing ok. There&#39;s still a few presents to buy, and a lot to wrap, but we&#39;re pretty close, I think. We do things a bit differently on Christmas day. Instead of having a big fancy roast dinner, we cook a simple curry and enjoy that instead. That way, we&#39;re not slaving in the kitchen all day and can enjoy the day as a family. Hows about you? You all sorted yet?&lt;/p&gt;
&lt;p&gt;Look forward to talking soon.&lt;/p&gt;
&lt;p&gt;Kev&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;22nd December&lt;/h3&gt;
&lt;p&gt;Hey Kev,&lt;/p&gt;
&lt;p&gt;Been a while since I replied, we&#39;ve had a hectic week over at the Knight household with illnesses going round everyone.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Have you ever thought about integrating social with your blog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think about this &lt;em&gt;all the time&lt;/em&gt;. I do have a mirror of my Mastodon feed on my site as a sort of backup, but I would like to get to a point of proper &lt;a href=&quot;https://indieweb.org/POSSE&quot;&gt;POSSE&lt;/a&gt;. For that to work for me I really need to be able to post from mobile, which means integrating a CMS of some kind. I&#39;m looking at Kirby as well as Wordpress but also considering building my own. &amp;quot;The developer curse&amp;quot; as I like to call it.&lt;/p&gt;
&lt;p&gt;I agree having them in one feed (long posts and short posts) isn&#39;t what I&#39;d like from someone else&#39;s site so I certainly wouldn&#39;t be doing that on mine. I also want to split out some things to services more suited to the media; right now I post photos directly on Mastodon but I think Pixelfed would make a lot more sense for me. They are releasing &amp;quot;Solo&amp;quot;, a single-user version of Pixelfed soon so I&#39;ll be checking that out as soon as it&#39;s available.&lt;/p&gt;
&lt;p&gt;As for Christmas we&#39;re all sorted now, the food is in the fridge ready, chocolates are scattered around the house in bowls for grabbing as we walk past, and my daughter has met Santa for the first time. This year will be the first time I&#39;ve cooked for my dad so I&#39;m pulling out all the stops.&lt;/p&gt;
&lt;p&gt;If I don&#39;t speak to you again before Christmas (because apparently it&#39;s only 3 days away 😱) have a good one and I&#39;ll speak to you soon.&lt;/p&gt;
&lt;p&gt;Robb&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;24th December&lt;/h3&gt;
&lt;p&gt;Hey Robb,&lt;/p&gt;
&lt;p&gt;Good to hear from you and hope you and the family are all feeling better now!&lt;/p&gt;
&lt;p&gt;Thanks for you help on the &lt;a href=&quot;https://echo.rknight.me&quot;&gt;Echo&lt;/a&gt; thing - that really helped, but has had the undesired effect of making me explore POSSE again and whether I should start posting &amp;quot;notes&amp;quot; to my blog and have them syndicate to Masto. Problem is, I then go down this rabbit hole of &amp;quot;but I won&#39;t have replies...&amp;quot; so then I start looking at webmentions and the whole thing gets so complicated.&lt;/p&gt;
&lt;p&gt;I&#39;m also considered adding a bookmarks page to my site. Kinda like a self-hosted read later type thing. Or just a resource that people can use to see what I&#39;ve found interesting or useful. But I don&#39;t know whether I&#39;m going to implement that. If I do, I&#39;ll probably switch my about page to my home page, then have my posts served from /blog/ as the site will be far more than just a blog at that point. I dunno what I&#39;ll do ultimately, but it&#39;s so much fun playing with this stuff.&lt;/p&gt;
&lt;p&gt;I see you&#39;re looking at &lt;a href=&quot;https://tina.io&quot;&gt;TinaCMS&lt;/a&gt; - I was keeping an eye on that project when I was running Jekyll. It&#39;s looks really good, but was only in beta when I switched, so never explored it further.&lt;/p&gt;
&lt;p&gt;You know, we have a distinct lack of chocolate in casa Quirk this year, which is disappointing. I think my wife hasn&#39;t bothered because of all the work I&#39;ve put in losing weight, but I&#39;m happy to put on a few KG over the next couple weeks. I might have to nip the shops for a couple boxes! :)&lt;/p&gt;
&lt;p&gt;Cooking Christmas dinner is so much pressure. Good luck cooking for your old man! We tend to have a quiet Christmas, where we don&#39;t even have a roast dinner actually. Our tradition is to cook a curry. The kids don&#39;t really like roast dinners, so seems silly to spend all day in the kitchen for a meal they won&#39;t enjoy.&lt;/p&gt;
&lt;p&gt;Anyway, it&#39;s the big day tomorrow. Hope you and the family have a great one and that there&#39;s no problems with dinner.&lt;/p&gt;
&lt;p&gt;Talks soon,&lt;/p&gt;
&lt;p&gt;Kev&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;30th December&lt;/h3&gt;
&lt;p&gt;Hey Kev,&lt;/p&gt;
&lt;p&gt;Hope your Christmas went well. The cooking for my dad went well, he was very impressed so much so that he said he’s never cooking on Christmas and I have to do every year. I’ll be getting my roast potato recipe up on the blog hopefully tomorrow.&lt;/p&gt;
&lt;p&gt;If you subscribe my RSS feed you might have seen a sneak peek at what I plan to build next year, but I’m still torn on bookmarks, POSSE notes, etc. It’s a hard problem to solve or at least come up with something I’m happy with.&lt;/p&gt;
&lt;p&gt;I am completely chocolated (and cheesed) out now so we’re back to proper dinners and mealtimes. We have been having bacon and egg sandwiches every morning this week which has been nice treat.&lt;/p&gt;
&lt;p&gt;No plans for new years here, I expect we’ll watch some movies and wait until midnight when I’m sure Baby Knight will wake up because of the fireworks. Do you have any fun plans at all?&lt;/p&gt;
&lt;p&gt;I guess this will likely be the last exchange for this month’s letters. I’m looking forward to seeing who you’ve got lined up for next year. This has been a lot of fun and I’ll definitely be asking for your opinions on all this POSSE stuff in the next few months as I try and get to grips with it all.&lt;/p&gt;
&lt;p&gt;Speak soon,&lt;/p&gt;
&lt;p&gt;Robb&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;30th December&lt;/h3&gt;
&lt;p&gt;Hey Robb,&lt;/p&gt;
&lt;p&gt;Yeah, Christmas was great thanks. Just very chilled and lots of family time. I still have another week off work, so only halfway through the holiday yet. Sounds like you&#39;re on he hook for all the Christmas dinners from now on...no pressure!&lt;/p&gt;
&lt;p&gt;I do subscribe to your RSS feed - I&#39;m looking forward to seeing what comes of it all. Personally, I&#39;m still undecided. Integrating notes into the site would be trivial at this point, but I really don&#39;t know whether the juice is worth the squeeze.&lt;/p&gt;
&lt;p&gt;I&#39;ve been eating so much crap the last week or so, as I&#39;m writing this very email, I&#39;m chomping on a pack of Kettle chips. 🤦‍♂️ Oh well, I&#39;ll get back on the wagon after the holidays.&lt;/p&gt;
&lt;p&gt;It&#39;s actually my mum&#39;s birthday tomorrow, so I&#39;ll go up and see her for a few hours, then I think we&#39;re going to our neighbours house for a few drink tomorrow evening.&lt;/p&gt;
&lt;p&gt;Yeah, this is likely going to be the last exchange. Thanks so much for taking the time to be my PenPal for this last month, it&#39;s been great getting to know you better and I&#39;m looking forward to continuing to get to know you better in the future.&lt;/p&gt;
&lt;p&gt;Happy new year, and talk soon!&lt;/p&gt;
&lt;p&gt;Kev&lt;/p&gt;
</content>
    <summary>I emailed with Kev during December as part of his PenPals project</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Another Project I Forgot About</title>
    <link href="https://rknight.me/blog/another-project-i-forgot-about/"/>
    <updated>2023-12-29T15:58:44Z</updated>
    <id>https://rknight.me/blog/another-project-i-forgot-about/</id>
    <content type="html">&lt;p&gt;Welcome to the Knight club - RSS-only posts. These only show for RSS subscribers but feel free to share them. &lt;a href=&quot;https://daverupert.com/rss-club/&quot;&gt;Read more about RSS club&lt;/a&gt;.&lt;/p&gt; &lt;hr&gt; &lt;p&gt;I totally forgot about one more project I&#39;d like to get done this year. I want to take my current Eleventy-based site I used for &lt;a href=&quot;https://ruminatepodcast.com/&quot;&gt;my&lt;/a&gt; &lt;a href=&quot;https://wegot.family/&quot;&gt;podcasts&lt;/a&gt; and make it usable for anyone to quickly get a podcast up and running. I need to move any hard-coded stuff to a data file, plus decide how to handle file uploads and storage.&lt;/p&gt;
&lt;p&gt;In the spirit of committing myself to this, I&#39;m posting it here as an addendum to the &lt;a href=&quot;https://rknight.me/blog/welcome-to-the-knight-club/&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A project I forgot to include in the first Knight club post</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Welcome to the Knight Club</title>
    <link href="https://rknight.me/blog/welcome-to-the-knight-club/"/>
    <updated>2023-12-29T13:21:50Z</updated>
    <id>https://rknight.me/blog/welcome-to-the-knight-club/</id>
    <content type="html">&lt;p&gt;Welcome to the Knight club - RSS-only posts. These only show for RSS subscribers but feel free to share them. &lt;a href=&quot;https://daverupert.com/rss-club/&quot;&gt;Read more about RSS club&lt;/a&gt;.&lt;/p&gt; &lt;hr&gt; &lt;p&gt;Congratulations on subscribing via RSS, you get these bonus posts. Lucky you. Welcome to the Knight Club&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;What am I going to post here? Not a clue to be honest but there are things that I want to talk about that don&#39;t need to be full posts. I might &amp;quot;release&amp;quot; these into the &lt;a href=&quot;/blog&quot;&gt;main archive page&lt;/a&gt; after a year or so, mostly for my own sanity of finding them.&lt;/p&gt;
&lt;p&gt;It&#39;s two days before the end of 2023 so I want to write down what projects I plan to do in the next 12 months. I don&#39;t mind talking about what I&#39;m working on but I don&#39;t think a &amp;quot;proper&amp;quot; blog post makes sense until I have something to release. Firstly, I have a couple of in progress projects I want to finish.&lt;/p&gt;
&lt;p&gt;Meta checker (I will come up with a better name) is similar to &lt;a href=&quot;https://metatags.io/&quot;&gt;metatags.io&lt;/a&gt; but more suited to the specific things I want to check for a website: favicon, Safari accent color, is the RSS feed auto-detectable, those kinds of things. It will serve as a checklist of sorts for when I&#39;m nearly done with a project.&lt;/p&gt;
&lt;p&gt;The second is &lt;a href=&quot;https://echo.rknight.me/&quot;&gt;Echo&lt;/a&gt;. I want to make this a more friendly service for non-tech people to use. Right now it requires NodeJS knowledge, a horrible Javascript config file, and a pocket full of hopes and dreams.&lt;/p&gt;
&lt;p&gt;Now for the new projects. The first is a GitHub-based CMS, similar to &lt;a href=&quot;https://tina.io/&quot;&gt;TinaCMS&lt;/a&gt;. If you follow me on Mastodon, you&#39;ll know I&#39;ve had &lt;em&gt;a lot&lt;/em&gt; of issues with getting Tina set up. I&#39;m not sure how their backend works but it is definitely more complicated than it needs to be. I think I can make something more suited to what I want and hopefully what other people want.&lt;/p&gt;
&lt;p&gt;The second project has already been through multiple iterations: Almanac. A media logging website. Think Letterboxd but for everything: movies, TV shows, podcasts, music, books. I initially wanted to make this a service people signed up for and used but the licensing around the data just isn&#39;t worth the hassle. So instead, I&#39;m going to make it a self-hosted, bring-your-own-api-keys site. It&#39;ll have a nice API to be able to update my &lt;a href=&quot;/now&quot;&gt;/now page&lt;/a&gt;, feeds to auto-post to Mastodon, and some other fun stuff. The API itself is done but I need to consider how I want the front end to work.&lt;/p&gt;
&lt;p&gt;Finally, webmentions. How do they work? I &lt;a href=&quot;https://rknight.me/blog/adding-webmentions-to-your-site/&quot;&gt;wrote a post about it&lt;/a&gt; and I&#39;m still not entirely sure. I&#39;m relying on &lt;a href=&quot;https://webmention.io/&quot;&gt;Webmention.io&lt;/a&gt; and &lt;a href=&quot;https://brid.gy/&quot;&gt;Bridgy&lt;/a&gt; but &lt;em&gt;how&lt;/em&gt; do they work? I want to make my own thing to handle webmentions and conversation from Mastodon but I need to dig into the formats first.&lt;/p&gt;
&lt;p&gt;That&#39;s it for now, have a great new years!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;When I &lt;a href=&quot;https://rknight.me/blog/changing-your-name-by-deed-poll/&quot;&gt;changed my name&lt;/a&gt; I didn&#39;t consider how many good puns I was going to be able to make with it, just a fun little bonus. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>The inaugural RSS club post</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The Web is Fantastic</title>
    <link href="https://rknight.me/blog/the-web-is-fantastic/"/>
    <updated>2023-12-28T23:52:27Z</updated>
    <id>https://rknight.me/blog/the-web-is-fantastic/</id>
    <content type="html">&lt;p&gt;Reading the title you might be thinking &amp;quot;&lt;em&gt;Yeah no shit Robb of course the web&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; is fantastic it&#39;s literally the cornerstone of all commerce and communications in the modern world&lt;/em&gt;&amp;quot;. Or maybe you&#39;re not thinking that. But I&#39;m not talking about the web as a whole, I&#39;m talking about the open web. The &lt;em&gt;come-do-cool-things-with-our-api&lt;/em&gt; web. The open standards web. The &lt;a href=&quot;https://indieweb.org/&quot;&gt;indie web&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;p&gt;Services like &lt;a href=&quot;https://linktr.ee/&quot;&gt;Linktree&lt;/a&gt; exist because Facebook, TikTok, et al decided that links are okay but only if it&#39;s to their stuff. You, the creator of the video/photo/whatever only get one link, better make it a good one. Even then, my wife sometimes sends me links of Facebook &lt;em&gt;don&#39;t-call-it-tiktoks&lt;/em&gt; and unless I install the mobile app, those links just don&#39;t work.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;real&lt;/em&gt; web is built on links. Hyper ones, in fact. Links you can share on your website. Links you can send to your mates. Links to pages that can be indexed by search engines so you can find things again (in theory).&lt;/p&gt;
&lt;p&gt;Look at this journey &lt;a href=&quot;https://chrisenns.com/2023/11/app-defaults/&quot;&gt;Chris went through to stumble upon the App Defaults project&lt;/a&gt;:&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I was adding a link to omg.lol, a blog and email hosting service that&#39;s cute AND easy AND (relatively) cheap, to my newsletter.&lt;/p&gt;
&lt;p&gt;While browsing their help and info page, I saw that they offer a /now/ feature that lets you update the world on what you&#39;re working on, reading, watching, etc... now. Old school internet at it&#39;s best.&lt;/p&gt;
&lt;p&gt;I clicked through to the omg.lol /now garden which has examples of how people are using /now to update the world.&lt;/p&gt;
&lt;p&gt;I randomly picked Rebecca Owen&#39;s /now page.&lt;/p&gt;
&lt;p&gt;Then I clicked back through to her omg.lol page to see how she was using it.&lt;/p&gt;
&lt;p&gt;I saw she had a blog, so I checked that out.&lt;/p&gt;
&lt;p&gt;The most recent post on Rebecca&#39;s blog was one called Default Apps 2023. That&#39;s clickbait-up-arrow.gif material for me.&lt;/p&gt;
&lt;p&gt;She had included a link to an episode a podcast called Hemispheric Views, and this defaults page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is cool. That is how we should find interesting things. With links. The big social media sites have decided that actually no, we don&#39;t like links. Just sort of &amp;quot;find&amp;quot; things and if you don&#39;t find it well tough shit. Sharing interesting websites, blogs, and articles on your own site is the way to go. Make a &lt;a href=&quot;https://blogroll.org&quot;&gt;blogroll&lt;/a&gt;. Make a &lt;a href=&quot;/podcasts/roll/&quot;&gt;podroll&lt;/a&gt;. Share links on your Mastodon account.&lt;/p&gt;
&lt;h3&gt;Blogs and RSS&lt;/h3&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://aboutfeeds.com/&quot;&gt;About Feeds&lt;/a&gt; to see how RSS works and apps that work with it. I use &lt;a href=&quot;https://netnewswire.com/&quot;&gt;NetNewsWire&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Blogs and RSS never died. Some of us just took a little break from it while we all shitposted on Twitter for likes, retweets, and validation. While we wrote long, unfindable threads instead of blog posts. I&#39;m as guilty of this as anyone.&lt;/p&gt;
&lt;p&gt;Get an RSS app or service and install an extension that auto detects RSS feeds. Keep an eye on it while you&#39;re browsing around and grab every feed you see. You can easily unsubscribe if it&#39;s not for you. Here&#39;s over &lt;a href=&quot;https://defaults.rknight.me&quot;&gt;300 blogs to get you started&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Chris McLeod said this about blogging in his post, &lt;a href=&quot;https://chrismcleod.dev/blog/blogging-is-where-its-at-again/&quot;&gt;&amp;quot;Blogging is where it&#39;s at, again&amp;quot;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;stumbling into such a trove of &lt;em&gt;active&lt;/em&gt; blogs has enthused me about blogging as a medium again&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He&#39;s right. Blogging &lt;em&gt;is&lt;/em&gt; where it&#39;s at. Get a blog. Post some stuff.&lt;/p&gt;
&lt;p&gt;If you have a website, don&#39;t forget to &lt;a href=&quot;https://rknight.me/please-expose-your-rss/&quot;&gt;expose your RSS&lt;/a&gt;. Have a big prominent button. Make sure it&#39;s in your &lt;code&gt;head&lt;/code&gt; for auto-detection. Maybe start an &lt;a href=&quot;https://daverupert.com/rss-club/&quot;&gt;RSS club&lt;/a&gt;. Post some wonderful things, or sad things, or &lt;em&gt;only-interesting-to-you&lt;/em&gt; things.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3&gt;Extras&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Add a &lt;code&gt;/now&lt;/code&gt; page to your site. Check out a &lt;a href=&quot;https://nownownow.com/&quot;&gt;whole load of them here&lt;/a&gt; and &lt;a href=&quot;https://now.garden/&quot;&gt;on the now garden&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;/uses&lt;/code&gt; page to list what apps and hardware and whatever else you use. &lt;a href=&quot;https://uses.tech/&quot;&gt;uses.tech&lt;/a&gt; has nearly 800 examples.&lt;/li&gt;
&lt;li&gt;If you&#39;re really feeling adventurous you can &lt;a href=&quot;https://rknight.me/adding-webmentions-to-your-site/&quot;&gt;add webmentions&lt;/a&gt; to your site.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&#39;s your website, you can add literally anything you want&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; and no one can stop you.&lt;/p&gt;
&lt;h3&gt;Useful links to get started&lt;/h3&gt;
&lt;p&gt;This is all well and good but if you don&#39;t already have a website it can be daunting to know where to go.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://micro.blog/&quot;&gt;Micro.blog&lt;/a&gt; - $5 a month, has cross-posting to a whole load of places&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.com&quot;&gt;Wordpress.com&lt;/a&gt; - Free&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;weblog.lol via omg.lol&lt;/a&gt; - $20 a year also includes a Mastodon server, pastebin, profile page, now page, and some other cool things&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bearblog.dev/&quot;&gt;Bear&lt;/a&gt; - free&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://neocities.org/&quot;&gt;Neocities&lt;/a&gt; - free&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pika.page&quot;&gt;Pika&lt;/a&gt; - free&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt; if you want to dig into code and run your own thing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reach out to me on Mastodon if you have questions and I&#39;ll do what I can to help get you started.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The real web, the small web, the indie web is amazing. Don&#39;t give Facebook and the rest of these clowns your content. Don&#39;t give them the time or your attention. Get a blog, a website, a Mastodon account, something &lt;em&gt;you control&lt;/em&gt;, and share links to cool things you find. Make a list of your favourite blogs or websites or photos of cats. Write about a pizza you had that was delicious. Share a recipe. Go down a rabbit hole for hours on end adding weird stuff to your site. Just do it somewhere you control because the &lt;em&gt;real&lt;/em&gt; web is fantastic.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Yeah I know &amp;quot;the web&amp;quot; and &amp;quot;the internet&amp;quot; are different things, don&#39;t at me &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I miss StumbleUpon &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I guarantee you&#39;re not the only one interested in this theorectical topic &lt;a href=&quot;#fnref3&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Keep it legal, folks &lt;a href=&quot;#fnref4&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>No not that web. The real web.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Generating and Caching Open Graph Images with Eleventy</title>
    <link href="https://rknight.me/blog/generating-and-caching-open-graph-images-with-eleventy/"/>
    <updated>2023-12-24T10:09:42Z</updated>
    <id>https://rknight.me/blog/generating-and-caching-open-graph-images-with-eleventy/</id>
    <content type="html">&lt;p&gt;I recently added automatically generated open graph images to my site using &lt;a href=&quot;https://github.com/KiwiKilian/eleventy-plugin-og-image&quot;&gt;&lt;code&gt;eleventy-plugin-og-image&lt;/code&gt;&lt;/a&gt;. Here is the open graph image for this post:&lt;/p&gt;
&lt;img style=&quot;border: 1px solid white;&quot; src=&quot;/assets/ogi/bloggenerating-and-caching-open-graph-images-with-eleventy.png&quot; alt=&quot;Generating, and Caching, Open Graph Images with Eleventy&quot; /&gt;
&lt;p&gt;I won&#39;t go over how to use the plugin; the docs on the repo and &lt;a href=&quot;https://lewisdale.dev/post/adding-statically-generated-open-graph-images/&quot;&gt;this blog post&lt;/a&gt; explain that very well. What I didn&#39;t like is that these are generated every time the site builds which, aside from being wildly inefficient, added significant time to my builds.&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://social.lol/@robb/111574217802419330&quot;&gt;posted about this&lt;/a&gt; on the &#39;don and &lt;a href=&quot;https://social.lol/@sophie/111574234339127389&quot;&gt;Sophie replied with how she is doing it&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I run it locally when I write a new post, and commit the results [...] basically the dev server will spit out the OG image&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is exactly what I wanted - generate the images once, and commit them to the repo. To do this I had to modify the plugin config to output the images to my &lt;code&gt;src&lt;/code&gt; folder instead of the output folder:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;eleventyConfig.addPlugin(ogImagePlugin, {&lt;br /&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    outputDir: &#39;src/assets/ogi&#39;,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   satoriOptions: {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will output the image to my &lt;code&gt;assets&lt;/code&gt; directory, which in turn gets copied into my built site. This did cause a new issue though - Eleventy watches for changes in source files and rebuilds the site so every time a new image was made, Eleventy would rebuild again. To solve this, I used &lt;code&gt;watchesIgnore&lt;/code&gt; in my config file:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;watchIgnores&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;src/assets/ogi/**/*&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I only wanted these to be generated in development mode so I added an &lt;code&gt;env&lt;/code&gt; data file to check the mode:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ELEVENTY_RUN_MODE&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;build&#39;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then I updated my base layout so it only uses the &lt;code&gt;ogImage&lt;/code&gt; plugin when in development mode. In production, it uses the full path to the image:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;production &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;meta property&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;og:image&quot;&lt;/span&gt; content&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/assets/ogi/{{ page.url | slugify }}.png&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; ogImage &lt;span class=&quot;token string&quot;&gt;&quot;src/og-image.og.njk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; safe &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; endif &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The final problem I had is the plugin will wipe the output directory on every change. &lt;a href=&quot;https://github.com/KiwiKilian/eleventy-plugin-og-image/pull/74&quot;&gt;This pull request&lt;/a&gt; added that functionality and originally had an option to pass in for it to happen or not, but that option didn&#39;t make it to the final version. Based on the discussion it looked as though this wasn&#39;t something wanted in the plugin, so I made a copy of the plugin in my &lt;code&gt;plugins&lt;/code&gt; directory and removed the line that deleted the files each time:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; eleventyConfig.on(&#39;eleventy.before&#39;, () =&gt; {&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    const options = mergeOptions(directoriesConfig, pluginOptions);&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    fs.rmSync(options.outputDir, { recursive: true, force: true });&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This process does require me to run &lt;code&gt;--serve&lt;/code&gt; at least once each time I added a blog post but there is rarely a time where I wouldn&#39;t do that.&lt;/p&gt;
</content>
    <summary>How I'm caching my open graph images with eleventy-plugin-og-image instead of generating them on every build</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Just 2023 Things</title>
    <link href="https://rknight.me/blog/just-2024-things/"/>
    <updated>2023-12-22T10:11:45Z</updated>
    <id>https://rknight.me/just-2024-things/</id>
    <content type="html">&lt;p&gt;I got married and had a child. No time for anything else. Thank you for reading.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Writing&lt;/h3&gt;
&lt;p&gt;This year I wrote 60 blog posts including this one which is a big jump compared to last year&#39;s 19. My most popular posts&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; for the year are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/please-expose-your-rss/&quot;&gt;Please, Expose your RSS&lt;/a&gt; - this one hit the &lt;a href=&quot;https://news.ycombinator.com/item?id=38595855&quot;&gt;front page of Hacker News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/app-defaults/&quot;&gt;App Defaults&lt;/a&gt; - see the everything else section below for more info on this&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me//adding-webmentions-to-your-site/&quot;&gt;Adding Webmentions to Your Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me//automating-my-now-page/&quot;&gt;Automating My Now Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/using-pagefind-with-eleventy-for-search/&quot;&gt;Using PageFind with Eleventy for Search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Media&lt;/h3&gt;
&lt;h4&gt;Movies&lt;/h4&gt;
&lt;p&gt;Checking my &lt;a href=&quot;https://letterboxd.com/rknightuk&quot;&gt;Letterboxd&lt;/a&gt; I only watched a handful of &lt;em&gt;new-to-me&lt;/em&gt; movies this year. &lt;a href=&quot;https://www.imdb.com/title/tt9114286/&quot;&gt;Black Panther: Wakanda Forever&lt;/a&gt; and &lt;a href=&quot;https://www.imdb.com/title/tt10954600/&quot;&gt;Ant-Man and the Wasp: Quantumania&lt;/a&gt; were equally disappointing in their own special ways. &lt;em&gt;Barbie&lt;/em&gt; was...fine? Maybe the hype set my expectations too high but it was fine. Whatever. It&#39;s a sad state of affairs that &lt;a href=&quot;https://www.imdb.com/title/tt2933474/&quot;&gt;Superfast!&lt;/a&gt; was the best new-to-me movie I watched this year (here my review on &lt;a href=&quot;https://wegot.family/5/&quot;&gt;episode 5 of We Got Family&lt;/a&gt;).&lt;/p&gt;
&lt;h4&gt;TV&lt;/h4&gt;
&lt;p&gt;Just two shows jump out at me as worth recommending this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.imdb.com/title/tt11280740/&quot;&gt;Severance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.imdb.com/title/tt3581920/&quot;&gt;The Last of Us&lt;/a&gt; accompanied with &lt;a href=&quot;https://www.theincomparable.com/tcou/&quot;&gt;The Incomparable&#39;s &lt;em&gt;The Cast of Us&lt;/em&gt; podcast&lt;/a&gt;&lt;br /&gt;
I have yet to watch For All Mankind season 4 and the Scott Pilgrim show.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Music&lt;/h4&gt;
&lt;p&gt;I&#39;ve continued to use &lt;a href=&quot;https://rknight.me/add-to-musicthread-shortcut/&quot;&gt;my MusicThread shortcut&lt;/a&gt; to send new albums and tracks to the relevant playlists:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://musicthread.app/thread/2L6LZz60026Onq3waGuwt7WdJ5x&quot;&gt;2023 Albums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://musicthread.app/thread/2L6IuBPKCCo7fsA8SFyXZLirH5W&quot;&gt;2023 Tracks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://musicthread.app/link/2VIGOGRMFyCta6smxRY0H5jKPQq&quot;&gt;Punk Tactics by Joey Valence &amp;amp; Brae&lt;/a&gt; has easily been my favourite album of the year, with &lt;a href=&quot;https://musicthread.app/link/2X1GTScJIyLzJugjczig4sWFn66&quot;&gt;One More Time by blink-182&lt;/a&gt; a close second. The &lt;a href=&quot;https://musicthread.app/link/2YgZCdX5aTVecEnkxXiVFpnTRaI?share_prompt=1&quot;&gt;Meteora 20th Anniversary Edition&lt;/a&gt; was also in heavy rotation for me this year as well. According to Apple Music my top artists were (I promise this is a 2023 list and not 2005):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Linkin Park&lt;/li&gt;
&lt;li&gt;Simple Plan&lt;/li&gt;
&lt;li&gt;Punk Rock Factory&lt;/li&gt;
&lt;li&gt;Blink 182&lt;/li&gt;
&lt;li&gt;State Champs&lt;/li&gt;
&lt;li&gt;Zebrahead&lt;/li&gt;
&lt;li&gt;Bowling for Soup&lt;/li&gt;
&lt;li&gt;Allister (top 100 listeners!)&lt;/li&gt;
&lt;li&gt;Eminem&lt;/li&gt;
&lt;li&gt;Story of the Year&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Games&lt;/h4&gt;
&lt;p&gt;According to Playstation Wrap-Up, I played four games this year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Last of Us Part 1&lt;/li&gt;
&lt;li&gt;Stray&lt;/li&gt;
&lt;li&gt;Spider-Man 2&lt;/li&gt;
&lt;li&gt;Guardian of the Galaxy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of those I stopped playing Guardians because I found it boring and I&#39;m halfway through Spider-Man and Last of Us. Stray is the only game I&#39;ve finished.&lt;/p&gt;
&lt;h4&gt;Books&lt;/h4&gt;
&lt;p&gt;In &lt;a href=&quot;https://rknight.me/just-2022-things/&quot;&gt;last year&#39;s end of year post&lt;/a&gt; I said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I did start &lt;a href=&quot;https://micro.blog/books/9781728236254&quot;&gt;Men Who Hate Women&lt;/a&gt; and hopefully will finish it soon.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I did not finish it yet. Maybe next year. The only book I read this year was the &lt;a href=&quot;https://johnnydecimal.com/10-19-concepts/14-build-your-system/14.02-the-decimal-workbook/&quot;&gt;Johnny Decimal workbook&lt;/a&gt; which I enjoyed so much I &lt;a href=&quot;https://rknight.me/using-the-johnny-decimal-system/&quot;&gt;wrote a post about it&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Podcasts&lt;/h4&gt;
&lt;p&gt;The only new podcast I added to &lt;a href=&quot;http://localhost:8080/podcasts/roll/&quot;&gt;my subscriptions&lt;/a&gt; is &lt;a href=&quot;https://hemisphericviews.com/&quot;&gt;Hemispheric Views&lt;/a&gt;. I enjoyed it so much I went back and &lt;a href=&quot;http://localhost:8080/three-years-of-hemispheric-views-feedback/&quot;&gt;listened to all 78 episodes&lt;/a&gt; over three months. Hemispheric Views was also how &lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;App Defaults&lt;/a&gt; started, more about that below.&lt;/p&gt;
&lt;h3&gt;Side Projects&lt;/h3&gt;
&lt;h4&gt;January: omg! lol!&lt;/h4&gt;
&lt;p&gt;At the start of the year I switched over to social.lol and using Mastodon rather than micro.blog which led to a few related projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/omglolcli&quot;&gt;omglolcli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://recentfm.rknight.me/&quot;&gt;recentfm.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://omgnow.rknight.me/&quot;&gt;omgnow.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://echo.rknight.me/&quot;&gt;Echo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lantern.rknight.me/&quot;&gt;Lantern&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Echo I am still using heavily and I know that RecentFM and omgnow.js is being used by at least a few people. I have plans to make Echo a more user-friendly project but that&#39;s a way off yet I think.&lt;/p&gt;
&lt;h4&gt;September: The Donation Daddy Cometh&lt;/h4&gt;
&lt;p&gt;This year I was organised enough to setup a sub-campaign for &lt;a href=&quot;https://relay.experience.stjude.org&quot;&gt;Relay&#39;s annual St Jude fundraising campaign&lt;/a&gt; and I (with the help of &lt;a href=&quot;https://neatnik.net&quot;&gt;Adam&lt;/a&gt;) was able to raise $12,590.57. You can &lt;a href=&quot;/st-jude-2023-final-numbers/&quot;&gt;read the blog post here&lt;/a&gt; for more of the juicy details on the campaign itself.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;real&lt;/em&gt; fun (aside from raising lots of money of course) comes from the japes in the Relay discord. It started with &lt;a href=&quot;http://septembed.rknight.me&quot;&gt;Septembed&lt;/a&gt;, then &lt;a href=&quot;https://deskmat.help&quot;&gt;deskmat.help&lt;/a&gt;, then &lt;a href=&quot;https://coinme.dad/dy&quot;&gt;Coin Me, Daddy&lt;/a&gt;, and finally &lt;a href=&quot;https://donationtreats.rknight.me&quot;&gt;Donation Treats&lt;/a&gt;. These were all separate websites for the majority of the campaign but towards the end I merged them into a single project for my own sanity and slapped Zach&#39;s incredible &lt;a href=&quot;https://donationdaddy.rknight.me&quot;&gt;donation daddy logo on it&lt;/a&gt;. I can&#39;t wait for next year, me and Adam have some fun ideas already (it&#39;s basically September anyway).&lt;/p&gt;
&lt;p&gt;We also sent out over 100 sets of stickers to people who donated. I was pretty proud of how well the stickers I designed looked, so much so I made the Ruminate one our proper artwork.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/omg-lol-st-jude-stickers.jpg&quot; alt=&quot;omg.lol × St Jude stickers&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo courtesy of &lt;a href=&quot;https://lmika.org/&quot;&gt;Leon Mika&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Everything Else&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rknightuk.github.io/mac-30-font-svg/&quot;&gt;Mac 30th Anniversary Icons&lt;/a&gt;. I couldn&#39;t have done with without &lt;a href=&quot;https://keiransell.com/&quot;&gt;Keir&lt;/a&gt; and &lt;a href=&quot;https://calvetti.me/&quot;&gt;Josh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://treatday.rknight.me/&quot;&gt;Brian Butterfield Diet Soundboard&lt;/a&gt;. One of the more popular projects. It keeps ending up getting posted on random newsletters, gets a big spike of traffic, then dies down again. I use it all the time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugle.lol/&quot;&gt;Bugle&lt;/a&gt; - My ActivityPub server I&#39;m using for &lt;a href=&quot;https://bugle.lol/@wegotfamily&quot;&gt;We Got Family&lt;/a&gt; and &lt;a href=&quot;https://knightbot.rknight.me&quot;&gt;my bots&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/custom-finder-sidebar-icons&quot;&gt;Custom Finder Sidebar Icons&lt;/a&gt;. A fun but frustrating project I did with Keir&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wegot.family/&quot;&gt;We Got Family Podcast&lt;/a&gt;. We got a bit behind on this but we will finish it. It&#39;s been a lot of fun talking about the Fast and Furious movies.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://podduration.rknight.me/&quot;&gt;Podcast Duration Calculator&lt;/a&gt; and &lt;a href=&quot;https://defocused-vs-the-movies.netlify.app/&quot;&gt;Defocused vs. the Movies&lt;/a&gt;. I don&#39;t even remember why I wanted to know how many hours of audio a podcast was but these two projects were a result of that.&lt;/li&gt;
&lt;li&gt;Secret &lt;a href=&quot;http://Relay.fm&quot;&gt;Relay.fm&lt;/a&gt; project. Can&#39;t say what this is but it involved the Google Sheets API and Eleventy data files.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vlcnr.rknight.me/&quot;&gt;VLCNR&lt;/a&gt;. I had wanted to revive this app for a while and finally found the time to do it.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;App Defaults&lt;/a&gt;. My most popular project this year by far. In the 50 days from launching it there was only three days where I didn&#39;t have to add at least one site to the list. As of today, there are 282 blog posts.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pokedon.rknight.me/&quot;&gt;Pokédon&lt;/a&gt;. My first hackathon in seven years, this time on my own instead of part of &lt;a href=&quot;https://devsdodesign&quot;&gt;my team&lt;/a&gt;. I think I spent more time on the Pokédex design that I did the actual code.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doubleshift.rknight.me&quot;&gt;DoubleShift&lt;/a&gt; and &lt;a href=&quot;https://crossover.rknight.me&quot;&gt;Crossover&lt;/a&gt;. Two projects that scratched an itch for me to know where I&#39;d seen other actors in similar shows. A lot fun data stuff in here.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://postgraph.rknight.me/&quot;&gt;Eleventy Post Graph&lt;/a&gt;. The graph I added on my stats page was pretty popular so I made it into an Eleventy Plugin. This was also somehow the first time I&#39;ve published an npm package. &lt;a href=&quot;https://rknight.me/eleventy-post-graph-plugin/&quot;&gt;Read the blog post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This site. Last month I redesigned the site after seeing &lt;a href=&quot;https://simplebits.shop/products/cartridge&quot;&gt;SimpleBits Cartridge font&lt;/a&gt; and knew I had to use it somewhere. Now I&#39;ve redesigned it to make it more flexible I can start porting over some of the content from &lt;a href=&quot;https://intersect.rknight.me&quot;&gt;the Intersect&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&#39;s been a pretty good year all told. Now if I could find a way to get paid to make stupid web apps all day that&#39;d be great.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I&#39;ve excluded &lt;a href=&quot;https://rknight.me/convert-spotify-facebook-to-email-login/&quot;&gt;these&lt;/a&gt; &lt;a href=&quot;https://rknight.me//create-a-blank-no-header-markdown-table/&quot;&gt;two&lt;/a&gt; posts because although they are really popular they are very boring &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>2023 year in review</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Puff Pastry Sausage Roll Recipe</title>
    <link href="https://rknight.me/blog/puff-pastry-sausage-roll-recipe/"/>
    <updated>2023-12-21T14:18:43Z</updated>
    <id>https://rknight.me/puff-pastry-sausage-roll-recipe/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/sausage-rolls.jpg&quot; alt=&quot;Sausage Rolls&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here is the recipe for very easy to make sausage rolls. You&#39;ll need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;~450g of sausage meat. I prefer to buy sausages and remove the skin as there&#39;s a bigger variety of flavours available without having to add stuff to sausage meat myself&lt;/li&gt;
&lt;li&gt;A sheet of puff pastry. In the UK at least these come in a standard size of 320g (&lt;a href=&quot;https://groceries.asda.com/product/pastry-dough/jus-rol-puff-pastry-ready-rolled-sheet/910000468752&quot;&gt;example&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;An egg&lt;/li&gt;
&lt;li&gt;A baking tray and some greaseproof/baking paper&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Preheat the oven to 180°c. Whisk up an egg in a bowl.&lt;/p&gt;
&lt;p&gt;Lay the puff pastry flat and lay a cylinder of sausage meat about an inch thick across the pastry. Roll the pastry around that and cut it so there&#39;s just enough to cover the meat with a little bit of overlap. Do this until you run out of pastry.&lt;/p&gt;
&lt;p&gt;Grab your baking tray, lay down some greaseproof paper on it, then brush the tray with the eggwash.&lt;/p&gt;
&lt;p&gt;Cut up your long sausage roll into inch-wide smaller sausage rolls and pop them on the baking tray, seam down. Brush them with egg and pop them in the oven for 20-25 minutes until they&#39;re golden brown all over.&lt;/p&gt;
&lt;p&gt;Boom. Sausage rolls for days.&lt;/p&gt;
</content>
    <summary>A very simple recipe for making delicious sausage rolls</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Eleventy Post Graph Plugin</title>
    <link href="https://rknight.me/blog/eleventy-post-graph-plugin/"/>
    <updated>2023-12-19T15:10:02Z</updated>
    <id>https://rknight.me/eleventy-post-graph-plugin/</id>
    <content type="html">&lt;p&gt;Last week I &lt;a href=&quot;https://social.lol/@robb/111586346073402453&quot;&gt;tooted about my Github-style post graph&lt;/a&gt; on &lt;a href=&quot;/blog/stats&quot;&gt;my stats page&lt;/a&gt; and people seemed to like it. &lt;a href=&quot;https://jamesdoc.com/blog/&quot;&gt;James&lt;/a&gt; added one to his blog pages. &lt;a href=&quot;https://social.lol/@pimoore/111586392676224177&quot;&gt;Pete swore at me&lt;/a&gt;. I knew I had to make it into an Eleventy plugin so other people could us it easily.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/eleventy-plugin-post-graph-screenshot.png&quot; alt=&quot;Screenshot of eleventy-plugin-post-graph&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you just want to jump straight into using it, &lt;a href=&quot;https://postgraph.rknight.me&quot;&gt;check out the docs here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To create the data, which days have posts, and the grid itself I&#39;m using &lt;code&gt;moment.js&lt;/code&gt; to manipulate post dates&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; and generate an object that looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; postMap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;years&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;days&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;365&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;counts&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&#39;2023-1&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&#39;2023-5&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// and so on&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;days&lt;/code&gt; is the number of days in the year and &lt;code&gt;offset&lt;/code&gt; is used to start the grid on the correct day; if the 1st of January is a Sunday, the offset is 6. The keys in &lt;code&gt;counts&lt;/code&gt; are the year plus the &lt;em&gt;day of the year&lt;/em&gt;. This makes it easy to check if a day should be highlighted or not:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;${prefix}__squares&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// generate the offset of the start of year&lt;/span&gt;&lt;br /&gt;    Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; postMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;years&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;year&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;offset &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;div class=&quot;epg__box epg__box--empty&quot;&gt;&amp;lt;/div&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// make a box for every day of the year&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// if at least one post exists, highlight that box&lt;/span&gt;&lt;br /&gt;    Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; postMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;years&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;year&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;days &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; dateIndexKey &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;year&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; postCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; postMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;counts&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;dateIndexKey&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;div class=&quot;epg__box &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt; postCount &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;epg__hasPost&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&gt;&amp;lt;/div&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One edge case I hadn&#39;t considered until I was writing the docs was what if someone wanted two instances of the graph in different colors - the css injected into the page would apply to both. The solution I came up with was to add a &lt;code&gt;prefix&lt;/code&gt; option wherein the classes, instead of being &lt;code&gt;epg__{something}&lt;/code&gt;, will become &lt;code&gt;mycoolprefix-epg__{something}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I added a bunch of other options to handle all the different use cases I could think of but I&#39;m sure they&#39;ll be more. Get started with &lt;a href=&quot;https://postgraph.rknight.me/&quot;&gt;the docs&lt;/a&gt; and if you use this on your site let me know, I&#39;d love to see it.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;I am aware that &lt;a href=&quot;https://day.js.org&quot;&gt;Day.js&lt;/a&gt; is better but I just...forgot about it until right now &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>Generate Github-style post distribution graph for your blog posts in Eleventy</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Meta Doesn&#39;t Need ActivityPub to Slurp Up Your Data</title>
    <link href="https://rknight.me/blog/meta-doesnt-need-activitypub-to-slurp-up-your-data/"/>
    <updated>2023-12-15T10:30:49Z</updated>
    <id>https://rknight.me/meta-doesnt-need-activitypub-to-slurp-up-your-data/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://www.theverge.com/2023/12/13/24000120/threads-meta-activitypub-test-mastodon&quot;&gt;Threads started to test ActivityPub integration&lt;/a&gt; this week and the fediverse is losing it&#39;s collective mind going into overdrive to block them in any way possible so they can&#39;t grab all your data. Here&#39;s the fun part: they can already do that and they definitely don&#39;t need ActivityPub to do that.&lt;/p&gt;
&lt;p&gt;Take my profile for example: &lt;a href=&quot;https://social.lol/@robb&quot;&gt;https://social.lol/@robb&lt;/a&gt;. It&#39;s all right there for downloading, scraping, or scribbling down in a &amp;quot;&lt;em&gt;robb is very clever and handsome&lt;/em&gt;&amp;quot; notebook. The &lt;a href=&quot;https://social.lol/public/local&quot;&gt;local timeline for social.lol&lt;/a&gt; is the same. Ready to be gobbled up into whatever data center Meta want to put it in. This doesn&#39;t even take into account that &lt;em&gt;Mastodon has an API that anyone can use&lt;/em&gt;. Hell, they could follow the local timeline on Mastodon.social and probably get 90% of the data they want anyway, assuming they want any of it to begin with. Or create an account on a few hundred instances and get the data that way. But they won&#39;t because that&#39;s not why they&#39;re doing this.&lt;/p&gt;
&lt;p&gt;They are doing this because they have to. The EU is breathing down all the big tech companies neck&#39;s to be more open and interoperable.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; They only launched in the EU yesterday and I&#39;d bet my left bollock it took so long because they were doing sneaky shit with tracking that the EU would have fined them for immediately. The EU didn&#39;t make Threads illegal like certain tech pundits claimed, Meta were just doing illegal things. Just a little crime, as a treat.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fedipact.veganism.social/&quot;&gt;Some instances&lt;/a&gt; have already blocked Threads completely meaning their users have no way of intereacting with accounts on Threads. Purely on the basis that it&#39;s Meta with no evidence that they&#39;re doing anything nefarious or dangerous. Congratulations, you&#39;ve made your instance worse for your users. By all means, wait and see if federating with Threads &lt;em&gt;becomes&lt;/em&gt; a problem, but doing it just because &amp;quot;meta bad&amp;quot; is ridiculous.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mastodon.blaede.family/@cassidy/111576987371347535&quot;&gt;Cassidy James&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;...defederating from Threads is like an upstart email service blocking their users from being able to email Gmail users because they don’t like Google. That might seem fine on principle, but in reality it just siloes people from their friends — and makes joining the other service more attractive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What&#39;s to be gained from stopping your instance&#39;s users following their friends and family who have chosen to use Threads, other than making them switch to another instance? As Cassidy &lt;a href=&quot;https://mastodon.blaede.family/@cassidy/111580679497344885&quot;&gt;also points out&lt;/a&gt; an individual user can block an instance themselves which is the great thing about Mastodon: users have a choice to block or not block whatever they want.&lt;/p&gt;
&lt;p&gt;I&#39;m also aware that users also have a choice to move instances and to some extent I agree that if you don&#39;t like how your instance is run, you should move to another one.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; But how about instead everyone chills out for a minute, maybe give Meta a chance to &lt;em&gt;actual federate real accounts people want to follow&lt;/em&gt;, and &lt;em&gt;then&lt;/em&gt; decide if they should be blocked or not. How about we don&#39;t force hundreds of people to new instances (or worse, Threads) just so they can see the latest minion meme their mum posted.&lt;/p&gt;
&lt;p&gt;Yes, it&#39;s Meta and they suck and I hate them. But they don&#39;t need ActivityPub to grab your data and blocking them for no good reason is just making the Fediverse, and the open web, worse for everyone.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Stupid unelected elite in Brussels trying to make life better for it&#39;s citizens, how dare they. Brexit means Brexit. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&amp;quot;Tough shit, move instances&amp;quot; is something I have said on a few occasions when discussing disagreeing with instance admin decisions. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>Thoughts on Meta adding ActivityPub to Threads</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Subscriptions</title>
    <link href="https://rknight.me/blog/subscriptions/"/>
    <updated>2023-12-13T17:35:24Z</updated>
    <id>https://rknight.me/subscriptions/</id>
    <content type="html">&lt;p&gt;Inspired by &lt;a href=&quot;https://mb.esamecar.net/2023/12/13/state-of-app.html&quot;&gt;Marco&lt;/a&gt; and &lt;a href=&quot;https://kevquirk.com/on-subscriptions&quot;&gt;Kev&lt;/a&gt;, here is the current state of my subscriptions. Any prices that were in dollars I&#39;ve converted to GBP. Anything I pay for yearly I&#39;ve divided by 12 and marked them as such.&lt;/p&gt;
&lt;h3&gt;Miscellanea&lt;/h3&gt;
&lt;p&gt;I pay for &lt;a href=&quot;https://www.apple.com/uk/apple-one/&quot;&gt;Apple One Premier&lt;/a&gt; at £36.95 per month which includes Apple TV+, iCloud Storage, and Apple Music for me and my wife but I&#39;ll include it in the streaming section for the sake of clarity.&lt;/p&gt;
&lt;p&gt;I have a 1Password Family account but I get this for free through my job.&lt;/p&gt;
&lt;h3&gt;Streaming&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Netflix (£7.99 / month). We cheap out on this because it&#39;s mostly for my wife to watch old crime documentaries and the quality doesn&#39;t really matter&lt;/li&gt;
&lt;li&gt;Disney+ (£10.99 / month). We don&#39;t actually pay for this, instead we use our Tesco Clubcard vouchers every three months instead.&lt;/li&gt;
&lt;li&gt;Amazon Prime (£7.99 / month (paid yearly)). We don&#39;t so much pay for this as we just get it included because we want quick delivery.&lt;/li&gt;
&lt;li&gt;Apple TV+, Apple Music (£36.95 / month).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total:&lt;/strong&gt; £63.92 / month&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Memberships&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://getconnectedpro.co&quot;&gt;Connected Pro/Relay FM&lt;/a&gt; (£4 / month). Ad-free episodes with extra content for connected, bonus episodes and access to the Relay Discord.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://oneprimeplus.com/&quot;&gt;Hemispheric Views One Prime Plus&lt;/a&gt; (£4 / month). Bonus episodes, a newsletter, access to a members-only Discord channel, plus some dandy stickers. I &lt;em&gt;just&lt;/em&gt; bumped this from $2 to $5 because I&#39;m not convinced much of my $2 is actually reaching them once you account for fees and whatnot.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt; (£4 / month). I build so many of my sites with Eleventy, it&#39;s a no-brainer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total:&lt;/strong&gt; £12 / month&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Apps and Services&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;omg.lol&lt;/a&gt; (£1.33 / month (paid annually)). My main use is the &lt;a href=&quot;https://social.lol&quot;&gt;Mastodon instance&lt;/a&gt; but it has loads of stuff. Read &lt;a href=&quot;https://blakewatson.com/journal/omg-lol-an-oasis-on-the-internet/&quot;&gt;Blake&#39;s post&lt;/a&gt; for a better overview than I could ever write.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/?refcode=8e1d8283bd20&quot;&gt;Digital Ocean&lt;/a&gt; (£12 / month). Hosting for this website and all my &lt;a href=&quot;https://rknight.me/projects&quot;&gt;side projects&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://usefathom.com/ref/IXCLSF&quot;&gt;Fathom Analytics&lt;/a&gt; (£11 / month). Analytics I use for my sites. Worth noting here I get ~$7/£5 back each month thanks to referrals so the actual price paid here is ~£6.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bunny.net/?ref=b2i4y24apu&quot;&gt;BunnyCDN&lt;/a&gt; (£1 / month). Currently only using this to host the files for &lt;a href=&quot;https://wegot.family/&quot;&gt;We Got Family&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tapbots.com/ivory/&quot;&gt;Ivory&lt;/a&gt; (£2 / month (paid yearly)). The best Mastodon client on the Mac and iOS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total:&lt;/strong&gt; £25.33 / month&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Grand Total&lt;/h3&gt;
&lt;p&gt;£101.25 isn&#39;t too bad considering everything I&#39;m getting for that. Not sure what conclusion to draw from this, nothing here I really need to cut. Maybe if it goes much higher I&#39;ll think about it some more.&lt;/p&gt;
</content>
    <summary>The current state of what services I'm subscribed to</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Nine</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-nine/"/>
    <updated>2023-12-09T13:10:04Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-nine/</id>
    <content type="html">&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;Given this an input like this, find the next number in the sequence. See the &lt;a href=&quot;https://adventofcode.com/2023/day/9&quot;&gt;advent of code instructions&lt;/a&gt; for more details, but we need to go from this:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;0 3 6 9 12 15&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To the following, to get the final value for that row of &lt;code&gt;18&lt;/code&gt;. To do this we take the first two numbers and get the difference between them. That becomes our first number on the second row. Continue this until the final row is all zeros. Then take the last digit all of the rows and sum them to get &lt;code&gt;18&lt;/code&gt; (0 + 3 + 15).&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;0   3   6   9  12  15 -&gt; 18&lt;br /&gt;  3   3   3   3   3 -&gt; 3&lt;br /&gt;    0   0   0   0 -&gt; 0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I interated over each line, used a while loop to check if the sum of the new row is more than zero, and continue adding rows until the new row&#39;s sum is zero (this assumption becomes important in a minute). Then grab all the final numbers and sum them for our row value, then sum all the lines to get the answer.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$currentIndex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$finalNumbers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_key_last&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$finalNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$currentRow&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$currentIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$new&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$currentRow&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$currentRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$finalNumbers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_key_last&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$currentRow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$currentIndex&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$finalValue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$finalValue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_key_last&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$finalValue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;Total: &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This worked perfectly on the sample input but like other days the real input had a gotcha. As I noted above, I made the assumption that if the sum of a row was more than zero we should carry on but this doesn&#39;t account for negative numbers. What I &lt;em&gt;should&lt;/em&gt; have done was check if the sum was not &lt;em&gt;exactly zero&lt;/em&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; while (array_sum($finalNumbers) !== 0) {&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; while (array_sum($finalNumbers) &gt; 0) {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That was part one done.&lt;/p&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;Instead of calculating the &lt;em&gt;next&lt;/em&gt; number we need to do the &lt;em&gt;previous&lt;/em&gt; number from each sequence. All of my previous code for getting all the rows is the same, I just need to update my total calculator to generate the previous number for each row and get the previous number for the original sequence:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $finalValue = 0;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; foreach ($allNumbers as $numbers) {&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    $finalValue += $numbers[array_key_last($numbers)];&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; }&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $total += $finalValue;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$next&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$allNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// skip the first row it&#39;s always zeros&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$next&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was a nice one. Nothing too hard to understand from the instructions and totally doable without knowing a magic maths solution.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>My solution for "Mirage Maintenance"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Eight</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-eight/"/>
    <updated>2023-12-08T15:05:58Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-eight/</id>
    <content type="html">&lt;p&gt;We&#39;ve navigating a network today for...reasons.&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;The sample input looks like so:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RL&lt;br /&gt;&lt;br /&gt;AAA = (BBB, CCC)&lt;br /&gt;BBB = (DDD, EEE)&lt;br /&gt;CCC = (ZZZ, GGG)&lt;br /&gt;DDD = (DDD, DDD)&lt;br /&gt;EEE = (EEE, EEE)&lt;br /&gt;GGG = (GGG, GGG)&lt;br /&gt;ZZZ = (ZZZ, ZZZ)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first line is a list of instructions (left or right) and the rest is the nodes with their left and right defined. So if we go right from &lt;code&gt;AAA&lt;/code&gt;, we move to &lt;code&gt;CCC&lt;/code&gt;, then left from there takes us to &lt;code&gt;ZZZ&lt;/code&gt;. The puzzle is to count how many steps it takes to get to &lt;code&gt;ZZZ&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I did a bunch of string replacement and exploding to get the output in a format I wanted:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$instructions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;unset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$elements&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; = &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$elementKey&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$L&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$R&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;, &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;(&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$elements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$elementKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;L&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;R&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    &#39;AAA&#39; =&gt; [ &#39;L&#39; =&gt; &#39;BBB&#39;, &#39;R&#39; =&gt; &#39;CCC&#39; ],&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    &#39;BBB&#39; =&gt; [ &#39;L&#39; =&gt; &#39;DDD&#39;, &#39;R&#39; =&gt; &#39;EEE&#39; ],&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One other part of this is that you may not get to &lt;code&gt;ZZZ&lt;/code&gt; with the set of instructions. So if you hit the end, go back to the start of the instructions. I set the starting values and counters then while &lt;code&gt;found&lt;/code&gt; is false, I incremenent the instruction index until we hit &lt;code&gt;ZZZ&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_key_first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$elements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$found&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$found&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// if we&#39;re at the end of the instructions, go back to the start&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$instruction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$instructions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$elements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instruction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;ZZZ&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$found&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;It takes &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; steps to reach ZZZ&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I ran it on the real input and I got stuck in an infinite loop. Initially I didn&#39;t read the instructions properly so I was starting at whatever the first node was; in the samples, this is always &lt;code&gt;AAA&lt;/code&gt; but in the real input, it &lt;em&gt;isn&#39;t&lt;/em&gt;. I stepped back and re-read what I was supposed to be doing and fixed this:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $element = array_key_first($elements);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $element = &#39;AAA&#39;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Re-ran it and it worked perfectly.&lt;/p&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;For part two there some story about a ghost or whatever, but the crux of it is we need to follow multiple paths starting at all node that end with an &lt;code&gt;A&lt;/code&gt;. We&#39;re only done when all the nodes for all paths end in a &lt;code&gt;Z&lt;/code&gt;. I updated my formatting code to account for this:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $startingElements = [];&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;$elements = [];&lt;br /&gt;foreach ($input as $value) {&lt;br /&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   $data = explode(&#39; = &#39;, $value);&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   $elementKey = $data[0];&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   [$L, $R] = explode(&#39;, &#39;, str_replace(&#39;)&#39;, &#39;&#39;, str_replace(&#39;(&#39;, &#39;&#39;, $data[1])));&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   $elements[$elementKey] = compact(&#39;L&#39;, &#39;R&#39;);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    if (str_ends_with($elementKey, &#39;A&#39;)){&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;        $startingElements[] = $elementKey;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the new sample input gave me two starting points (the real input has five):&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$test&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;LR&lt;br /&gt;&lt;br /&gt;11A = (11B, XXX)&lt;br /&gt;11B = (XXX, 11Z)&lt;br /&gt;11Z = (11B, XXX)&lt;br /&gt;22A = (22B, XXX)&lt;br /&gt;22B = (22C, 22C)&lt;br /&gt;22C = (22Z, 22Z)&lt;br /&gt;22Z = (22B, 22B)&lt;br /&gt;XXX = (XXX, XXX)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;11A&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;22A&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next I updated my instruction loop to go through each starting point, get the next element for all of them, then check if they all the found elements end with a &lt;code&gt;Z&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$found&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$foundElements&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$instruction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$instructions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$check&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$elementRange&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$er&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$el&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$nextElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$startingElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$er&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$nextElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$er&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$foundElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$elements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$el&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instruction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$allEndWithZ&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$foundElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$fe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_ends_with&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$fe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Z&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$elementCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$allEndWithZ&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$found&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$nextElements&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$foundElements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$instructionIndex&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I ran it on the sample, no problem. Ran it on the real input and it just kept going. For a long time. I ran it for 45 minutes and it was still going. I spoke to &lt;a href=&quot;https://zoeaubert.me&quot;&gt;Zoe&lt;/a&gt;, who had already finished part two, and the correct answer is 14 digits. Based on her maths, this method would take somewhere in the region of 500 hours. I knew there had to be some kind of number...things I could do to work out the answer but it was beyond me at this point.&lt;/p&gt;
&lt;h3&gt;Part Two Redux&lt;/h3&gt;
&lt;p&gt;After &lt;a href=&quot;https://social.lol/@robb/111545115167242100&quot;&gt;making a joke&lt;/a&gt; about wanting a supercomputer on Mastodon, &lt;a href=&quot;https://fosstodon.org/@chrishannah/111545160939769663&quot;&gt;Chris asked&lt;/a&gt; if I wanted a clue he&#39;d seen on the subreddit. I had no idea how to solve this so yes, yes I did. The clue:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lowest Common Multiple&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Of course&lt;/em&gt; the solution was a maths concept I&#39;d heard of but never had a need to use (or I did and I just wasn&#39;t listening at school). &amp;quot;&lt;em&gt;The smallest positive integer that is divisible by both a and b&lt;/em&gt;&amp;quot;. As always, PHP has a function for this: &lt;a href=&quot;https://www.php.net/manual/en/function.gmp-lcm.php&quot;&gt;&lt;code&gt;git_lcm&lt;/code&gt;&lt;/a&gt; but this only works for two numbers. I made a new file (&lt;code&gt;2v2.php&lt;/code&gt;), extracted my path-to-Z logic into a function, collected the steps for each path, and calculated the lowest common multiple.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$allSteps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$startingElements&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;stepsToZ&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$instructions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$elements&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$element&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$allSteps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gmp_init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// numbers passed to `gmp_lcm` need to be converted to GMP&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$allSteps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$allSteps&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$step&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gmp_init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gmp_lcm&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$step&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m still not clear on &lt;em&gt;why&lt;/em&gt; this gets the answer beyond &lt;em&gt;maths&lt;/em&gt; but whatever, it&#39;s done. Onwards to day nine.&lt;/p&gt;
&lt;p&gt;Update: Zoe has a &lt;a href=&quot;https://zoeaubert.me/blog/advent-of-code-2023-day-08/&quot;&gt;good explanation of why this is the answer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/08&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>My solution for "Haunted Wasteland"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Seven</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-seven/"/>
    <updated>2023-12-07T15:45:19Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-seven/</id>
    <content type="html">&lt;p&gt;Time to play some matches of legally-distinct-from-poker-and-easy-to-play-on-a-camel&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; card game.&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;Each hand has five cards and a score:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;32T3K &lt;span class=&quot;token number&quot;&gt;765&lt;/span&gt;&lt;br /&gt;T55J5 &lt;span class=&quot;token number&quot;&gt;684&lt;/span&gt;&lt;br /&gt;KK677 &lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;&lt;br /&gt;KTJJT &lt;span class=&quot;token number&quot;&gt;220&lt;/span&gt;&lt;br /&gt;QQQJA &lt;span class=&quot;token number&quot;&gt;483&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each hand outranks others based on how many cards of each type it has, starting at five of a kind and ending with high card. Here&#39;s the array I was using to test out my hand rank calculator:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$scores&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;AAAAA&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// five of a kind / rank 7&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;AA8AA&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// four of a kind / rank 6&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;23332&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// full house / rank 5&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;TTT98&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// three of a kind / rank 4&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;23432&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// two pair / rank 3&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;A23A4&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// one pair / rank 2&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;23456&#39;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// high card / rank 1&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All the hands need to be ordered by their rank and in the result of a tie, compare the hands&#39;s first value and if those are the same the second value, and so on. Some values are letters rather than numbers, and ace is high:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$highValues&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;A&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;K&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Q&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;J&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;T&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once they&#39;ve all been ranked, multiply that rank by the score and add them together to get the answer. The lowest rank is 1 and upwards to however many hands we have.&lt;/p&gt;
&lt;p&gt;Like &lt;a href=&quot;https://rknight.me/blog/tags/adventofcode/&quot;&gt;previous days&lt;/a&gt; PHP has some handy functions to make this easier. &lt;a href=&quot;https://www.php.net/manual/en/function.count-chars.php&quot;&gt;&lt;code&gt;count_chars&lt;/code&gt;&lt;/a&gt; &amp;quot;counts the number of occurrences of every byte-value in a string&amp;quot;. &lt;a href=&quot;https://www.php.net/manual/en/function.chr.php&quot;&gt;&lt;code&gt;chr&lt;/code&gt;&lt;/a&gt; then converts that back to the number or letter:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count_chars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;12344&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// output&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token number&quot;&gt;49&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token number&quot;&gt;51&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token number&quot;&gt;52&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;52&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once I had my counts for each hands, I make this &lt;code&gt;calculateHandRank&lt;/code&gt; function to return a rank between one and seven depending on the hand. Based on how many elements the array has (and the product in some cases) I can work out the rank easily. &lt;a href=&quot;https://lewisdale.dev/post/advent-of-code-2023-day-seven/&quot;&gt;Lewis has a more elegant solution&lt;/a&gt; thay works when the counts are ordered but the result is the ultimately the same:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;calculateHandRank&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_product&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_product&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Part of ranking the hands is the tie-breaker I mentioned above, based on each card compared to the other hand. So if we had two hands that were both five of a kind, the first one would win because A (ace) is higher than Q (queen):&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;AAAAA&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token string&quot;&gt;&#39;QQQQQ&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here it us all together to get the answer for part one:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// extract the hands and scores, caclulate the hand types&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$formatted&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count_chars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$handType&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateHandRank&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;cards&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;score&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;handType&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// sort the hands by type, compare the card values in the event of a tie break&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;usort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$formatted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$highValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;handType&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;handType&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;cards&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$aCard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$aCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$highValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$aCard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$aCard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$bCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;cards&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$bCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$highValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;cards&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;cards&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$aCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$bCard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$aCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$bCard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;handType&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;handType&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// calculate the overall score &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$formatted&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;score&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;Part two introduced a fun twist. &lt;code&gt;J&lt;/code&gt; is now a joker instead of the jack/11. In the event of a tie break, the joker is worth 1 but if it exists in a hand the it goes towards whichever grouping would increase the hands type. For example, this three of a kind hand becomes four of a kind:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$before&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;AAA5J&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// three of a kind&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$after&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;AAA5A&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// four of a kind&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I updated my formatting code to account for, using &lt;code&gt;count_chars&lt;/code&gt; to find which value the joker should become:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$formatted&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$highValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$score&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count_chars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strpos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;J&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// get the highest grouping character&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$highest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$character&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;J&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$fChar&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$highValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$highest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token comment&quot;&gt;// compare the numbers/cards instead of the count&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$fChar&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$character&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$highest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$character&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$fChar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$highest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$highest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$character&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$fChar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$newCards&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;J&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count_chars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$newCards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cards&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$handType&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateHandRank&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$counts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;compact&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;cards&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;score&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;handType&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, I swapped the &lt;code&gt;J&lt;/code&gt; value for 1:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;$highValues = [&lt;br /&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &#39;J&#39; =&gt; 11,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &#39;J&#39; =&gt; 1,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;];&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I ran the code and got a warning:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;chr(): Passing null to parameter #1 ($codepoint) of type int is deprecated&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One of the edge cases (maybe the only one?) was a hand that was five of a kind of all &lt;code&gt;J&lt;/code&gt; cards. I hadn&#39;t accounted for this in my new code for locating the joker replacement; I was skipping every card that was a &lt;code&gt;J&lt;/code&gt; so it never the replacement index would be &lt;code&gt;null&lt;/code&gt;. One more quick change and I had part two finished.&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $replace = $index ? chr($index) : &#39;A&#39;;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $newCards = str_replace(&#39;J&#39;, $chr($index), $cards);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $newCards = str_replace(&#39;J&#39;, $replace, $cards);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This was a nice one today. Easy to understand but complicated enough to be a challenge.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/07&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Told you the story was bonkers &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>My solution for "Camel Cards"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Smart Speed Broke My Brain</title>
    <link href="https://rknight.me/blog/smart-speed-broke-my-brain/"/>
    <updated>2023-12-06T22:30:39Z</updated>
    <id>https://rknight.me/smart-speed-broke-my-brain/</id>
    <content type="html">&lt;p&gt;According to &lt;a href=&quot;https://overcast.fm/&quot;&gt;Overcast&lt;/a&gt;&#39;s stats I&#39;ve saved 424 hours with smart speed. Smart speed, or &amp;quot;trim silence&amp;quot; as other apps call it, is a feature that will remove silences from podcasts and at launch was Overcast’s primary selling point. After the best part of a decade I was convinced &lt;a href=&quot;https://gkeenan.co/avgb/hot-take-its-okay-if-we-dont-consume-all-of-the-worlds-information-before-we-die&quot;&gt;by Keenan&lt;/a&gt; (if you can, listen to the audio version of the post, it&#39;s wonderful) to turn it off and I’m so glad I did.&lt;/p&gt;
&lt;p&gt;It’s a common joke in the &lt;a href=&quot;https://www.relay.fm/membership&quot;&gt;Relay FM Discord&lt;/a&gt; about how those of us who use smart speed (or just the speed controls) think the hosts sound drunk or like they’re slurring when we hear the “normal” version of podcasts; we’re so used to listening to them sped up with no gaps between each side of the conversation like some kind of Aaron Sorkin movie.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How do you distinguish yourself in a population of people who all got 1600 on their SAT’s?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I didn’t know they take SAT’s in China.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;They don’t. I wasn’t talking about China anymore, I was talking about me.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I haven’t listened to a show at standard speed for years. After I turned off smart speed and listened to a show I realised how calm I felt compared to usual. It was relaxing. I had time to process what was being said without also trying to hear the next part of the conversation. I realised for the past decade I’ve been on high alert just to listen to a podcast, concentrating really hard to consume all the information. I was &lt;em&gt;stressed&lt;/em&gt; from something that’s supposed to be enjoyable. I was accustomed to &lt;em&gt;readying myself&lt;/em&gt; to listen to a show. Smart speed had broken my brain.&lt;/p&gt;
&lt;p&gt;424 hours &amp;quot;saved&amp;quot; according to Overcast. Saved what though? 424 more hours to &lt;em&gt;consume content&lt;/em&gt;. Lovely.&lt;/p&gt;
&lt;p&gt;Back to Keenan:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I truly believe that Trim Silence is an abomination that should be fully eradicated from existence, as it not only spits in the face of the people who take the time and effort to produce their shows, but also, more broadly, encourages a way of interfacing with art that can only be described as gluttonous&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I don&#39;t feel &lt;em&gt;that&lt;/em&gt; strongly about it but I do feel stupid for doing this to myself for so long. I don’t think there’s some big conclusion to draw here but maybe, if you speed up your podcasts all the time&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;, maybe try it without for a show or two to see if you like it.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Hi Cory 👋 &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>I turned off smart speed for the first time in a decade</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Six</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-six/"/>
    <updated>2023-12-06T11:07:22Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-six/</id>
    <content type="html">&lt;p&gt;It&#39;s boat racing time. For each millisecond you hold the boat down, it&#39;s speed will increase by one millimeter per second. Just like the bus in Speed, the boat never slows down.&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;The input format:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Time:      &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;   &lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;br /&gt;Distance:  &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;40&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each column is a race which contains the race time and a distance the boat needs to travel to win. So in race one, the boat can travel the required distance (9) by holding down the boat for two, three, four, and five milliseconds. Here is some mathematics:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$distance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$testSeconds&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$newDistance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$testSeconds&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$canWin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$newDistance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// $canWin = true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For each of the races I generated a range of numbers to test based on the time, then checked if those could win based on the distance for that race.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$extract&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$extract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$extract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$wins&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$race&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$distance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$race&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$newDistance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$r&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$canWin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$newDistance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$canWin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$wins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Total is &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_product&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$wins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Got the correct total, part one done. Easy peasy.&lt;/p&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;Apprently the kerning on the peice of paper the input was written on was not good and it&#39;s actually just one race and not multiple.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; So now we have one large race:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$time = 71530;
$distance = 940200;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I switched out my extractor to remove all the spaces and give me just two numbers (I put them in an array so I could avoid changing any of the other code):&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$extract&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$extract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$extract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like &lt;a href=&quot;https://rknight.me/advent-of-code-2023-day-five/&quot;&gt;yesterday&lt;/a&gt; when I also used &lt;code&gt;range&lt;/code&gt; on some large numbers, I ran out of memory. I did throw memory at it and it worked but I knew an easy fix for this one so I changed the &lt;code&gt;range&lt;/code&gt; logic to a &lt;code&gt;while&lt;/code&gt; loop.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$times&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$race&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$distance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distances&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$race&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$newDistance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$time&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$canWin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$newDistance&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$distance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$canWin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$wins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Total is &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_product&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$wins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that was part two. I don&#39;t know how efficient &lt;code&gt;array_product&lt;/code&gt; is and I could have just calculated the total as I went along instead of adding to an array instead.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/06&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The &amp;quot;story&amp;quot; part of advent of code is really something. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>My solution for "Wait For It"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Five</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-five/"/>
    <updated>2023-12-05T11:40:26Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-five/</id>
    <content type="html">&lt;p&gt;The description for this puzzle was confusing. Like, &lt;em&gt;really&lt;/em&gt; confusing. I had to read it at least five times before I even understood the question.&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;For this puzzle the sample input was as follows:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;seeds: 79 14 55 13&lt;br /&gt;&lt;br /&gt;seed-to-soil map:&lt;br /&gt;50 98 2&lt;br /&gt;52 50 48&lt;br /&gt;&lt;br /&gt;soil-to-fertilizer map:&lt;br /&gt;0 15 37&lt;br /&gt;37 52 2&lt;br /&gt;39 0 15&lt;br /&gt;&lt;br /&gt;fertilizer-to-water map:&lt;br /&gt;49 53 8&lt;br /&gt;0 11 42&lt;br /&gt;42 0 7&lt;br /&gt;57 7 4&lt;br /&gt;&lt;br /&gt;water-to-light map:&lt;br /&gt;88 18 7&lt;br /&gt;18 25 70&lt;br /&gt;&lt;br /&gt;light-to-temperature map:&lt;br /&gt;45 77 23&lt;br /&gt;81 45 19&lt;br /&gt;68 64 13&lt;br /&gt;&lt;br /&gt;temperature-to-humidity map:&lt;br /&gt;0 69 1&lt;br /&gt;1 0 69&lt;br /&gt;&lt;br /&gt;humidity-to-location map:&lt;br /&gt;60 56 37&lt;br /&gt;56 93 4&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each line of a map is the destination start, the source start, and the range length. For example if we take the first line of the &lt;code&gt;seed-to-soil map&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;50 98 2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destinationStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sourceStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rangeLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$sourceRange&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$sourceStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$sourceStart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rangeLength&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$destinationRange&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$destinationStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$destinationStart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rangeLength&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$mapped&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sourceRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$destinationRange&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$mapped&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token number&quot;&gt;98&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;51&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This needs to be done for every map in the input. Then take the seed number for the first map, get the value (or the previous value if it&#39;s not in the range), and so on to the last location value. So in the above example if the seed number is &lt;code&gt;98&lt;/code&gt; the value is &lt;code&gt;50&lt;/code&gt;. Then take &lt;code&gt;50&lt;/code&gt; and see if that exists in the &lt;code&gt;soil-to-fertilizer map&lt;/code&gt;. If this makes no sense, have a look at the &lt;a href=&quot;https://adventofcode.com/2023/day/5&quot;&gt;advent of code page for today&#39;s puzzle&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Below is my full &amp;quot;solution&amp;quot;. I&#39;m looping through each line of each map, generating the ranges based on the numbers, and adding it to a &lt;code&gt;mapData&lt;/code&gt; array. Notice I&#39;m using &lt;code&gt;array_combine&lt;/code&gt; to use the source values as the keys and the destination values as the new values. &lt;code&gt;array_replace&lt;/code&gt; preserves keys unlike &lt;code&gt;array_merge&lt;/code&gt; which resets keys, which in this case are important.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$rawData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$seeds&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;seeds: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rawData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;unset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$rawData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$mapData&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$rawData&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$mapName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; map:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;unset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$mapData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destinationStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sourceStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rangeLength&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// generate the ranges for the source and destination&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$mapData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_combine&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sourceStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sourceStart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rangeLength&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$destinationStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$destinationStart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$rangeLength&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$locations&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$seeds&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$seed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// keep track of the current value, starting with the seed&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$seed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapData&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$mapName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// if there isn&#39;t a value set, fallback to the current&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$locations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Lowest location number is &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$locations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This worked for the sample input which was nice given how long I spent trying to understand the puzzle to start with. Then I ran it on the real input and got this out of memory error:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Fatal error: Allowed memory size of &lt;span class=&quot;token number&quot;&gt;536870912&lt;/span&gt; bytes exhausted&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hadn&#39;t actually looked at the real input at this point. The real input has &lt;em&gt;huge&lt;/em&gt; numbers compared to the sample input so the range generation was causing PHP to run out of memory. Which means I had to rethink my solution &lt;em&gt;or&lt;/em&gt; throw a bunch of memory at it and hope for the best.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/advent-button-meme.png&quot; alt=&quot;Button meme showing &amp;quot;Make my code better&amp;quot; on one side and &amp;quot;give it ALL the memory I can&amp;quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So I ran it with 64GB of memory: &lt;code&gt;php -d memory_limit=64000M 1.php&lt;/code&gt; and it worked! Or at least, it ran. It gave me an answer that was wrong. I had a better look at the numbers in the real input and called it a day.&lt;/p&gt;
&lt;p&gt;Two hours later I had a moment of clarity and realised how to solve this without needing the &lt;a href=&quot;https://en.wikipedia.org/wiki/Frontier_(supercomputer)&quot;&gt;1.102 exaFLOPS of the Frontier supercomputer&lt;/a&gt;. I also noticed a bit of testing code which sliced one of the arrays so even if I hadn&#39;t had the memory problems, I was never going to get the right answer. Whoops.&lt;/p&gt;
&lt;h3&gt;Part One Redux&lt;/h3&gt;
&lt;p&gt;Instead of generating the ranges for every number, I could work out the index of the seed by generating the start and end of each of the ranges:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $mapData[$mapName] = array_replace($mapData[$mapName], array_combine(&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    range($sourceStart, $sourceStart + $rangeLength - 1),&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    range($destinationStart, $destinationStart + $rangeLength - 1),&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; ));&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $mapData[$mapName][] = [&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &#39;sourceStart&#39; =&gt; $sourceStart,&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &#39;sourceEnd&#39; =&gt; $sourceStart + $rangeLength - 1,&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &#39;destinationStart&#39; =&gt; $destinationStart,&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;    &#39;destinationEnd&#39; =&gt; $destinationStart + $rangeLength - 1,&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; ];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then calculate the difference to make my index, then use that index on the next &amp;quot;map&amp;quot; to get the correct value:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$locations&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$seeds&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$seed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$seed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapData&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$mapName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$mapArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$mapArray&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;sourceStart&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;sourceEnd&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;sourceStart&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword type-casting&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;destinationStart&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$locations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Lowest location number is &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$locations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Part one done. And I didn&#39;t even need to give it extra memory to run.&lt;/p&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;To paraphrase Marie Kondo:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;your feelings are the standard for decision making – specifically, knowing what sparks joy.  To determine this when writing code, the key is to pick up each bit of code one at a time, and ask yourself quietly, “Does this spark joy?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just like 2015&#39;s Fantastic Four, there is no part two. Not today, satan.&lt;/p&gt;
&lt;p&gt;My code is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/05&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;And probably be as confused as I was &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>My solution for "If You Give A Seed A Fertilizer"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Four</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-four/"/>
    <updated>2023-12-04T13:07:52Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-four/</id>
    <content type="html">&lt;p&gt;As soon as I saw this one this morning I knew it was going to at least be a bit easier than &lt;a href=&quot;/advent-of-code-2023-day-three&quot;&gt;yesterday&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;The premise for today was scratchcards with two sets of numbers: winning numbers and numbers you have. The first half is winning numbers, the second is numbers you have.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;Card &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;41&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;83&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;86&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;83&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;86&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;31&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;17&lt;/span&gt;  &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;53&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the Advent of Code page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Card 1 has five winning numbers (41, 48, 83, 86, and 17) and eight numbers you have (83, 86, 6, 31, 17, 9, 48, and 53). Of the numbers you have, four of them (48, 83, 17, and 86) are winning numbers!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Seemed easy enough especially when using PHP&#39;s &lt;a href=&quot;https://www.php.net/manual/en/function.array-intersect.php&quot;&gt;&lt;code&gt;array_intersect&lt;/code&gt;&lt;/a&gt; which returns &amp;quot;&lt;em&gt;an array containing all the values of array that are present in all the arguments&lt;/em&gt;&amp;quot;. In this case, our winning numbers. For each winning number, the score doubles (starting with one for the first winning number). The goal was the find the total score of all the winning cards.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// explode the string to get only the numbers&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$card&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// get the two strings of numbers&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;|&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// make them an array&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$winningNumbers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_intersect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$currentTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$winningNumbers&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$win&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$currentTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token comment&quot;&gt;// first number, so start at 1 for the score&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$currentTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// each additional winning number doubles the score&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$currentTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$currentTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$currentTotal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Current total &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was pretty confident in this solution but I did not get the correct answer using the sample input. I then noticed the inconsistent spaces in the string so my &lt;code&gt;array_intersect&lt;/code&gt; was returning additional empty values. A quick &lt;code&gt;array_filter&lt;/code&gt; later and I had the correct answer so I was onto part two.&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $winningNumbers = array_intersect($have, $winners);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $winningNumbers = array_filter(array_intersect($have, $winners));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;Part two is, as always, more complicated:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Instead, scratchcards only cause you to win more scratchcards equal to the number of winning numbers you have&lt;/p&gt;
&lt;p&gt;Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4, and 5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Starting with part one&#39;s code, I did some processing of the data prior to looping over each scratchcard.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$l&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$l&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;|&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;winners&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$winners&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;have&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$have&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [[&#39;winners&#39; =&gt; [4,5,6], &#39;have&#39; =&gt; [1,2,3]], ...]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$multipliers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_fill&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [1 =&gt; 1, 2 =&gt; 2, 3 =&gt; 3, ...]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then looped over the scratchcards, identified the winning numbers, then for each number add to the &lt;code&gt;multipliers&lt;/code&gt; for that card. For example, card one has four wininng numbers so it &amp;quot;copies&amp;quot; cards two, three, four, and five by setting it to &lt;code&gt;2&lt;/code&gt;. When I hit card two in the loop, the added number would be &lt;code&gt;2&lt;/code&gt; rather than one, because I have two copies of that card.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$lines&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$cardId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// count the winning numbers&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;array_intersect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;have&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;winners&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// if there are none, we don&#39;t need to make any card copies&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// the card ID of the next card we need to copy&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$windex&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$cardId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// for each winning number, add the the multipliers to &quot;copy&quot; that card&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$winCount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$win&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$multipliers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$windex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$multipliers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$cardId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$windex&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All in all this took me about 30 minutes for part one, and about 15 minutes for part two - although I did think about part two for a few hours while I was working.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/04&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>My solution for "Scratchcards"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Three</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-three/"/>
    <updated>2023-12-03T11:50:39Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-three/</id>
    <content type="html">&lt;p&gt;More regex and string parsing today. Sounds like a party.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;Given an &amp;quot;engine schematic&amp;quot; like below, identify which numbers are part numbers. That is, they have a symbol (not a &lt;code&gt;.&lt;/code&gt; though) either next to, above, or below them including diagonally.&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;467..114..&lt;br /&gt;...*......&lt;br /&gt;..35..633.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, &lt;code&gt;467&lt;/code&gt; and &lt;code&gt;35&lt;/code&gt; &lt;em&gt;are&lt;/em&gt; part numbers, &lt;code&gt;114&lt;/code&gt; and &lt;code&gt;633&lt;/code&gt; are not.&lt;/p&gt;
&lt;p&gt;My plan was a such: go through each line, identifying the part numbers and symbols, and then use &lt;code&gt;strpos&lt;/code&gt; to work out if they are or are not part numbers. I also generated a range that I could use with &lt;code&gt;substr&lt;/code&gt; to get the location of the number (plus an additional character each side) on the previous, current, and next lines. For example if my string was as below, the range starts at  &lt;code&gt;2&lt;/code&gt; and ends at &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//       0123456789&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;...56.....&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// then use substr to get `.56.`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After some tinkering around I had a solution that worked. At least for the sample input.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$explodedInput&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$strippedInput&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$strippedInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/\d+/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/\D/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$symbols&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$explodedInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$previous&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$explodedInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$next&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$explodedInput&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strpos&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$position&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$findInCurrent&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$findInPrevious&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$previous&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$findInNext&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/[^0-9\.]/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$findInCurrent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/[^0-9\.]/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$findInPrevious&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/[^0-9\.]/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$findInNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$sn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$sn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$number&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Current total &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When I ran this on the real data, my total was too high. Despite how it looks, the code is relatively straight forward so I knew there must be something tiny I was missing.&lt;/p&gt;
&lt;p&gt;What I haven’t accounted for was numbers appearing more than once in a single line. I was using &lt;code&gt;strpos&lt;/code&gt; which finds the first instance of a string so if the string was &lt;code&gt;654...6...&lt;/code&gt; then when I tried to find that second &lt;code&gt;6&lt;/code&gt; it would find the first one. It sounds obvious but on the first pass it just didn&#39;t occur to me.&lt;/p&gt;
&lt;p&gt;Off the top of my head I didn&#39;t know how to fix this problem. Turns out &lt;code&gt;preg_match_replace&lt;/code&gt; &lt;a href=&quot;https://www.php.net/manual/en/function.preg-match-all.php&quot;&gt;can take a fourth parameter&lt;/a&gt; of &lt;code&gt;PREG_OFFSET_CAPTURE&lt;/code&gt; to return the string offset of the found string:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;654...6...&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/\d+/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [[&quot;654&quot;,&quot;6&quot;]]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/\d+/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$numbersWithOffset&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PREG_OFFSET_CAPTURE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [[[&quot;654&quot;,0], [&quot;6&quot;,6]]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then instead of getting the position separately, I could grab it from the matches:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; foreach ($numbers[0] as $number)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; foreach ($numbers[0] as $numberData)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;{&lt;br /&gt;&lt;span class=&quot;token deleted-sign deleted&quot;&gt;&lt;span class=&quot;token prefix deleted&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; $position = strpos($line, $number);&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt; [$number, $position] = $numberData;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And just like that I had the correct answer to part one.&lt;/p&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;Today&#39;s puzzle did not spark joy so I just didn&#39;t do part two. &lt;a href=&quot;https://zoeaubert.me/blog/advent-of-code-2023-day-03/&quot;&gt;Zoe&lt;/a&gt; and &lt;a href=&quot;https://lewisdale.dev/post/advent-of-code-2023-day-three/&quot;&gt;Lewis&lt;/a&gt; did if you want to see a completed solution. Here&#39;s hoping tomorrow is a bit less straining on my sleep-deprived brain.&lt;/p&gt;
&lt;p&gt;My solution for part one is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/03&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It wasn&#39;t a party at all. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>My solution for "Gear Ratios"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day Two</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-two/"/>
    <updated>2023-12-02T22:06:56Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-two/</id>
    <content type="html">&lt;p&gt;After finally finding time to do today&#39;s challenge, I was able to knock it out in about 30 minutes for parts one and two. At the core of both of parts was parsing strings like this:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// and so on&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;For part one I needed to get the game ID plus the amount and related colors from each pick of the games. There are a lot of ways of doing this but the solution I went with was some good-old fashioned string-replacement and exploding:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$colors&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;red&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;green&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;blue&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$validGameTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$game&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$games&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$gameId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$game&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$picks&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$games&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$gameValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$picks&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$gameValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token variable&quot;&gt;$gameValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$gameValid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$validGameTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$gameId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$validGameTotal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;break&lt;/code&gt; statement would make more sense instead of using &lt;code&gt;continue&lt;/code&gt; but I&#39;m not changing it now.&lt;/p&gt;
&lt;h3&gt;Part Two&lt;/h3&gt;
&lt;p&gt;Part two was similar but I needed to find the highest value of each given color and multiply them. PHP&#39;s &lt;code&gt;max&lt;/code&gt; function made this easy:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$game&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$games&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$gameId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$game&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$picks&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$games&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$blue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$green&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$picks&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pick&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;blue&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$blue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$blue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;red&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$red&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;green&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token variable&quot;&gt;$green&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$green&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$amount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$blue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$green&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Onwards to day three.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/02&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>My solution for "Cube Conundrum"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Advent of Code 2023: Day One</title>
    <link href="https://rknight.me/blog/advent-of-code-2023-day-one/"/>
    <updated>2023-12-01T11:30:30Z</updated>
    <id>https://rknight.me/advent-of-code-2023-day-one/</id>
    <content type="html">&lt;p&gt;Until &lt;a href=&quot;https://zoeaubert.me&quot;&gt;Zoe&lt;/a&gt; mentioned it this morning, I didn&#39;t know what &lt;a href=&quot;https://adventofcode.com&quot;&gt;Advent of Code&lt;/a&gt; was &lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;. Advent of Code is an &amp;quot;&lt;em&gt;advent calendar of small programming puzzles&lt;/em&gt;&amp;quot;. So once I knew what it was, I figured I&#39;d give it a go. I&#39;m not sure if I&#39;ll make it all month but I&#39;ll certainly try. I&#39;m doing it in PHP because it&#39;s what I know and it will annoy Zoe a little bit; you can see &lt;a href=&quot;https://zoeaubert.me/blog/advent-of-code-2023-day-01/&quot;&gt;her rust-based solution here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;The first challenge was to extract the first and last digit from an array of strings, concatenate them, then get the total. For example the result of this on &lt;code&gt;1fghy2&lt;/code&gt; would give &lt;code&gt;12&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Anyone who knows me professionally knows regex is my kryptonite. It just doesn&#39;t click with my brain and I seem to forget anything I learn about it instantly. I fired up &lt;a href=&quot;https://regex101.com/&quot;&gt;regex101&lt;/a&gt; to give this a go anyway. Regex101 has a handy quick reference which told me I needed &lt;code&gt;\d&lt;/code&gt; to find any digit. I used &lt;code&gt;preg_match_all&lt;/code&gt; to get all digits:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;1abc2&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;pqr3stu8vwx&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;a1b2c3d4e5f&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;treb7uchet&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;array_reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// get all digits&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/\d/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$last&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$last&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$total&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;The total is &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PHP_EOL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// The total is 142&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Part One&lt;/h3&gt;
&lt;p&gt;Part two added a complexity that some of the numbers could be written out as words instead of digits. Some of the strings might have no digits and some might have no numbers-as-words. So &lt;code&gt;onedsjfbi2&lt;/code&gt; would give &lt;code&gt;12&lt;/code&gt; and &lt;code&gt;23sdshseven&lt;/code&gt; would give &lt;code&gt;27&lt;/code&gt;. This part I &lt;em&gt;did&lt;/em&gt; know; find all digits, or the words of 1-9. A quick swap of my regex from before and mapping words to numbers with PHPs &lt;a href=&quot;https://www.php.net/manual/en/migration70.new-features.php&quot;&gt;null coalescing operator&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$lettersToNumbers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;one&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;two&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// and so on&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/\d|one|two|three|four|five|six|seven|eight|nine)/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$lettersToNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$last&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$lettersToNumbers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I thought I&#39;d cracked it but the advent of code site told me my number was too high. I logged out all the strings and the numbers I had found with my regex and eyeballed &lt;em&gt;a lot&lt;/em&gt; of them and everything seemed fine. After a good 20 minutes or so I had to call it quits and check out what &lt;a href=&quot;https://lewisdale.dev/post/advent-of-code-2023-day-one/&quot;&gt;Lewis had for his solution&lt;/a&gt;. It turns out some of the strings have words that crossover, for example &lt;code&gt;35oneight&lt;/code&gt;. The result &lt;em&gt;should&lt;/em&gt; be &lt;code&gt;38&lt;/code&gt; but I was getting &lt;code&gt;31&lt;/code&gt; because regex will match the first instance (in this case &lt;code&gt;one&lt;/code&gt;) and then move on. I didn&#39;t look at Lewis&#39; solution because I still want to attempt it myself.&lt;/p&gt;
&lt;p&gt;After a bit of googling what I needed was a &lt;a href=&quot;https://stackoverflow.com/questions/35458195/pcre-regular-expression-overlapping-matches&quot;&gt;capturing technique inside an unanchored positive lookahead&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; which would then return &lt;code&gt;eight&lt;/code&gt; in the example above:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/(?=(\d|one|two|three|four|five|six|seven|eight|nine))/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there we go, day one done.&lt;/p&gt;
&lt;p&gt;My solution is &lt;a href=&quot;https://github.com/rknightuk/adventofcode/tree/main/2023/01&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot; /&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Or more likely, I did know and just forgot about it. &lt;a href=&quot;#fnref1&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Very normal sentence, yes. Nothing to see here. &lt;a href=&quot;#fnref2&quot; class=&quot;footnote-backref&quot;&gt;&amp;#10558;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
    <summary>My solution for "Trebuchet?!"</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Crossover</title>
    <link href="https://rknight.me/blog/crossover/"/>
    <updated>2023-11-30T21:17:34Z</updated>
    <id>https://rknight.me/crossover/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/crossover-logo.png&quot; alt=&quot;Crossover logo&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Sometimes one idea begets another. In the case of &lt;a href=&quot;https://crossover.rknight.me&quot;&gt;Crossover&lt;/a&gt; I had the idea while building &lt;a href=&quot;/doubleshift&quot;&gt;DoubleShift&lt;/a&gt; but I was too far in to change it. DoubleShift also now has some fun additional features like leaderboards which only make sense for that site.&lt;/p&gt;
&lt;p&gt;Crossover, unlike DoubleShift, isn&#39;t limited to a handful of TV shows: if a show is in &lt;a href=&quot;https://www.themoviedb.org/&quot;&gt;The Movie Database&lt;/a&gt; you can compare it with Crossover.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/crossover-screenshot.png&quot; alt=&quot;Crossover screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are a few pre-loaded shows on the site but you can search for any show - once you&#39;ve found one, it gets added to the options so you can mix and match in any way you want.&lt;/p&gt;
&lt;p&gt;The logo is a mix of Breaking Bad and Game of Thrones so you might think Game of Thrones would be a good default on the site but there are very few actors that crossover with other shows I was testing with. The font looked good though so here we are.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://crossover.rknight.me&quot;&gt;Check out Crossover here&lt;/a&gt; and &lt;a href=&quot;https://doubleshift.rknight.me&quot;&gt;DoubleShift here&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A spin-off project from DoubleShift: compare actor appearances from any two TV shows</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>DoubleShift</title>
    <link href="https://rknight.me/blog/doubleshift/"/>
    <updated>2023-11-27T22:30:06Z</updated>
    <id>https://rknight.me/doubleshift/</id>
    <content type="html">&lt;p&gt;I have watched &lt;a href=&quot;https://www.themoviedb.org/tv/4556-scrubs&quot;&gt;Scrubs&lt;/a&gt; more times than I can count and I am currently re-watching &lt;a href=&quot;https://www.themoviedb.org/tv/1416-grey-s-anatomy&quot;&gt;Grey&#39;s Anatomy&lt;/a&gt; for the third (maybe fourth?) time. I noticed there are a lot of actors who have appeared in both and it &lt;em&gt;seemed&lt;/em&gt; like it was every other episode. After some data-wrangling I have an actual answer: 28 actors have appeared in both series.&lt;/p&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;I thought it would be fun to show this on a site along with highlighting what I&#39;m calling &amp;quot;double doctors&amp;quot;: that is, actors who have played a doctor in both shows. The site is called &lt;a href=&quot;https://doubleshift.rknight.me&quot;&gt;DoubleShift&lt;/a&gt; and it has this nifty logo I whipped up:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://doubleshift.rknight.me&quot;&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/double-shift-logo.png&quot; alt=&quot;DoubleShift logo&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I mentioned this idea to &lt;a href=&quot;https://mas.to/@_dreaves&quot;&gt;David&lt;/a&gt; and he asked what the numbers were like against &lt;a href=&quot;https://www.themoviedb.org/tv/1408-house&quot;&gt;House&lt;/a&gt;. So I added House to my dataset: 78 actors have appeared in Grey&#39;s and House, and 48 have appeared in Scrubs and House. I also added &lt;a href=&quot;https://www.themoviedb.org/tv/4588-er?language=en-GB&quot;&gt;ER&lt;/a&gt; because that had a lot of crossover too.&lt;/p&gt;
&lt;p&gt;I briefly added General Hospital because of how long it has been running but there was &lt;a href=&quot;https://www.themoviedb.org/person/36216-cynthia-watros&quot;&gt;just one actress&lt;/a&gt; who has been in any of the other shows so I removed it again. Also, adding even one more show generates so many more permutations.&lt;/p&gt;
&lt;h3&gt;Handling the Data&lt;/h3&gt;
&lt;p&gt;To fetch the actor data for each show I used &lt;a href=&quot;https://developer.themoviedb.org/reference/intro/getting-started&quot;&gt;The Movie Database API&lt;/a&gt; which has a handy &amp;quot;Aggregate Credits&amp;quot; endpoint for fetching all actors who have been in a show across all seasons. I then mapped that data to a keyed object by their TMDB ID:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://api.themoviedb.org/3/tv/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;show&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;/aggregate_credits?&amp;amp;series_id=1416&amp;amp;language=en-US&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string-property property&quot;&gt;&#39;Authorization&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;API_KEY&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string-property property&quot;&gt;&#39;accept&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;application/json&#39;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; json &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cast&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;actor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;actor&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;actor&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To find the actors who have been in both shows a &lt;code&gt;filter&lt;/code&gt; did the trick:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; intersection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;showData&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;showOne&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;showData&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;showTwo&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;element&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// console.log(intersection)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [123, 3456, 3456]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I used &lt;a href=&quot;https://11ty.dev&quot;&gt;Eleventy&lt;/a&gt; like I always do because it&#39;s data files are perfect at handling this kind of thing and using nunjucks is easy-peasy to output what I want. I decided to avoid using javascript on the site itself here so I used CSS and radio buttons to show and hide each combination of show.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;#show-greys-scrubs&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;#greys-scrubs:checked ~ #show-greys-scrubs&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s worth noting that when using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Subsequent-sibling_combinator&quot;&gt;subsequent-sibling combinator&lt;/a&gt; (&lt;code&gt;~&lt;/code&gt;) the two elements must be children of the same parent so I couldn&#39;t have the radio buttons inside their own container which made styling them slightly harder, but a small price to pay to not rely on JS here.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://doubleshift.rknight.me&quot;&gt;View the DoubleShift site here&lt;/a&gt; and you can view &lt;a href=&quot;https://github.com/rknightuk/doubleshift&quot;&gt;the source on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Update 2023-11-28: Added four more shows and leaderboards&lt;/li&gt;
&lt;li&gt;Update 2023-11-30: Check out &lt;a href=&quot;/crossover&quot;&gt;Crossover&lt;/a&gt; to compare &lt;em&gt;any&lt;/em&gt; two TV shows&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>A small idea to check how many actors have been in both Scrubs and Grey's Anatomy turned into a much bigger thing</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Popular Pages with Eleventy and Fathom Analytics</title>
    <link href="https://rknight.me/blog/popular-pages-with-eleventy-and-fathom-analytics/"/>
    <updated>2023-11-24T22:42:04Z</updated>
    <id>https://rknight.me/popular-pages-with-eleventy-and-fathom-analytics/</id>
    <content type="html">&lt;p&gt;Now my new site design is done, I&#39;ve been able to take some time to add features I&#39;ve wanted for a while. In this case, I want to show popular pages based on pageviews at the end of blog posts, on the &lt;a href=&quot;/search&quot;&gt;search page&lt;/a&gt;, and on the &lt;a href=&quot;/404notfound&quot;&gt;404 page&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Fetching Pageviews&lt;/h3&gt;
&lt;p&gt;I use &lt;a href=&quot;https://usefathom.com/ref/IXCLSF&quot;&gt;Fathom&lt;/a&gt; for analytics on my sites and they &lt;a href=&quot;https://usefathom.com/api&quot;&gt;have an API&lt;/a&gt; which is handy. If you use Plausible for your analytics you should &lt;a href=&quot;https://coryd.dev/posts/2023/popular-posts-widget-using-eleventy-plausible/&quot;&gt;check out Cory&#39;s post&lt;/a&gt; on the same topic for the specific API implementation. He also uses liquid rather than nunjucks which I use so if that&#39;s your jam you probably want his post instead.&lt;/p&gt;
&lt;p&gt;To fetch the data I use &lt;a href=&quot;https://www.11ty.dev/docs/data-global/&quot;&gt;Eleventy data files&lt;/a&gt;. You can get an API key from &lt;a href=&quot;https://app.usefathom.com/api&quot;&gt;your Fathom dashboard&lt;/a&gt;. Also, you don&#39;t &lt;em&gt;need&lt;/em&gt; to use the &lt;a href=&quot;https://www.npmjs.com/package/qs&quot;&gt;&lt;code&gt;qs&lt;/code&gt;&lt;/a&gt; library but it does make life a bit easier.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// _data/fathom.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; qs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;qs&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date_from &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;subtract&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;days&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;YYYY-MM-DD HH:mm&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; date_to &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;moment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;YYYY-MM-DD HH:mm&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; query &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; qs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stringify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;pageview&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FATHOM_SITE_CODE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;aggregates&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;pageviews&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;field_grouping&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;pathname&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		date_from&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		date_to&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;sort_by&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;pageviews:desc&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://api.usefathom.com/v1/aggregations?&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;query&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token string-property property&quot;&gt;&#39;Authorization&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Bearer &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FATHOM_API_KEY&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; json &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives uses a response like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		pageviews&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		pathname&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;/&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		pageviews&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		pathname&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;/please-expose-your-rss/&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		pageviews&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;98&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		pathname&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &#39;/app-defaults/&#39;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token comment&quot;&gt;// and so on&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first problem here is this includes pages that aren&#39;t blog posts. If you&#39;re normal and setup your site well, this is easy: filter the list to only get posts that contain &lt;code&gt;/blog&lt;/code&gt; in the &lt;code&gt;pathname&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; json &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;pv&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; pv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/blog&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&#39;re like me and made a silly mistake many years ago and your posts live at the root of your site, you have to get a bit creative to get all the blog post paths. I&#39;m also using &lt;code&gt;titleMap&lt;/code&gt; to get the titles of the posts so I can add those to the Fathom data.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;fs&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ...fetching fathom goes here&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; files &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./src/posts/blog/**/*.md&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; titleMap &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;files&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;page&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;utf8&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; permalink &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^permalink: ?(.*$)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;gm&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;permalink: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;index.html&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^title: ?(.*$)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;gm&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;title: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;	&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		title &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;	&lt;br /&gt;	titleMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;permalink&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; title&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// titleMap = {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;/please-expose-your-rss/&#39;: &#39;Please, Expose your RSS&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;/app-defaults/&#39;: &#39;App Defaults&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// filter out only blog posts&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; json&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;pv&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;titleMap&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// add the titles to the fathom data&lt;/span&gt;&lt;br /&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;pv&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; titleMap&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; pv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pathname&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;pageviews&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; pv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pageviews&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; data&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This sets the &lt;code&gt;fathom&lt;/code&gt; data to something like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Please, Expose your RSS&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/please-expose-your-rss/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;pageviews&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;App Defaults&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/app-defaults/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token literal-property property&quot;&gt;pageviews&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;98&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token comment&quot;&gt;// and so on&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s worth noting you don&#39;t have to map the titles to the data inside the data file, you can do it when rendering popular posts inside a custom filter as &lt;a href=&quot;https://coryd.dev/posts/2023/popular-posts-widget-using-eleventy-plausible/&quot;&gt;Cory did&lt;/a&gt; which would give you access to other post attributes you have. I didn&#39;t need any of the additional attributes as I&#39;m just outputting the title and link so I didn&#39;t bother but it&#39;s worth keeping in mind.&lt;/p&gt;
&lt;h3&gt;Including Popular Posts&lt;/h3&gt;
&lt;p&gt;I want to include the popular pages in multiple places so an include file makes the most sense. Annoyingly, nunjucks doesn&#39;t support passing in variables to an include like liquid does so I need to define the variables before each include:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// all popular posts&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; popular &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fathom &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;popularPosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; include &lt;span class=&quot;token string&quot;&gt;&#39;popular_posts.njk&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// on a post page, exclude that post by passing in the current url&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; pageUrl &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; stripIndex &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; endset &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; popular &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fathom &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;popularPosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pageUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; include &lt;span class=&quot;token string&quot;&gt;&#39;popular_posts.njk&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;popularPosts&lt;/code&gt; is an Eleventy filter I have defined in my config:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .eleventy.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;popularPosts&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;pageviews&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; limit&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pageviews&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;pv&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; pv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// filter out the passed in url&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; limit&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// limit to the passed-in limit&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the &lt;code&gt;popular_posts.njk&lt;/code&gt; include looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;// _includes/popular_posts.njk&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;use&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xlink:&lt;/span&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#popular&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; Popular Posts&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;	{%- for p in popular %}&lt;br /&gt;		&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{{ p.url }}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ p.title }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;li&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;	{% endfor %}&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;ul&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;small&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Analytics powered by &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://usefathom.com/ref/IXCLSF&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Fathom&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;small&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the final result (or you can look just below this post and they &lt;em&gt;should&lt;/em&gt; be there unless I broke something, or got bored and removed them 🙃). If you don&#39;t have analytics yet and want to use Fathom &lt;a href=&quot;https://usefathom.com/ref/IXCLSF&quot;&gt;my referral link&lt;/a&gt; will give you $10 credit - I&#39;ve been using them for a quite a while and use them on all of my sites.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/fathom-popular-posts.jpg&quot; alt=&quot;Popular Posts screenshot&quot; /&gt;&lt;/p&gt;
</content>
    <summary>How I'm using the Fathom API to show a list of popular blogs posts in my Eleventy site</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Using SVG Sprites</title>
    <link href="https://rknight.me/blog/using-svg-sprites/"/>
    <updated>2023-11-21T21:41:14Z</updated>
    <id>https://rknight.me/using-svg-sprites/</id>
    <content type="html">&lt;p&gt;Recently someone emailed me to ask how I was doing SVGs on my website because they&#39;d looked in the source but it wasn&#39;t obvious how it actually rendered the SVG so I figured I would do a proper post about it. Here is their email:&lt;/p&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#39;m looking to steal more ideas from you and found this while looking through your web site source:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;use&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xlink:&lt;/span&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#rklogo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;But when I inspect the DOM I see it fully expanded:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;use&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xlink:&lt;/span&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#rklogo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;viewBox&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0 0 400 400&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2000/svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;rklogo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;logo-bar&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;currentColor&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill-rule&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;evenodd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M 300 400 L 200 200 L 300 0 L 400 0 L 300 200 L 400 400 L 300 400 Z&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;logo-dot&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill-rule&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;evenodd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M 0 399 L 75 399 L 75 324 L 0 324 Z&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;logo-bar&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;currentColor&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill-rule&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;evenodd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M 150 400 L 50 200 L 106 89 L 0 89 L 0 0 L 250 0 L 150 200 L 250 400 L 150 400 Z&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h3&gt;Other Methods&lt;/h3&gt;
&lt;p&gt;Before I get into how to use sprites, there are two arguably easier options to use an SVG on a website: &lt;code&gt;img&lt;/code&gt; and directly:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- use the SVG just like any other image --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;icon.svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- put the SVG in directly --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;viewBox&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0 0 400 400&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2000/svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#000000&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill-rule&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;evenodd&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;stroke&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;none&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M 300 400&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using an &lt;code&gt;img&lt;/code&gt; tag is quick but you lose any ability to change the SVG colors, or animate it, with CSS. If you have an SVG that doesn&#39;t need any of that, this works fine.&lt;/p&gt;
&lt;p&gt;Putting the SVG in the HTML directly is also a perfectly fine way to do it, but it can get messy if you have lots of icons, or you need to reuse the same icon multiple times.&lt;/p&gt;
&lt;h3&gt;SVG Sprites&lt;/h3&gt;
&lt;p&gt;An SVG sprite is basically a collection of SVGs inside an &lt;code&gt;svg&lt;/code&gt; tag that can be used with the syntax I already mentioned at the top of the article. A sprite looks something like this where we have an &lt;code&gt;svg&lt;/code&gt; tag and then some SVGs inside that. Note the &lt;code&gt;id&lt;/code&gt; attribute - this is used to identify the SVG when we use it elsewhere on the site. For my sites, I usually put the sprite right before the closing &lt;code&gt;body&lt;/code&gt; tag.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt;  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;buymeacoffee&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;img&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2000/svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;viewBox&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0 0 24 24&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;currentColor&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M20.216 6.415l-.132-.666c-.119-.598-.388-1.163-1.001-1.379-.197-.069-.42-.098-.57-.241-.152-.143-.196-.366-.231-.572-.065-.378-.125-.756-.192-1.133-.057-.325-.102-.69-.25-.987-.195-.4-.597-.634-.996-.788a5.723 5.723 0 00-.626-.194c-1-.263-2.05-.36-3.077-.416a25.834 25.834 0 00-3.7.062c-.915.083-1.88.184-2.75.5-.318.116-.646.256-.888.501-.297.302-.393.77-.177 1.146.154.267.415.456.692.58.36.162.737.284 1.123.366 1.075.238 2.189.331 3.287.37 1.218.05 2.437.01 3.65-.118.299-.033.598-.073.896-.119.352-.054.578-.513.474-.834-.124-.383-.457-.531-.834-.473-.466.074-.96.108-1.382.146-1.177.08-2.358.082-3.536.006a22.228 22.228 0 01-1.157-.107c-.086-.01-.18-.025-.258-.036-.243-.036-.484-.08-.724-.13-.111-.027-.111-.185 0-.212h.005c.277-.06.557-.108.838-.147h.002c.131-.009.263-.032.394-.048a25.076 25.076 0 013.426-.12c.674.019 1.347.067 2.017.144l.228.031c.267.04.533.088.798.145.392.085.895.113 1.07.542.055.137.08.288.111.431l.319 1.484a.237.237 0 01-.199.284h-.003c-.037.006-.075.01-.112.015a36.704 36.704 0 01-4.743.295 37.059 37.059 0 01-4.699-.304c-.14-.017-.293-.042-.417-.06-.326-.048-.649-.108-.973-.161-.393-.065-.768-.032-1.123.161-.29.16-.527.404-.675.701-.154.316-.199.66-.267 1-.069.34-.176.707-.135 1.056.087.753.613 1.365 1.37 1.502a39.69 39.69 0 0011.343.376.483.483 0 01.535.53l-.071.697-1.018 9.907c-.041.41-.047.832-.125 1.237-.122.637-.553 1.028-1.182 1.171-.577.131-1.165.2-1.756.205-.656.004-1.31-.025-1.966-.022-.699.004-1.556-.06-2.095-.58-.475-.458-.54-1.174-.605-1.793l-.731-7.013-.322-3.094c-.037-.351-.286-.695-.678-.678-.336.015-.718.3-.678.679l.228 2.185.949 9.112c.147 1.344 1.174 2.068 2.446 2.272.742.12 1.503.144 2.257.156.966.016 1.942.053 2.892-.122 1.408-.258 2.465-1.198 2.616-2.657.34-3.332.683-6.663 1.024-9.995l.215-2.087a.484.484 0 01.39-.426c.402-.078.787-.212 1.074-.518.455-.488.546-1.124.385-1.766zm-1.478.772c-.145.137-.363.201-.578.233-2.416.359-4.866.54-7.308.46-1.748-.06-3.477-.254-5.207-.498-.17-.024-.353-.055-.47-.18-.22-.236-.111-.71-.054-.995.052-.26.152-.609.463-.646.484-.057 1.046.148 1.526.22.577.088 1.156.159 1.737.212 2.48.226 5.002.19 7.472-.14.45-.06.899-.13 1.345-.21.399-.072.84-.206 1.08.206.166.281.188.657.162.974a.544.544 0 01-.169.364zm-6.159 3.9c-.862.37-1.84.788-3.109.788a5.884 5.884 0 01-1.569-.217l.877 9.004c.065.78.717 1.38 1.5 1.38 0 0 1.243.065 1.658.065.447 0 1.786-.065 1.786-.065.783 0 1.434-.6 1.499-1.38l.94-9.95a3.996 3.996 0 00-1.322-.238c-.826 0-1.491.284-2.26.613z&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt;  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;github&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;img&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2000/svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;viewBox&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0 0 24 24&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;currentColor&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt;  &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;mastodon&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;img&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://www.w3.org/2000/svg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;viewBox&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0 0 24 24&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;path&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;currentColor&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because the SVGs have &lt;code&gt;fill=&amp;quot;currentColor&lt;/code&gt; set instead of a specific color, we can style them just using &lt;code&gt;color: #e33d94&lt;/code&gt; in CSS. Handy. To use one of the SVGs, for example &lt;code&gt;buymeacoffee&lt;/code&gt;, we can do the following in the HTML wherever we need it:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;use&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;xlink:&lt;/span&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#buymeacoffee&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;use&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;svg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which will output the icon:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/svg-icon-coffee.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; just paste in your SVGs to make a sprite or you can do what I do and use &lt;a href=&quot;https://svgsprit.es/&quot;&gt;https://svgsprit.es&lt;/a&gt;. You can drop in a bunch of SVGs and it will give you back your sprite for putting on your site. A lot of static site generators also have plugins to do this, for example &lt;a href=&quot;https://github.com/patrickxchong/eleventy-plugin-svg-sprite&quot;&gt;this one for Eleventy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can view the SVG sprite for &lt;a href=&quot;https://github.com/rknightuk/rknight.me/blob/master/src/_includes/svgs.njk&quot;&gt;this site on GitHub here&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>How to use SVG sprites on your website</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Pokédon: Read Mastodon on a Pokédex</title>
    <link href="https://rknight.me/blog/pokedon-read-mastodon-on-a-pokedex/"/>
    <updated>2023-11-18T19:32:15Z</updated>
    <id>https://rknight.me/pokedon-read-mastodon-on-a-pokedex/</id>
    <content type="html">&lt;p&gt;Today, I attended a casual no-official-name hackathon. Just a bunch of people working on silly projects. It &lt;em&gt;did&lt;/em&gt; have a theme though: silly interfaces. I spent the first hour before I arrived thinking of a few ideas until I thought of the perfect thing: a Mastodon client but it&#39;s in a Pokédex.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pokedon.rknight.me&quot;&gt;Try it out here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pokedon.png&quot; alt=&quot;Pokédon interface&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It&#39;s fairly limited but you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sign into your instance&lt;/li&gt;
&lt;li&gt;View your timeline&lt;/li&gt;
&lt;li&gt;Navigate with the keyboard (up/down for newer/older toots)&lt;/li&gt;
&lt;li&gt;Listen to a toot with the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis&quot;&gt;SpeechSynthesis API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Mastodon OAuth process is handled by &lt;a href=&quot;https://laravel.com/docs/10.x/socialite&quot;&gt;Laravel Socialite&lt;/a&gt; and &lt;a href=&quot;https://github.com/kawax/socialite-mastodon&quot;&gt;this Mastodon socialite provider&lt;/a&gt; which has excellent examples in the readme enabling me to have this up and running in under an hour. Interacting with the Mastodon API is done with &lt;a href=&quot;https://github.com/kawax/laravel-mastodon-api&quot;&gt;&lt;code&gt;kawax/laravel-mastodon-api&lt;/code&gt;&lt;/a&gt; by the same author.&lt;/p&gt;
&lt;p&gt;The SpeechSynthesis API allows you to do text to speech in the browser. For this project I used the &lt;code&gt;speak&lt;/code&gt; method as well as two events of &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisUtterance&quot;&gt;SpeechSynthesisUtterance&lt;/a&gt;: &lt;code&gt;end&lt;/code&gt; and &lt;code&gt;boundary&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// text to speech&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SpeechSynthesisUtterance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Hello&#39;&lt;/span&gt;&lt;br /&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;speechSynthesis&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;speak&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;end&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// do something&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get the text to output as it&#39;s spoken, I took the text, split it on a blank space, then slice the array and join again and then put that back in the element after each &lt;code&gt;boundary&lt;/code&gt; event. This isn&#39;t the best way as it removes any HTML like links. I&#39;d be interested in a reliable way to do this while keeping the HTML in tact.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; toot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#toot&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; content &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; toot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerText&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tootWords &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; currentBoundary &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;boundary&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    currentBoundary&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;br /&gt;    toot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;p&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;tootWords&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; currentBoundary&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/p&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make Professor Oak slide up when talking, I used CSS transitions on the height of the element:&lt;/p&gt;
&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;.poak&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; absolute&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; -5px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 75px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 230px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; hidden&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; all 1s&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token selector&quot;&gt;.poak.close&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Things it doesn&#39;t do right now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;s&gt;Be responsive. I just didn&#39;t have time today.&lt;/s&gt; Done 2023-11-21&lt;/li&gt;
&lt;li&gt;Allow boosting and favouriting.&lt;/li&gt;
&lt;li&gt;Allow you to pause audio.&lt;/li&gt;
&lt;li&gt;View followers&lt;/li&gt;
&lt;li&gt;View your activity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will probably come back to this at some point and add some of these features but as it is I&#39;m pretty happy with this as a day&#39;s project.&lt;/p&gt;
&lt;p&gt;Credit for the name goes to &lt;a href=&quot;https://zoeaubert.me&quot;&gt;Zoe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fonts used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dafont.com/pkmn-rbygsc.font&quot;&gt;PKMN RBYGSC Font&lt;/a&gt; for the text on the screens&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dafont.com/pokemon.font&quot;&gt;Pokémon Font&lt;/a&gt; for the logo&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://brailleinstitute.org/freefont&quot;&gt;Atkinson Hyperlegible Font&lt;/a&gt; for the body text&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>A Mastodon client in a Pokédex I built at a hackathon today</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>So Many Default Apps</title>
    <link href="https://rknight.me/blog/so-many-default-apps/"/>
    <updated>2023-11-16T22:16:38Z</updated>
    <id>https://rknight.me/so-many-default-apps/</id>
    <content type="html">&lt;p&gt;Two weeks ago when &lt;a href=&quot;https://listen.hemisphericviews.com/097&quot;&gt;Hemispheric Views 097&lt;/a&gt; released and &lt;a href=&quot;https://gabz.blog/2023/11/03/my-defaults.html&quot;&gt;people&lt;/a&gt; &lt;a href=&quot;https://rknight.me/app-defaults/&quot;&gt;started&lt;/a&gt; &lt;a href=&quot;https://maique.eu/2023/11/03/defaults.html&quot;&gt;putting&lt;/a&gt; &lt;a href=&quot;https://lmika.org/2023/11/04/defaults.html&quot;&gt;up&lt;/a&gt; &lt;a href=&quot;https://alpine.weblog.lol/2023/11/the-defaults&quot;&gt;their&lt;/a&gt; &lt;a href=&quot;https://canion.blog/2023/11/04/duel-of-the.html&quot;&gt;default&lt;/a&gt; &lt;a href=&quot;https://www.andycarolan.com/appdefaults&quot;&gt;app&lt;/a&gt; &lt;a href=&quot;https://mb.esamecar.net/2023/11/04/app-defaults.html&quot;&gt;posts&lt;/a&gt; &lt;a href=&quot;https://grepjason.sh/&quot;&gt;Jason&lt;/a&gt; said this in the HV Discord:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;take a hike &lt;code&gt;/now&lt;/code&gt;. It&#39;s all about &lt;code&gt;/default&lt;/code&gt; now&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I decided to quickly throw a site together to collect all these (at the time eight) blog posts in one place: &lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;App Defaults&lt;/a&gt;. I used this old web framework you might have heard of called &amp;quot;artisanal hand-crafted HTML&amp;quot;. It was only seven links, maybe a couple more, manually adding a new link didn&#39;t seem like a problem. Until &lt;em&gt;way&lt;/em&gt; more than that arrived. At it&#39;s peak, there were 35 new posts added to the list. As of this post, there are 151 posts listed.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Date&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Posts Added&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;4/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;5/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;6/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;7/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;8/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;9/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;11/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;12/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;13/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;14/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;15/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;16/11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;151&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Three days in I realised this was likely to take off so I switched the site to &lt;a href=&quot;https://11ty.dev&quot;&gt;Eleventy&lt;/a&gt; and a &lt;code&gt;json&lt;/code&gt; data file to keep track of the blog posts. I also added RSS feeds for everyone&#39;s sites.&lt;/p&gt;
&lt;p&gt;Day four was the busiest for submissions and I had a fun idea to allow anyone to subscribe to &lt;em&gt;all&lt;/em&gt; of the websites mentioned. I generated &lt;a href=&quot;https://github.com/rknightuk/app-defaults/blob/main/opml.njk&quot;&gt;an OPML file&lt;/a&gt; from the site data and added a link to that to the site.&lt;/p&gt;
&lt;h3&gt;Network Graph&lt;/h3&gt;
&lt;p&gt;The latest feature was added today when I was inspired by something said on &lt;a href=&quot;https://listen.hemisphericviews.com/098&quot;&gt;episode 098&lt;/a&gt; but as of this moment I cannot remember what it was that was said. Regardless, I wanted to visualise the links between all the blog posts to get a sense of how the &amp;quot;trend&amp;quot; spread between people so I created &lt;a href=&quot;https://defaults.rknight.me/network/&quot;&gt;the Network Graph page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To achieve this I used &lt;a href=&quot;https://github.com/extractus/article-extractor&quot;&gt;@extractus/article-extractor&lt;/a&gt; to extract the article contents from every post, then I used &lt;a href=&quot;https://github.com/WebReflection/linkedom&quot;&gt;linkedom&lt;/a&gt; to get all the links contained in each article, and then I mapped each of those links to the post they were linking to. Finally I ran a script to map that data to the format required for &lt;a href=&quot;https://visjs.github.io/vis-network/docs/network/index.html&quot;&gt;&lt;code&gt;network&lt;/code&gt;&lt;/a&gt; to render the graph. This is the same graph used on &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;omg.lol&lt;/a&gt; to show the referral data and thankfully I could look at Adam&#39;s implementation to speed things up.&lt;/p&gt;
&lt;p&gt;A few stats to finish:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;67 of the sites were added via a pull request on GitHub&lt;/li&gt;
&lt;li&gt;The most popular TLD is, unsurprisingly, &lt;code&gt;.com&lt;/code&gt; (48 posts). &lt;code&gt;.blog&lt;/code&gt;, &lt;code&gt;.me&lt;/code&gt;, and &lt;code&gt;.net&lt;/code&gt; were tied for second with 13 posts each.&lt;/li&gt;
&lt;li&gt;144 of the 151 sites have RSS feeds 🙌&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>A look at just over two weeks of adding submissions and features to the default apps website</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Using the Johnny Decimal System</title>
    <link href="https://rknight.me/blog/using-the-johnny-decimal-system/"/>
    <updated>2023-11-15T18:09:17Z</updated>
    <id>https://rknight.me/using-the-johnny-decimal-system/</id>
    <content type="html">&lt;p&gt;In &lt;a href=&quot;https://listen.hemisphericviews.com/025&quot;&gt;episode 028 of Hemispheric Views&lt;/a&gt; &lt;a href=&quot;https://canion.blog&quot;&gt;Andrew&lt;/a&gt; mentioned the &lt;a href=&quot;https://johnnydecimal.com&quot;&gt;Johnny Decimal (JD) system&lt;/a&gt; for organising files. I made a note of it as a thing to look into. Then, like a lot of things, I never went back to investigate. Then in &lt;a href=&quot;https://listen.hemisphericviews.com/096&quot;&gt;episode 096&lt;/a&gt; they had Mr Johnny Decimal himself on to talk about the system. This was the kick I needed to properly check it out. I also spoke with &lt;a href=&quot;https://mastodon.macstories.net/@johnvoorhees&quot;&gt;John&lt;/a&gt; about the JD system on the two most recent episodes of Ruminate if audio is more your thing.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ruminatepodcast.com/172/&quot;&gt;172 - Big Knowledge Boys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ruminatepodcast.com/173/&quot;&gt;173 - Should This Be a Blog Post?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before we get into it, the JD system has concepts that are worth knowing about for any of this to make sense:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Areas - these are the top level of the folder system, e.g. &lt;code&gt;10-19 Family&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Categories - These are the folders &lt;em&gt;inside&lt;/em&gt; areas, e.g. &lt;code&gt;10 Finance&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;IDs or Items - These are the actual files that exist inside of areas, e.g. &lt;code&gt;10.01 Insurance&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Attempt One&lt;/h3&gt;
&lt;p&gt;I skimmed through the &lt;a href=&quot;https://johnnydecimal.com&quot;&gt;beautiful website&lt;/a&gt; to get a sense of what the &amp;quot;rules&amp;quot; are for the system and starting coming up with my categories. Note I use the word &amp;quot;skimmed&amp;quot; there because I got this &lt;em&gt;very&lt;/em&gt; wrong; my categories were too narrow and my areas were too broad to make any sense. Johnny was kind enough &lt;a href=&quot;https://johnnydecimal.com/20-29-communication/23-forums-and-chat/23.02-discord/&quot;&gt;in the JD Discord&lt;/a&gt; to give me some feedback after I clearly rushed though and didn&#39;t pay enough attention to the website. I&#39;ll just go over two of them here:&lt;/p&gt;
&lt;details&gt;
	&lt;summary&gt;00-09 System&lt;/summary&gt;
	&lt;pre&gt;00-09 System
│ 00 Inbox
│ 01 Exported Data
│ ├── 01.01 Twitter
│ ├── 01.02 Tumblr
│ ├── 01.03 Instagram
│ ├── 01.04 Mastodon
│ ├── 01.05 Reddit
│ ├── 01.06 Project Databases
│ ├── 01.07 Other
│ 02 Education Archive
│ ├── 02.01 College
│ ├── 02.02 Uni
│ ├── 02.03 School
│ 03 Sites Archive
│ ├── 03.01 Just Delete Me (JDM)
│ ├── 03.02 Wordpress Themes
│ ├── 03.03 Personal
│ ├── 03.04 Freelance
│ ├── 03.05 DevsDoDesign
│ 09 Archive
│ ├── 09.01 Archive
│ ├── 09.02 Camera Uploads
	&lt;/pre&gt;
&lt;/details&gt;
&lt;blockquote&gt;
&lt;p&gt;I think all archives can just become 09 archive. it doesn’t feel like you have anywhere near 99 things you’ll ever put in there? fill ‘er up baby&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this case, I was trying to organise too hard. As Johnny pointed out, for an archive it really doesn&#39;t matter how much stuff is in there. Fill &#39;er up baby indeed.&lt;/p&gt;
&lt;details&gt;
	&lt;summary&gt;40-49 Games&lt;/summary&gt;
	&lt;pre&gt;40-49 Games
│ 40 Screenshots
│ 41 Manuals
│ 42 ROMs
&lt;/pre&gt;
&lt;/details&gt;
&lt;blockquote&gt;
&lt;p&gt;that’s a nice clear area, perhaps it doesn’t need its own area and could just be a category elsewhere though? do you see it filling up with time, or is this it? if this is it it’s a ‘waste’ of an area as it is&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I mean you have 10 to use, it’s not like it’s a crime…I’ve just learned over the years that compression tends to better results&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This category was far too specific. This is 10 years worth of stuff, it&#39;s unlikely I&#39;m going to suddenly have a huge influx in new areas of things for this.&lt;/p&gt;
&lt;p&gt;Johnny also offered some other advice about my other categories but the general gist was I hadn&#39;t quite &lt;em&gt;got it&lt;/em&gt;. So I dug into the book (which Johnny kindly sent me).&lt;/p&gt;
&lt;h3&gt;The Workbook&lt;/h3&gt;
&lt;p&gt;The JD Workbook is a 110-page ebook designed to &amp;quot;&lt;em&gt;guide you through the entire process of setting up your own Johnny.Decimal system&lt;/em&gt;&amp;quot;. There are also videos at the end of each section which go over everything in that chapter. I found these useful particularly seeing how Johnny does his index in &lt;a href=&quot;https://bear.app&quot;&gt;Bear&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Johnny gave me this advice before starting the workbook, in reference to his previous comments:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’d really like to see the results after a workbook-doin’. When you do that, try to forget all of this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I read the book twice, once just reading and the second time while taking notes about what I thought my areas and categories should look like. I started by creating a new directory in my iCloud Drive, created folders, then used &lt;a href=&quot;http://mama.indstate.edu/users/ice/tree/&quot;&gt;tree&lt;/a&gt; to see the folder structure in plain text:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;tree &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# -L 3 for how many levels deep&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# -d for directories only&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;├── 00-09 System&lt;br /&gt;│   ├── 00 Index&lt;br /&gt;│   │   └── 00.01 Index Files&lt;br /&gt;│   ├── 01 Exported Data&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# ...and so on&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I even printed out the worksheets from the back of the book as suggested by Johnny. I found the process really helpful to actually write down with pen and paper rather than into Obsidian or some other note taking app.&lt;/p&gt;
&lt;h3&gt;The Index&lt;/h3&gt;
&lt;p&gt;Before reading the book I didn&#39;t really understand the need for &lt;a href=&quot;https://johnnydecimal.com/10-19-concepts/11-core/11.05-the-index/&quot;&gt;the index&lt;/a&gt;. I get it now. The index is the source of truth for the location of items &lt;strong&gt;and&lt;/strong&gt; any additional notes or tasks related to the item. The index is a list of all of your JD IDs stored in some kind of note app, in my case Obsidian. After watching the video on the index, I realised that the part that would be useful to me was adding notes &lt;em&gt;about&lt;/em&gt; the files in my IDs. So each ID has a corresponding note. For example, I have a folder called &lt;code&gt;30-39 Resources/30 Fonts/30.02 Media Fonts&lt;/code&gt; and in my index Obsidian vault I have a note called &lt;code&gt;30.02 Media Fonts.md&lt;/code&gt;. This note contains the following link to &lt;a href=&quot;https://www.fontspace.com/london-tube-font-f2717&quot;&gt;the source&lt;/a&gt; of the &lt;code&gt;London Tube.otf&lt;/code&gt; font:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;London Tube Font: https://www.fontspace.com/london-tube-font-f2717&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I have found being able to add additional notes about a certain items really helpful. In the past I would have the files for something like applying for a mortgage in Finder and then a separate note in Obsidian with things like dates and expected timelines but those two things didn&#39;t know anything about each other. Using the index links those things together: if I need to find out information about applying for the mortgage, I open up &lt;code&gt;11.04 Mortgage.md&lt;/code&gt; and can see any notes and tasks that need to be done. And based on the ID I know that it it&#39;s stored in &lt;code&gt;10-19 Family/11 Finance/11.04 Mortgage&lt;/code&gt;. The index is also the place to start when a new project or file doesn&#39;t have a home.&lt;/p&gt;
&lt;p&gt;As a slight aside and a little outside the spirit of the deliberate nature of the JD system, I didn&#39;t actually create the notes in Obsidian until I was mostly done with the folders and files themselves. I built this little script to make the files for me instead:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/path/to/obsidian/vault&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# put a list of folders names here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token string&quot;&gt;&quot;50.01 Audio Books&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token string&quot;&gt;&quot;50.02 Comics&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token string&quot;&gt;&quot;50.03 Ebooks&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token for-or-select variable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${files&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;@&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;}&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;touch&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$output&lt;/span&gt;/&lt;span class=&quot;token variable&quot;&gt;$f&lt;/span&gt;.md&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After reading the workbook for the second time and thinking some more about my structure, this is where it&#39;s at as of today:&lt;/p&gt;
&lt;details&gt;
	&lt;summary&gt;JD System Structure&lt;/summary&gt;
	&lt;pre&gt;00-09 System
| 00 Index
│ ├── 00.01 Index Files
| 01 Exported Data
│ ├── 01.01 Twitter
│ ├── 01.02 Tumblr
│ ├── 01.03 Instagram
│ ├── 01.04 Mastodon
│ ├── 01.05 Reddit
│ ├── 01.06 Project Databases
│ ├── 01.07 Other
│ ├── 01.08 TwitPic
| 09 Archive
│ ├── 09.01 Archive
│ ├── 09.02 Camera Uploads
│ ├── 09.03 DevsDoDesign
│ ├── 09.04 Freelance
│ ├── 09.05 Just Delete Me (JDM)
│ ├── 09.06 Personal Sites
│ ├── 09.07 Wordpress Themes
│ ├── 09.08 College
│ ├── 09.09 Uni
│ ├── 09.10 School
│ ├── 09.11 Talks
│ ├── 09.12 Artwork
10-19 Home and Family
| 10 Products
│ ├── 10.01 Washing Machine
│ ├── 10.02 Dishwasher
│ ├── 10.03 Freezer
│ ├── 10.04 Oven
│ ├── 10.05 Microwave
│ ├── 10.06 TV
│ ├── 10.07 Electronics
| 11 Finance
│ ├── 11.01 Mortgage
│ ├── 11.02 Insurance
│ ├── 11.03 Credit Cards
│ ├── 11.04 Loans
│ ├── 11.05 Monzo Pots
| 12 Building Work
│ ├── 12.01 Floorplans and Layouts
│ ├── 12.02 Photos
│ ├── 12.03 Kitchen
│ ├── 12.04 Utility Room
│ ├── 12.05 Bathroom
| 13 Purchases
│ ├── 13.01 123 House Street
│ ├── 13.02 456 House Road
| 14 Legal
│ ├── 14.01 Work
│ ├── 14.02 Deaths
│ ├── 14.03 Deed Poll
│ ├── 14.04 Payslips
│ ├── 14.09 [redacted]
20-29 Podcasts
| 20 Ruminate
│ ├── 20.00 Recordings
│ ├── 20.01 Episodes
│ ├── 20.02 Artwork
│ ├── 20.03 Sounds
│ ├── 20.04 Shownotes
│ ├── 20.05 Episode Art
| 21 We Got Family
│ ├── 21.00 Recordings
│ ├── 21.01 Episodes
│ ├── 21.02 Artwork
│ ├── 21.03 Sounds
│ ├── 21.04 Shownotes
│ ├── 21.05 Episode Art
| 22 Follow Out
│ ├── 22.01 Appearances
│ ├── 22.02 Mentions
│ ├── 22.03 Fan Art
| 23 Show Archives
│ ├── 23.01 The Ricky Gervais Show
│ ├── 23.02 Bionic and Bonanza
│ ├── 23.03 Cooking With Brett and Myke
│ ├── 23.03 Futurama
│ ├── 23.04 Hello Internet
30-39 Resources
| 30 Fonts
│ ├── 30.01 Coding
│ ├── 30.02 Media
│ ├── 30.03 Symbols
│ ├── 30.04 Others
| 31 Icons
│ ├── 31.01 General Use
│ ├── 31.02 Niche
| 32 Music and Sounds
│ ├── 32.01 Clips
│ ├── 32.02 Royalty Free Music
│ ├── 32.03 Blahaj
| 33 Books
│ ├── 33.01 Audio Books
│ ├── 33.02 Comics
│ ├── 33.03 Dev
│ ├── 33.04 eBooks
│ ├── 33.05 Lego
40-49 Hobbies
| 40 Games
│ ├── 40.01 Screenshots
│ ├── 40.02 Manuals
│ ├── 40.03 ROMs
| 41 Lego
│ ├── 41.01 Manuals
│ ├── 41.02 Photos
│ ├── 41.03 MOC
│ ├── 41.04 Comic Con Exclusives
| 42 Raspberry Pi
│ ├── 42.01 PiSight
│ ├── 42.02 Now Playing Pi
| 43 Fundraising
│ ├── 43.01 St Jude 2023
| 44 Streaming
│ ├── 44.01 Backgrounds
50-59 Media
| 50 Tattoo Ideas
│ ├── 50.01 Inbox
│ ├── 50.02 Arm Tattoo
│ ├── 50.03 SleeveStar
│ ├── 50.04 CSS HTML Tattoo
| 51 Memes
│ ├── 51.01 Mine
│ ├── 51.02 Gifs
| 52 Profile
│ ├── 52.01 Avatars
│ ├── 52.02 Headers
│ ├── 52.03 Memoji
│ ├── 52.04 RK Logo
| 53 Wallpapers
│ ├── 53.01 Desktop
│ ├── 53.02 Phone
│ ├── 53.03 iPad
| 54 Media Screenshots
│ ├── 54.01 Comics
│ ├── 54.02 TV
│ ├── 54.03 Back to the Future Posters
│ ├── 54.04 Cornetto Trilogy Posters
| 55 Music
│ ├── 55.01 Album Covers
│ ├── 55.02 Linkin Park Demos
│ ├── 55.03 Bowling for Soup Demos
│ ├── 55.04 Albums
| 56 Photos and Videos
│ ├── 56.00 Camera Uploads
│ ├── 56.01 By Year
│ ├── 56.02 [redacted]
│ ├── 56.03 Paper Drawings
│ ├── 56.04 Various
│ ├── 56.06 Personal Videos
│ ├── 56.07 YouTube Videos
│ ├── 56.08 Wedding Photo Booth
	&lt;/pre&gt;
&lt;/details&gt;
&lt;h3&gt;Using JD Elsewhere&lt;/h3&gt;
&lt;p&gt;One of the things I found really useful was the idea that by using numbers for sorting folders instead of names, &lt;em&gt;things don&#39;t move&lt;/em&gt;. If I renamed &lt;code&gt;30.02 Garden Patio&lt;/code&gt; to &lt;code&gt;30.02 Garden Decking&lt;/code&gt; the folder &lt;em&gt;stays in the same place&lt;/em&gt;. This seems obvious in hindsight but I found this so useful I incorporated it into my main Obsidian vault. Previously I had three folders called &lt;code&gt;Ideas&lt;/code&gt;, &lt;code&gt;Posts&lt;/code&gt;, and &lt;code&gt;Projects&lt;/code&gt; as well as some more time-specific ones. Now, these are &lt;code&gt;00.01 Ideas&lt;/code&gt;, &lt;code&gt;00.02 Posts&lt;/code&gt;, and &lt;code&gt;00.03 Projects&lt;/code&gt;. Another very obvious-in-hindsight idea came from Johnny&#39;s index video: sorting files by last modified instead of by name. I&#39;ve found this to be way easier to be able to jump in and update a note quickly when I have an idea.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I think systems like this tend to either work for a person or don&#39;t work at all, there&#39;s no middle ground. That&#39;s not the case for the JD system. I believe even if it doesn&#39;t work as a whole for someone (like John) there are loads of good ideas in here that can be applied in a lot of different cases. It &lt;em&gt;has&lt;/em&gt; worked very well for me and I&#39;ve been able to find files I&#39;m looking for so much quicker than I could before.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://johnnydecimal.com&quot;&gt;Johnny Decimal website&lt;/a&gt; to read more and if you like it, &lt;a href=&quot;https://johnnydecimal.com/10-19-concepts/14-build-your-system/14.02-the-decimal-workbook/&quot;&gt;check out the workbook&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>I finally found some time to dig into the Johnny Decimal system and reorganise all my files</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Please, Expose your RSS</title>
    <link href="https://rknight.me/blog/please-expose-your-rss/"/>
    <updated>2023-11-06T13:11:20Z</updated>
    <id>https://rknight.me/please-expose-your-rss/</id>
    <content type="html">&lt;p&gt;Earlier this week I had a need to manually find a bunch of people&#39;s RSS feed links. It seemed simple enough: go to their website and look for an RSS/Subscribe link but I was surprised to find that a lot of people don&#39;t have a link anywhere to their feed.&lt;/p&gt;
&lt;p&gt;Even if people only ever add your website into their feed reader and let the app find the RSS feed (see below for more info on this), showing an RSS link reminds people that RSS exists, a win for the open web.&lt;/p&gt;
&lt;p&gt;My second step when finding a link failed was to use this handy JS snippet from my &lt;a href=&quot;https://podduration.rknight.me&quot;&gt;Podcast Duration project&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;link&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; l&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;application/rss+xml&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;href&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This looks for a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag on the website that has a type of &lt;code&gt;application/rss+xml&lt;/code&gt;. This is called RSS auto-discovery and is a standard way to expose RSS feeds to help &lt;a href=&quot;https://www.rssboard.org/rss-autodiscovery&quot;&gt;browsers and other software to automatically find a site&#39;s RSS feed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Like the standard link, a lot of sites were also missing this. This is (at least as a first step) what feed reeders like &lt;a href=&quot;https://netnewswire.com&quot;&gt;NetNewsWire&lt;/a&gt; will use to automatically find a feed when you paste in a URL. If you have an RSS feed, you should have the following in the &lt;code&gt;head&lt;/code&gt; of your website:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My Cool Website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/feed.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- use application/atom+xml for an atom feed --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/atom+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My Cool Website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/atom.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have multiple feeds, you can have more than one &lt;code&gt;link&lt;/code&gt; tag that links to those feeds as well. For example, say you have a &lt;a href=&quot;https://www.jsonfeed.org&quot;&gt;JSON feed&lt;/a&gt; and a podcast feed you want to link to:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Website RSS feed --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My Cool Website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/feed.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Website JSON feed --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/json&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My Cool Website but JSON&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/feed.json&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Podcast RSS feed --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;alternate&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;application/rss+xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;My Cool Podcast&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/podcast.xml&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Please, expose your RSS.&lt;/p&gt;
&lt;p&gt;Update 2023-12-09 via &lt;a href=&quot;https://bne.social/@james/111545470669286673&quot;&gt;James&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;if you&#39;re going to add an RSS button, please ensure it looks like an RSS button and is in RSS orange&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is an excellent idea and I have done so here.&lt;/p&gt;
</content>
    <summary>I noticed a lot of people don't have a link to their RSS feeds on their sites or have the correct metadata for auto-discovery</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>App Defaults</title>
    <link href="https://rknight.me/blog/app-defaults/"/>
    <updated>2023-11-03T17:31:10Z</updated>
    <id>https://rknight.me/app-defaults/</id>
    <content type="html">&lt;p&gt;Inspired by &lt;a href=&quot;https://listen.hemisphericviews.com/097&quot;&gt;Hemispheric Views 097 - Duel of the Defaults!&lt;/a&gt; and this &lt;a href=&quot;https://gabz.blog/2023/11/my-defaults&quot;&gt;post by Gabz&lt;/a&gt; herein lies all the apps I use in the various categories as written by Andrew:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;📨 Mail Client&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Mail.app&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📮 Mail Server&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;iCloud with custom domain&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📝 Notes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Notes.app, Obsidian&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;✅ To-Do&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Reminders&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📷 iPhone Photo Shooting&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;iOS Camera&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🟦 Photo Management&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Photos.app&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📆 Calendar&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Fantastical&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📁 Cloud File Storage&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;iCloud Drive&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📖 RSS&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;NetNewsWire&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🙍🏻‍♂️ Contacts&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Contacts.app&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🌐 Browser&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Safari, Chrome for development/work&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;💬 Chat&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Discord&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🔖 Bookmarks&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://intersect.rknight.me&quot;&gt;The Intersect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📑 Read It Later&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Omnivore&lt;/li&gt;
&lt;li&gt;Score: 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📜 Word Processing&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Sublime Text&lt;/li&gt;
&lt;li&gt;Score: 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📈 Spreadsheets&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Numbers&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📊 Presentations&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Keynote&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🛒 Shopping Lists&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Reminders&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🍴 Meal Planning&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;n/a&lt;/li&gt;
&lt;li&gt;Score: 0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;💰 Budgeting and Personal Finance&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;A spreadsheet&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;📰 News&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Mastodon, BBC News&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🎵 Music&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Apple Music&lt;/li&gt;
&lt;li&gt;Score: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🎤 Podcasts&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Overcast&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🔐 Password Management&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;1Password&lt;/li&gt;
&lt;li&gt;Score: 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🔔 &lt;a href=&quot;https://en.wikipedia.org/wiki/Hard_Quiz&quot;&gt;Hard Quiz&lt;/a&gt; Special Topic Interlude (Something for  Which I’d Be the Subject Matter Expert in the Room)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Back to the Future&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Final score: 37&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://defaults.rknight.me/&quot;&gt;Read more app default posts&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>All of the apps I use as per the categories defined by Hemispheric Views episode 097 - Duel of the Defaults!</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>St Jude 2023</title>
    <link href="https://rknight.me/blog/st-jude-2023-final-numbers/"/>
    <updated>2023-10-07T06:19:47Z</updated>
    <id>https://rknight.me/st-jude-2023-final-numbers/</id>
    <content type="html">&lt;p&gt;It&#39;s September 37th and the &lt;a href=&quot;https://512pixels.net/2023/10/775375-54/&quot;&gt;Relay for St Jude campaign&lt;/a&gt; has closed. They raised $774,262.53, putting Relay at $2.98m lifetime raised! Our St Jude sub-campaign raised $12,590.57 and sent out 106 sticker packs to 15 different countries. This is a far cry from &lt;a href=&quot;https://rknight.me/st-jude-2023/&quot;&gt;my initial goal of $250&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I want to thank everyone who donated but I want to call out some people specifically as well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://neatnik.net&quot;&gt;Adam&lt;/a&gt; for donating half of &lt;a href=&quot;https://omglol.news/2023/10/01/st-jude-fundraiser-report&quot;&gt;omg.lol&#39;s profits&lt;/a&gt; for the entire month - &lt;a href=&quot;https://prami.paste.lol/2023-st-jude-fundraiser&quot;&gt;$3309&lt;/a&gt;! If you want to thank him, you should &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;sign up for omg.lol&lt;/a&gt; - it&#39;s a fun community&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://512pixels.net&quot;&gt;Stephen&lt;/a&gt; for buying the &lt;a href=&quot;https://coinme.dad&quot;&gt;Coin Daddy domain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.klmatthews.com&quot;&gt;Kate&lt;/a&gt; for always finding bugs the second I pushed a new change. Also for the idea for &lt;a href=&quot;https://coinme.dad&quot;&gt;Coin Me, Daddy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tildy.dev&quot;&gt;Ben&lt;/a&gt; for helping with the API so I could build all the stupid websites for the campaign (see below)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/c/IanOfEarth&quot;&gt;Ian&lt;/a&gt;, &lt;a href=&quot;http://gdovin.net&quot;&gt;Mike&lt;/a&gt; and all the other dollar daddies&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zmknox.com&quot;&gt;Zach&lt;/a&gt; for creating the Donation Daddy logo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/donation-daddy-logo.png&quot; alt=&quot;Donation Daddy logo&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I also got myself a couple of nice rewards. &lt;a href=&quot;http://jdburch.com&quot;&gt;JD&lt;/a&gt; mowed my name into a lawn and I will be getting a Jony Cube sticker from &lt;a href=&quot;https://www.peerreviewed.io&quot;&gt;Matt&lt;/a&gt;. We hit our first milestone which meant I had to watch &lt;a href=&quot;https://www.imdb.com/title/tt2933474/&quot;&gt;Superfast!&lt;/a&gt; - you can listen to the &lt;a href=&quot;https://wegot.family/5/&quot;&gt;episode of We Got Family about it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The campaign this year led me to make four different websites to help with donations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://septembed.rknight.me&quot;&gt;Septembed&lt;/a&gt; - A script for embedding a campaign on your website. This was the start of the japes. Very proud of the name as well.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://deskmat.help&quot;&gt;Desk Mat Help&lt;/a&gt; - The precursor to Coin Me, Daddy this site lists all the campaigns that were close to $250 to get a desk mat&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://coinme.dad&quot;&gt;Coin Me, Daddy&lt;/a&gt; - The most popular of the sites, this one was an idea from Kate. It shows all campaigns that have yet to raise one dollar to get a coin. There are &lt;em&gt;so many&lt;/em&gt; donations with the title &amp;quot;Dollar Daddy&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://donationtreats.rknight.me&quot;&gt;Donation Treats&lt;/a&gt; - Lists all the rewards you can get for all the available campaigns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Initially, these were all separate websites with &lt;em&gt;very&lt;/em&gt; similar code. Towards the end of the month I merged these into one single codebase. This should make it a lot easier next year when I&#39;m sure I&#39;ll think of some other site to do.&lt;/p&gt;
</content>
    <summary>A look at how much we raised in September for St Jude as well as all the japes that occurred</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Add Full Screen Artwork to Your Podcast</title>
    <link href="https://rknight.me/blog/add-full-screen-artwork-to-your-podcast/"/>
    <updated>2023-09-22T12:18:12Z</updated>
    <id>https://rknight.me/add-full-screen-artwork-to-your-podcast/</id>
    <content type="html">&lt;p&gt;tl;dr: You can&#39;t set full screen artwork without being featured by Apple.&lt;/p&gt;
&lt;p&gt;In iOS17, the Apple Podcasts app has (for some shows) fancy new full screen artwork but I noticed that &lt;a href=&quot;https://ruminatepodcast.com&quot;&gt;my&lt;/a&gt; &lt;a href=&quot;https://wegot.family&quot;&gt;shows&lt;/a&gt; don&#39;t.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/full-screen-artwork.png&quot; alt=&quot;We Got Family artwork vs Connected in Apple Podcasts app&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After some hunting around, some &lt;a href=&quot;https://social.lol/@robb/111105291859489382&quot;&gt;tooting&lt;/a&gt;, and messaging &lt;a href=&quot;https://mastodon.macstories.net/@johnvoorhees&quot;&gt;John&lt;/a&gt;, I came across &lt;a href=&quot;https://podcasters.apple.com/support/866-promotional-artwork&quot;&gt;this page&lt;/a&gt; that outlines the full screen artwork. It explains the sizes for hero images, channel covers, and full page show art. It even has photoshop templates. My podcasts are unlikely to be featured but I figured it was worth a shot.&lt;/p&gt;
&lt;p&gt;Once I made the art and hit the submit button, it turns out you can &lt;em&gt;only&lt;/em&gt; submit hero images and if Apple then deems my show worthy enough for a feature will they then request the full page art.&lt;/p&gt;
&lt;p&gt;This feels really shitty that you have to get featured just to get nicer artwork in the Apple Podcasts app which is far and away the most popular podcast app.&lt;/p&gt;
</content>
    <summary>How (not) to add full screen artwork to the Apple Podcasts app for your podcast</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>I&#39;m (Not) Building a Podcast Host</title>
    <link href="https://rknight.me/blog/im-not-building-a-podcast-host/"/>
    <updated>2023-09-20T11:32:33Z</updated>
    <id>https://rknight.me/im-not-building-a-podcast-host/</id>
    <content type="html">&lt;p&gt;Late last year I moved &lt;a href=&quot;https://ruminatepodcast.com&quot;&gt;Ruminate&lt;/a&gt; from Simplecast to it&#39;s &lt;a href=&quot;https://rknight.me/bulding-podcast-site-eleventy/&quot;&gt;own site built with Eleventy&lt;/a&gt; for a two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I wanted full control over how the site looked&lt;/li&gt;
&lt;li&gt;Simplecast is $15 a month and that&#39;s a lot for a show that makes no money&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since then, I&#39;ve successfully used that same Eleventy site to build the site for &lt;a href=&quot;https://wegot.family&quot;&gt;We Got Family&lt;/a&gt;, my Fast and Furious podcast. Having both my podcasts hosted myself has been great. I can automate uploads, extract the title and description from the file instead of having to copy and paste it into a CMS, and it costs me &lt;em&gt;basically&lt;/em&gt; nothing.&lt;/p&gt;
&lt;p&gt;One thing I am missing since I moved away from Simplecast is listener/download numbers. This is, in my opinion, the core selling feature of a dedicated podcast host. Each host does the calculations differently (and they all keep their methods secret) but they do all seem to at least attempt to follow this &lt;em&gt;thrilling&lt;/em&gt; document titled &lt;a href=&quot;https://iabtechlab.com/wp-content/uploads/2021/03/PodcastMeasurement_v2.1.pdf&quot;&gt;&amp;quot;Podcast Measurement Technical Guidelines Version 2.1&amp;quot;&lt;/a&gt;. There&#39;s some boring stuff in there about the poor advertisers who can&#39;t get the data they want and some talk about a new, yet-to-happen reporting feature from some apps but the part I care about is counting listens. The hard part of calculating downloads is parsing server logs: if someone listens in a browser, logs will show multiple partial downloads for that file so that should be counted as one listen.&lt;/p&gt;
&lt;p&gt;Thankfully, &lt;a href=&quot;https://docs.bunny.net/docs/cdn-log-format&quot;&gt;Bunny has a very nice log format&lt;/a&gt; that is easy enough to parse. A quick-and-dirty solution me and &lt;a href=&quot;https://neatnik.net&quot;&gt;Adam&lt;/a&gt; came up with for counting a single listen is if the IP address, user agent, and file are the same within the same 24 hour period, count that as one listen. This isn&#39;t perfect by any means, but will be good enough for what I want.&lt;/p&gt;
&lt;p&gt;This attempt at generating listen stats was partially research into an idea I&#39;ve had running around in my head for at least a year:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can you build a podcast host for smaller podcasts like mine for, say, $20 a year?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The accounts, uploading files, hosting websites, is all easy enough but when you consider download costs the answer, after going over some calculations with &lt;a href=&quot;https://zoeaubert.me&quot;&gt;Zoe&lt;/a&gt;, is no. The file egress costs (the cost of downloading the files from a CDN) is too high even for a small show.&lt;/p&gt;
&lt;p&gt;Update: I got the calculations wrong here for Bunny&#39;s pricing so it &lt;em&gt;might&lt;/em&gt; still be viable as a product although the margins are still tight.&lt;/p&gt;
&lt;p&gt;As an example, if a show has a 30mb episode and that show gets 500 downloads, that&#39;s ~15gb of egress. On &lt;a href=&quot;https://bunny.net&quot;&gt;BunnyCDN&lt;/a&gt; that would cost somewhere in the region of $1.50. AWS S3 is about the same. Assuming one episode a month (unlikely), that&#39;s pretty close to $20 a year.&lt;/p&gt;
&lt;p&gt;These calculations don&#39;t even take into account older episodes getting more downloads over time (they definitely will) or the show growing over time (it likely will). What about if someone decides to &lt;a href=&quot;https://rknight.me/three-years-of-hemispheric-views-feedback/&quot;&gt;listen to all 74 episodes of a show at once&lt;/a&gt; leading to 2-3gb of downloads in one go?&lt;/p&gt;
&lt;p&gt;There is an argument to be made that variable pricing might work: pay $X per year then monthly pay whatever the CDN cost for your show is but this feels counter-intuitive to building a simple podcast host. I could charge a similar amount as some of the existing services but then I&#39;m not bringing anything new to the table.&lt;/p&gt;
&lt;p&gt;Ultimately every solution to the cost problem goes against my initial idea. Instead, I&#39;m going to focus some time on making my Eleventy podcast site more usable for other people to deploy their own podcasts.&lt;/p&gt;
</content>
    <summary>Why I considered building a podcast host until I did the maths on the costs</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Fundraising for St Jude</title>
    <link href="https://rknight.me/blog/st-jude-2023/"/>
    <updated>2023-08-28T15:28:07Z</updated>
    <id>https://rknight.me/st-jude-2023/</id>
    <content type="html">&lt;p&gt;This year is &lt;a href=&quot;https://relay.experience.stjude.org&quot;&gt;Relay FM&#39;s 5th annual fundraiser&lt;/a&gt; for &lt;a href=&quot;https://www.stjude.org&quot;&gt;St Jude Children&#39;s Research Hospital&lt;/a&gt;. If you don&#39;t know St Jude:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The mission of St. Jude Children’s Research Hospital is to advance cures, and means of prevention, for pediatric catastrophic diseases through research and treatment. Consistent with the vision of our founder Danny Thomas, no child is denied treatment based on race, religion or a family’s ability to pay.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Their goal this year is to hit $2.5 &lt;em&gt;million&lt;/em&gt; lifetime donations. As part of that individuals, like me, can set up their own campaign which is &lt;a href=&quot;https://tiltify.com/@rknightuk/stjude2023&quot;&gt;exactly what I&#39;ve done&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I set a milestone of $150 at which point I will watch all 99 minutes of &lt;a href=&quot;https://www.imdb.com/title/tt2933474/&quot;&gt;Superfast!&lt;/a&gt;, a Fast and Furious parody movie which I definitely do not want to watch in any way. That milestone has been hit already so keep an eye out on the &lt;a href=&quot;https://wegot.family&quot;&gt;We Got Family podcast&lt;/a&gt; feed for an episode about it.&lt;/p&gt;
&lt;p&gt;My original goal was $250 but &lt;a href=&quot;https://adam.omg.lol&quot;&gt;Adam of omg.lol&lt;/a&gt; kindly donated the entire amount in one go. Then he went one step further and commited to donating 50% of profits from omg.lol for the &lt;em&gt;entire month&lt;/em&gt;. So if you&#39;re an omg.lol member (or you &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;sign up&lt;/a&gt; for a new account) and you renew your address you&#39;re donating to the campaign.&lt;/p&gt;
&lt;p&gt;We also have two omg.lol codes up for grabs: anyone who donates $10 or more will be entered to win a five year code and whoever donates the most will win an ultra-rare lifetime code.&lt;/p&gt;
&lt;p&gt;I have moved the goal to &lt;s&gt;$3000&lt;/s&gt; &lt;s&gt;$5000&lt;/s&gt; $10000 and as generous as Adam is being, I don&#39;t want it to all come from him so if you can donate anything, even a dollar, it all helps towards an amazing cause.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://tiltify.com/@rknightuk/stjude2023&quot;&gt;Donate to the campaign here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://rknight.me/st-jude-2023-final-numbers/&quot;&gt;Update post&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>I'm fundraising for St Jude this September as part of Relay's campaign</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>It’s Better in the App and Other Lies</title>
    <link href="https://rknight.me/blog/its-better-in-the-app-and-other-lies/"/>
    <updated>2023-08-22T10:00:00Z</updated>
    <id>https://rknight.me/its-better-in-the-app-and-other-lies/</id>
    <content type="html">&lt;p&gt;I&#39;ve seen a few conversations on Mastodon the last week or so about why we have so many apps rather than decent mobile websites and why we&#39;re shown &amp;quot;things are better in the app!&amp;quot; banners (and who&#39;s fault is that website?!). I&#39;ve been thinking about this on and off for a &lt;a href=&quot;https://social.lol/@robb/110588163612894889&quot;&gt;long time&lt;/a&gt;. I don&#39;t like that Apple hold all the keys to distrubting an app and I&#39;m a big fan of the open web. I do beleive there are good reasons for native apps in some cases (specifically native features not available in browsers) but not &lt;em&gt;everything&lt;/em&gt; needs an app. I think there are three different reasons this is happening so much.&lt;/p&gt;
&lt;h3&gt;Gobbling data&lt;/h3&gt;
&lt;p&gt;This is the obvious one. It&#39;s a lot easier to collect data from a native app than it is from a website. On an app I have very little control over what requests are made, blocking ads, that kind of thing. So of course companies want to use apps to collect this data.&lt;/p&gt;
&lt;h3&gt;Making money&lt;/h3&gt;
&lt;p&gt;This one applies more to indie developers than it does to big companies but I&#39;m certain people are more willing to pay for an app than access to a website. As an example, &lt;a href=&quot;https://www.caseyliss.com/2023/8/7/callsheet&quot;&gt;Callsheet&lt;/a&gt; &lt;em&gt;could&lt;/em&gt; be a website but would people pay $9 a year for a website? I don&#39;t think they would.&lt;/p&gt;
&lt;h3&gt;People want apps&lt;/h3&gt;
&lt;p&gt;This last one is at least a little bit &lt;a href=&quot;https://www.youtube.com/watch?v=szrsfeyLzyg&quot;&gt;on Apple with their &amp;quot;there&#39;s an app for that&amp;quot; ad&lt;/a&gt;. A few years ago I ordered a washing machine from &lt;a href=&quot;https://ao.com&quot;&gt;AO&lt;/a&gt; and if I was on mobile the only way to track my order was to download their brand new tracking app. I contacted them about this and I was told they made the app because lots of customers were asking for it.&lt;/p&gt;
&lt;p&gt;Just think about that for a second: people want to download an app just to track deliveries of their white goods, something which most people order at most once a year. This is bonkers to me. They did eventually fix the deep link so you could track from the website on mobile.&lt;/p&gt;
&lt;p&gt;In some instances it&#39;s become impossible to do certain things on mobile because the app doesn&#39;t support the feature (for example, buying ebooks on Amazon) but I never get redirected back out&lt;/p&gt;
</content>
    <summary>Some thoughts on why there are so many apps when when in a lot of cases a good old website will do</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Just Delete Me: Ten Years Later</title>
    <link href="https://rknight.me/blog/just-delete-me-ten-years-later/"/>
    <updated>2023-08-18T12:44:06Z</updated>
    <id>https://rknight.me/just-delete-me-ten-years-later/</id>
    <content type="html">&lt;p&gt;Ten years ago &lt;a href=&quot;https://www.edpoole.me/&quot;&gt;Ed Poole&lt;/a&gt; and I &lt;a href=&quot;https://hellsite.rknight.me/369368988762906626/&quot;&gt;launched Just Delete Me&lt;/a&gt;. Just Delete Me, as I &lt;a href=&quot;https://rknight.me/just-delete-me/&quot;&gt;described it at the time&lt;/a&gt;, was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a directory of urls to delete your account from web services&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wrote three blog posts in first ten days which you can read here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/just-delete-me/&quot;&gt;Just Delete Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/24-hours-of-just-delete-me/&quot;&gt;24 Hours of Just Delete Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rknight.me/just-delete-me-one-million-page-views/&quot;&gt;JustDelete.me: One Million Page Views&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I recall we made it over the course of one Sunday afternoon and launched it the day after. The first day it had a decent amount of visitors (~3000) and then seemingly overnight it got picked up everywhere, including some huge sites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mashable.com/archive/justdelete-me&quot;&gt;Mashable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.wired.com/2013/08/just-delete-me/&quot;&gt;Wired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://slate.com/technology/2013/08/just-delete-me-how-to-delete-your-account-on-amazon-netflix-skype-et-al.html&quot;&gt;Slate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cnet.com/culture/how-to-delete-your-web-accounts-with-justdelete-me/&quot;&gt;CNET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://neil-gaiman.tumblr.com/post/59537088319/futurejournalismproject-delete-yourself-from&quot;&gt;Neil Gaiman&lt;/a&gt; reblogged it on his Tumblr&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We spent the next week or two frantically merging pull requests for new sites, going from the 16 we started with to over 100 in a very short space of time. We hit one million page views within nine days of launching and I was interviewed by the Wall Street Journal and a BBC radio station (I don&#39;t remember which one nor do I have the recording).&lt;/p&gt;
&lt;p&gt;A few days after this I added a service to the site and marked it as difficult to delete, then tweeted about it. Within hours I got an email from their CEO (I won&#39;t name him but I will say maybe he had a day phone and a night phone) who was annoyed we had marked them as such and wanted to know what he could do to change that. To the best of my knowledge, they never actually did anything about it.&lt;/p&gt;
&lt;p&gt;The only way to contribute to the site was to open a pull request on Github which wasn&#39;t great for non-developers so I set up a Google form to collect suggestions and links. We got so many pull requests I completely forgot about the form for a couple of months. When I did remember about it and logged in to have a look I was genuinely surprised to see there was thousands of submissions but most of them weren&#39;t suggestions for sites. There was hundreds of submissions that included peoples usernames and passwords for various sites (&lt;em&gt;loads&lt;/em&gt; of Facebook ones) because they thought the form was a way to get &lt;em&gt;me&lt;/em&gt; to delete their accounts. I promptly deleted that form and the associated sheet, I did not want to be responsible for that data.&lt;/p&gt;
&lt;p&gt;Thanks to contributors the site eventually had translations into 20 or so languages and grew to have 476 sites listed at the time I sold it. At some stage in the first few months we put Google ads on the site (gross) and it paid my, admittedly small, rent for the next 2 years (not gross).&lt;/p&gt;
&lt;p&gt;Unfortunately the person I sold it to let it go stagnant (turns out they just wanted the domain) but someone forked the project, put it up on a new domain (&lt;a href=&quot;https://justdeleteme.xyz/&quot;&gt;https://justdeleteme.xyz/&lt;/a&gt;) and continued adding sites. It now has over 1500 sites and services listed. This forked project also spun off two other projects based on the same premise: &lt;a href=&quot;https://justgetmydata.com&quot;&gt;Just Get My Data&lt;/a&gt; and &lt;a href=&quot;https://justwhatsthedata.github.io/&quot;&gt;Just What&#39;s The Data&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The original version of the site was built with &lt;s&gt;hopes, dreams, and duct tape&lt;/s&gt; a makefile and a whole lot of json files. If I was going to make this exact site today it would be significantly easier with &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; data files and I could probably avoid a lot of the merge conflicts we had in the early days with a better data structure. I also definitely wouldn&#39;t put Google ads on the site.&lt;/p&gt;
&lt;p&gt;Just Delete Me is still my most popular project at least in terms of page views, although the &lt;a href=&quot;https://potimages.rknight.me/&quot;&gt;Monzo Pot Image Generator&lt;/a&gt; has definitely been more consistent in terms of visits (and ~55k images generated).&lt;/p&gt;
&lt;p&gt;Here&#39;s every link I collected about the site back then. Given it&#39;s been 10 years I&#39;m guessing a lot of these are dead now.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://time.com/3054279/50-best-websites-2014/&quot;&gt;50 Best Websites 2014&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://live.wsj.com/video/tired-of-being-on-facebook-just-delete-me/39305F59-6E77-4BC8-B3F3-5DDE9D69347A.html#!39305F59-6E77-4BC8-B3F3-5DDE9D69347A&quot;&gt;Video - Just Delete Me -- New Website Helps Users Delete Personal Info From Sites - WSJ.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.theage.com.au/digital-life/consumer-security/welcome-to-the-counterrevolution-20140308-34e1v.html&quot;&gt;Welcome to the counter-revolution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://readwrite.com/2014/02/05/how-to-remove-yourself-from-the-internet#awesm=~ov27CdupU0RRa3&quot;&gt;How To Remove Yourself From The Internet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zapier.com/blog/productivity-apps-2013/&quot;&gt;10 Can&#39;t Miss Productivity Apps Released in 2013&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bgr.com/2013/12/17/remove-internet-accounts-just-delete-me/&quot;&gt;You can remove yourself from the Internet one website at a time with this&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.intego.com/mac-security-blog/justdelete-me-is-an-eye-opener/&quot;&gt;JustDelete.Me is an Eye-Opener&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ebuyer.com/blog/2013/12/how-to-disappear-completely-online/&quot;&gt;How to disappear completely…Online&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.portsmouth.co.uk/news/education/university-of-portsmouth-students-deleting-website-proves-popular-1-5491597&quot;&gt;University of Portsmouth students deleting website proves popular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.smashingmagazine.com/smashing-newsletter-issue-97/&quot;&gt;Smashing Newsletter: Issue #97&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.onemorethingstudio.com/blog/2013/11/18/bonnes-pioches-14-ux-float-label-pattern-justdeleteme/&quot;&gt;Good Picks # 14: UX Design - Float Label Pattern - JustDeleteMe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jamrelian.com/justdelete-me-delete-accounts/&quot;&gt;justdelete.me: Delete accounts &amp;amp; quit web services with ease&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.davescomputertips.com/delete-those-unwanted-online-accounts/&quot;&gt;Delete those Unwanted Online Accounts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.prdaily.com/Main/Articles/15573.aspx&quot;&gt;10 steps to building and managing your personal brand&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.clickorlando.com/news/deleting-online-trail-proves-difficult/-/1637132/22979182/-/cvnolwz/-/index.html&quot;&gt;Deleting online trail proves difficult&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.makeuseof.com/pages/best-websites&quot;&gt;Best Websites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.hover.com/blog/domain-of-the-month-november-justdelete-me/&quot;&gt;Domain of the Month, November: JustDelete.Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.bbc.co.uk/news/technology-24463390&quot;&gt;Webscape: Making exercise a game&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.forbes.com/sites/adamtanner/2013/10/02/one-easy-way-to-stop-target-and-other-companies-from-selling-your-data/&quot;&gt;One Easy Way To Stop Target And Other Companies From Selling Your Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.startribune.com/lifestyle/225069852.html&quot;&gt;Vanish from the Web with justdelete.me | Star Tribune&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.heart.co.uk/southcoast/news/local/students-create-site-deleting-old-accounts/&quot;&gt;Students Create Site For Deleting Old Accounts - Heart South Coast News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://forums.theregister.co.uk/forum/1/2013/09/13/students_embark_on_mission_to_delete_you_from_the_internet/&quot;&gt;Zuck off, Zuck: Brit duo&#39;s JustDelete.Me nukes clingy web accounts • The Register Forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.port.ac.uk/uopnews/2013/09/11/new-one-stop-shop-for-deleting-internet-accounts/&quot;&gt;New one-stop shop for deleting internet accounts | UoP News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.redmondpie.com/want-to-delete-yourself-from-the-internet-new-web-app-helps-you-do-just-that/&quot;&gt;Want To Delete Yourself From The Internet? New Web App Helps You Do Just That! | Redmond Pie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.bizjournals.com/albany/blog/socialmadness/2013/08/how-to-disappear-from-the-internet.html&quot;&gt;You can vanish from the internet, but it&#39;ll take work - Vote for the best company in Albany&#39;s business competition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://techbeat.com/2013/09/vanish-from-the-internet-with-justdelete-me/&quot;&gt;Vanish from the Internet with JustDelete.me | TechBeat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://apartments.naproperties.com/texas/grapevine/grapevine-station-apartments/news?__rmid=erase_yourself_from_the_intern-239860063.html&amp;amp;xrs=RebelMouse_tw&quot;&gt;Grapevine Texas Apartments | Grapevine Station Apartments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://iyaan.info/justdelete-me-wants-to-help-you-pull-the-plug-on-all-those-pesky-online-accounts/&quot;&gt;Justdelete.me Wants To Help You Pull The Plug On All Those Pesky Online Accounts | iyaan.info&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.repubblica.it/tecnologia/2013/08/29/news/pulire_tracce_web-65493280/?ref=fbpr&quot;&gt;JustDeleteMe, come pulire le nostre tracce sul Web - Repubblica.it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://thefluffyheads.com/techie-tony/just-delete-me&quot;&gt;Just Delete Me | The Fluffy Heads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lowecounsel.com/blog/2013/08/just-delete-me-app-lets-you-disappear-quicker&quot;&gt;Just Delete Me: An App That Lets You Disappear, Quicker | COUNSEL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.techsupportalert.com/content/how-cancel-online-accounts-easy-way.htm&quot;&gt;How to Cancel Online Accounts the Easy Way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.watchlistnews.com/2013/08/26/dt-daily-iphone-trade-in-justdelete-me-white-xbox-one/&quot;&gt;DT Daily: iPhone trade-in, justdelete.me, White Xbox One - Watch List News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.bitrebels.com/technology/just-delete-me-service-directory/&quot;&gt;Just Delete Me: Helps You Erase Your Online Presence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://technorati.com/technology/article/got-a-bunch-of-ignored-online/&quot;&gt;Got a Bunch of Ignored Online Accounts? Say Hello to JustDelete.me - Technorati Technology&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://neil-gaiman.tumblr.com/post/59537088319/futurejournalismproject-delete-yourself-from&quot;&gt;Neil Gaiman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.komando.com/coolsites/index.aspx?id=15113&quot;&gt;Easily delete unwanted online accounts - Cool Sites from The Kim Komando Radio Show® &amp;amp; Web site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.pcworld.com/article/2047632/learn-how-to-cancel-your-online-accounts.html&quot;&gt;Learn how to cancel your online accounts | PCWorld&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://domain.me/justdelete-me/&quot;&gt;JustDelete.Me: Are You Tired of Your Social Media Profile? - Domain.ME&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.crazyengineers.com/threads/justdelete-me-removes-your-web-traces-attracts-5-00-000-views-in-its-first-week.70308/&quot;&gt;JustDelete.Me Removes Your Web Traces; Attracts 5,00,000 Views In Its First Week | CrazyEngineers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://fox2now.com/2013/08/28/justdelete-me-makes-cleaning-up-your-online-identity-easy/&quot;&gt;JustDelete.Me makes cleaning up your online identity easy | FOX2now.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tumblr.thefjp.org/post/59394819304/delete-yourself-from-web-services-with-justdelete-me&quot;&gt;The FJP — Delete Yourself From Web Services With...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wonderoftech.com/justdelete-me-close-your-online-accounts-easily/&quot;&gt;Justdelete.me – Close Your Online Accounts Easily&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.foxnews.com/tech/2013/08/27/justdeleteme-helps-wash-away-your-digital-life/&quot;&gt;JustDelete.me helps you wash away your digital life | Fox News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://5by5.tv/news/134&quot;&gt;5by5 | The News #134: Monday, August 26, 2013&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.redbull.com.br/cs/Satellite/pt_BR/Article/Site-facilita-retirada-dos-seus-dados-da-Internet-021243357182040&quot;&gt;Site facilitates removal of your data from the Internet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.synaix.de/2013/08/justdelete-me-das-loeschregister-im-internet-hilft-uns-beim-aufraeumen-unserer-accounts/&quot;&gt;synaix BLOG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.digitaltrends.com/web/justdelete-me-helps-delete-unused-online-accounts/&quot;&gt;JustDelete.me Helps You Delete Unused and Unwanted Online Accounts | Digital Trends&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slate.com/blogs/future_tense/2013/08/26/just_delete_me_how_to_delete_your_account_on_amazon_netflix_skype_et_al.html&quot;&gt;Just Delete Me: How to delete your account on Amazon, Netflix, Skype, et al.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dashburst.com/just-delete-me/&quot;&gt;Justdelete.me Wants to Help You Unplug From the Internet for Good&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://howto.cnet.com/8301-11310_39-57600044-285/how-to-delete-your-web-accounts-with-justdelete.me/&quot;&gt;How to delete your Web accounts with JustDelete.me | How To - CNET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cbc.ca/strombo/technology-1/want-to-delete-yourself-from-the-internet-this-site-can-help.html&quot;&gt;Strombo | Want To Delete Yourself From The Internet? This Site Can Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.psfk.com/2013/08/erase-web-presence.html&quot;&gt;Erase Your Web Presence With The Click Of One Button - PSFK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.idesigntimes.com/articles/7347/20130826/just-delete-me-new-free-website-search-close-account.htm&quot;&gt;JustDelete.Me: New Free Website To Delete Search Listings, Close Online Accounts And Remove Personal Information From The Web - International Design Times&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.anonymousbrasil.com/tecnologia/site-ajuda-usuario-cancelar-servicos-online-desaparecer-internet/&quot;&gt;Site helps user to cancel online services and &#39;disappear&#39; from the internet - Anonymous Brazil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blogs.phoenixnewtimes.com/jackalope/2013/08/justdeleteme_social_media_delete_facebook_off_the_grid.php&quot;&gt;How to Escape Social Media with JustDelete.Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.opposingviews.com/i/technology/justdeleteme-offers-advice-about-how-delete-digital-footprint-internet#&quot;&gt;JustDelete.me Offers Advice About How To Delete Digital Footprint From Internet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://everything-pr.com/justdelete-me/245353/#.UhtuCGSDQ18&quot;&gt;JustDelete.me Helps You Delete Your Account from 100+ Web Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tportal.hr/scitech/tehno/282123/Nestanite-s-interneta.html&quot;&gt;Disappears from the internet! | Tportal.hr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.gizmodo.fr/2013/08/26/supprimez-comptes-ligne-justdelete-me.html&quot;&gt;Supprimez facilement vos comptes en ligne avec JustDelete.me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dailydot.com/lifestyle/just-delete-me-web-accounts/&quot;&gt;The Daily Dot - Just Delete Me helps you painlessly wipe out all your Web accounts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dailygadgetry.com/justdelete-me-wants-to-help-you-commit-social-suicide/1629&quot;&gt;Justdelete.me wants to help you commit social suicide – Daily Gadgetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://stadt-bremerhaven.de/just-delete-me-hilft-bei-der-abmeldung-von-internet-diensten/&quot;&gt;Just Delete Me helps cancellation of Internet services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://computerhoy.com/noticias/internet/borrate-facebook-twitter-google-justdeleteme-5893&quot;&gt;Enrol yourself Delete Facebook, Twitter or Google with Justdelete.me - ComputerHoy.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://techcrunch.com/2013/08/23/justdelete-me-wants-to-help-you-pull-the-plug-on-all-those-pesky-online-accounts/&quot;&gt;Justdelete.me Wants To Help You Pull The Plug On All Those Pesky Online Accounts | TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://securityspread.com/2013/08/24/deleting-online-services-longer-need-easy/&quot;&gt;Deleting online services you no longer want or need, the easy way | Security Spread&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mondoinformazione.com/notizie-estero/cancellarsi-dal-web-just-delete-me/113651/&quot;&gt;Just-delete-me a help to unsubscribe from the web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://news.softpedia.com/news/Just-Delete-Me-Removes-You-from-the-Internet-377984.shtml&quot;&gt;Just Delete Me Removes You from the Internet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>Ten years ago we launched JustDelete.me</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Compiling CSS with Eleventy</title>
    <link href="https://rknight.me/blog/compiling-css-with-eleventy/"/>
    <updated>2023-08-16T12:30:35Z</updated>
    <id>https://rknight.me/compiling-css-with-eleventy/</id>
    <content type="html">&lt;p&gt;Yesterday I &lt;a href=&quot;https://social.lol/@robb/110894030545897361&quot;&gt;asked on Mastodon&lt;/a&gt; what methods people are using for compiling CSS with Eleventy. It&#39;s been a while since I&#39;ve need anything more than a single stylesheet but since I keep adding various things to my site, the stylesheet has got a bit unweildy. I&#39;ll admit, I know very little about the various css libraries and tools (the last time I did this I used Gulp which tells you how long ago that was) so I was coming to this with basically no knowledge. My basic requirements were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compile multiple CSS files into one&lt;/li&gt;
&lt;li&gt;Minify the CSS&lt;/li&gt;
&lt;li&gt;Keep everything in Eleventy. I don&#39;t want to have to manage additional libraries and scripts outside the Eleventy build step.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;PostCSS&lt;/h3&gt;
&lt;p&gt;The first response was &lt;a href=&quot;https://social.lol/@jgarber@mastodon.cc/110894115168581629&quot;&gt;Jason&lt;/a&gt; with his method of &lt;a href=&quot;https://github.com/jgarber623/refresh-dc.org/blob/main/lib/plugins/postcss.js&quot;&gt;using PostCSS&lt;/a&gt; with the &lt;code&gt;easy-import&lt;/code&gt; and &lt;code&gt;nesting&lt;/code&gt; plugin. This is a nice solution and I have used &lt;a href=&quot;https://postcss.org&quot;&gt;PostCSS&lt;/a&gt; a little bit in the past. &lt;a href=&quot;https://martinschneider.me/articles/generating-css-with-postcss-and-eleventy-before/&quot;&gt;Martin Schneider has a nice blog post&lt;/a&gt; about using PostCSS before the site is built so they can inline and purge the CSS.&lt;/p&gt;
&lt;h3&gt;Read the fucking manual&lt;/h3&gt;
&lt;p&gt;David Darnes came at me with a classic &lt;a href=&quot;https://en.wikipedia.org/wiki/RTFM&quot;&gt;RTFM&lt;/a&gt;. Turns out Eleventy has a &lt;a href=&quot;https://www.11ty.dev/docs/languages/custom/#example-add-sass-support-to-eleventy&quot;&gt;page on the docs for doing exactly this&lt;/a&gt;. This method uses &lt;a href=&quot;https://www.npmjs.com/package/sass&quot;&gt;Sass&lt;/a&gt; and requires a little bit of config. One thing to note is by default this will output &lt;em&gt;all&lt;/em&gt; &lt;code&gt;.scss&lt;/code&gt; file to the built site, so I added a check to see if the file is named &lt;code&gt;app&lt;/code&gt; and if it&#39;s not, then skip it. Alternatively you can put your files in an &lt;code&gt;_includes&lt;/code&gt; directory and these won&#39;t be output (thanks Dave). &lt;code&gt;style: &#39;compressed&#39;&lt;/code&gt; will minimise the CSS.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .eleventy.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sass &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sass&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;node:path&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addTemplateFormats&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;scss&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addExtension&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;scss&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;outputFileExtension&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;css&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token function-variable function&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;inputContent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; inputPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; parsed &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inputPath&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;app&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// we only want the output of app.scss&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sass&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;compileString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inputContent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;loadPaths&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;parsed&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dir &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;.&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;config&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dir&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;includes&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;compressed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; result&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;css&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;LightningCSS&lt;/h3&gt;
&lt;p&gt;I hadn&#39;t heard of &lt;a href=&quot;https://lightningcss.dev&quot;&gt;LightningCSS&lt;/a&gt; until yesterday but it&#39;s a &amp;quot;CSS parser, transformer, bundler, and minifier&amp;quot; built with Rust. &lt;a href=&quot;https://thinkdobecreate.com/&quot;&gt;Stephanie Eckles&lt;/a&gt; has an &lt;a href=&quot;https://github.com/5t3ph/eleventy-plugin-lightningcss&quot;&gt;Eleventy plugin&lt;/a&gt; for using LightningCSS which handles all the configuration and as a bonus ignores any files that start with &lt;code&gt;_&lt;/code&gt; so they won&#39;t get copied to the build folder.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .eleventy.js&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; lightningCSS &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;@11tyrocks/eleventy-plugin-lightningcss&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addPlugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;lightningCSS&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ultimately I like how simple this is to add to my existing site without any additonal configuration so I think this is the way I&#39;m going to go.&lt;/p&gt;
</content>
    <summary>A list of different options for compiling CSS with Eleventy</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Block ChatGPT and other AI Bots with robots.txt</title>
    <link href="https://rknight.me/blog/block-chatgpt-with-robotstxt/"/>
    <updated>2023-08-12T09:12:43Z</updated>
    <id>https://rknight.me/block-chatgpt-with-robotstxt/</id>
    <content type="html">&lt;p&gt;A &lt;code&gt;robots.txt&lt;/code&gt; file &amp;quot;tells search engine crawlers which URLs the crawler can access on your site&amp;quot;. Generally one would use this to tell a search engine which directories should be crawled, which ones shouldn&#39;t, or to completely block from crawling your site. The file lives at the root of your site. You can &lt;a href=&quot;https://rknight.me/robots.txt&quot;&gt;see mine here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://chat.openai.com&quot;&gt;ChatGPT&lt;/a&gt; has two user agents that might attempt to crawl your site: &lt;a href=&quot;https://platform.openai.com/docs/gptbot&quot;&gt;&lt;code&gt;GPTBot&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://platform.openai.com/docs/plugins/bot/chatgpt-user&quot;&gt;&lt;code&gt;ChatGPT-User&lt;/code&gt;&lt;/a&gt;. To disallow crawling from both of these, we can set our &lt;code&gt;robots.txt&lt;/code&gt; file like so:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;User-agent: GPTBot&lt;br /&gt;Disallow: /&lt;br /&gt;&lt;br /&gt;User-agent: ChatGPT-User&lt;br /&gt;Disallow: /&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Update 2023-09-29: &lt;a href=&quot;https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/&quot;&gt;Neil Clarke has a great post&lt;/a&gt; with some additional bots that should be blocked:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;User-agent: CCBot&lt;br /&gt;Disallow: /&lt;br /&gt;&lt;br /&gt;User-agent: Google-Extended&lt;br /&gt;Disallow: /&lt;br /&gt;&lt;br /&gt;User-agent: Omgilibot&lt;br /&gt;Disallow: /&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Adding a robots.txt file to Eleventy&lt;/h3&gt;
&lt;p&gt;Using Eleventy&#39;s &lt;a href=&quot;https://www.11ty.dev/docs/copy/&quot;&gt;passthrough file copy&lt;/a&gt; we can create a &lt;code&gt;robots.txt&lt;/code&gt; file and then add the following to our Eleventy config to make sure the file is copied to your built site:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addPassthroughCopy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;robots.txt&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively you can do this with just a file and a permalink:&lt;/p&gt;
&lt;pre class=&quot;language-txt&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;---&lt;br /&gt;permalink: robots.txt&lt;br /&gt;eleventyExcludeFromCollections: true&lt;br /&gt;---&lt;br /&gt;&lt;br /&gt;// user agents here&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there we go. ChatGPT, in theory, should be blocked from crawling our site.&lt;/p&gt;
</content>
    <summary>How to block ChatGPT from crawling your site with a robots.txt file</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Three Years of Hemispheric Views Feedback</title>
    <link href="https://rknight.me/blog/three-years-of-hemispheric-views-feedback/"/>
    <updated>2023-08-01T12:00:01Z</updated>
    <id>https://rknight.me/three-years-of-hemispheric-views-feedback/</id>
    <content type="html">&lt;p&gt;I recently started listening to the &lt;a href=&quot;https://hemisphericviews.com/&quot;&gt;Hemispheric Views&lt;/a&gt; podcast and decided I would go back to the start and listen to the 74 previous episodes that I hadn&#39;t listened to. I wrote down &lt;em&gt;all&lt;/em&gt; my feedback. I started this endevour on the 17th of May and finished the last episode this morning. &lt;a href=&quot;https://grepjason.sh/&quot;&gt;Jason&lt;/a&gt; agreed to this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We will take any feedback, 3 years old or otherwise haha&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In total I listened to just over 58 hours of main show and over ten hours of the one prime plus dot com member show. About ten episodes in I started singing the theme song to Baby Knight.&lt;/p&gt;
&lt;h3&gt;Main Show&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rknightuk.s3.amazonaws.com/site/desk-2023.jpg&quot;&gt;Roast my desk please&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;001 Jason tried Vegemite, has he tried marmite?&lt;/li&gt;
&lt;li&gt;002 Martins “Game Boy micro USB” joke wasn’t acknowledged as it should have been&lt;/li&gt;
&lt;li&gt;003 Did Jason ever develop the 1926 camera film?&lt;/li&gt;
&lt;li&gt;004 Halloween is the worst &amp;quot;holiday&amp;quot;&lt;/li&gt;
&lt;li&gt;009 Of course the week starts on Monday, anything else is mayhem&lt;/li&gt;
&lt;li&gt;009 I watched an episode of &lt;a href=&quot;https://youtu.be/Fahf77qzEnE&quot;&gt;Bargearse&lt;/a&gt; and it was glorious&lt;/li&gt;
&lt;li&gt;010 I love picking a random movie that&#39;s on TV when I’m away in a hotel or something but never do it at home&lt;/li&gt;
&lt;li&gt;010 One of favourite bands &lt;a href=&quot;https://www.youtube.com/watch?v=C7bnFPaGnkc&quot;&gt;covered the Round the Twist theme song&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;011 Andrew is a &lt;a href=&quot;https://www.youtube.com/watch?v=Qsj2-dWf1ko&quot;&gt;briefcase wanker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;012 Gabriel’s &lt;a href=&quot;https://www.lego.com/en-gb/product/poe-s-x-wing-fighter-75102&quot;&gt;Orange Lego X-Wing&lt;/a&gt; is canon&lt;/li&gt;
&lt;li&gt;014 What the hell is with Australian nature&lt;/li&gt;
&lt;li&gt;014 I would die for &lt;a href=&quot;https://www.youtube.com/watch?v=3vIaCXCkkrs&quot;&gt;the Gobbledok&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;014 “Nissan &lt;a href=&quot;https://en.wikipedia.org/wiki/Iambic_pentameter&quot;&gt;Iambic pentameter&lt;/a&gt;” 👏&lt;/li&gt;
&lt;li&gt;016 Andrew hasn’t seen Batman and Robin?! He should rectify that&lt;/li&gt;
&lt;li&gt;016 &lt;a href=&quot;https://rknight.me/building-a-pisight/&quot;&gt;I put a Raspberry Pi camera in an iSight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;017 &amp;quot;Double digit coffee action&amp;quot; would be a good band name&lt;/li&gt;
&lt;li&gt;019 My partner spent years using ~$10 headphones. When I gave her my good ones, she was blown away at how good music can sound&lt;/li&gt;
&lt;li&gt;020 Screw it, I’m making my own asset deprecation spreadsheet&lt;/li&gt;
&lt;li&gt;020 Sealed triangle toastie is the best toastie type&lt;/li&gt;
&lt;li&gt;022 Alex makes the media corner theme tune, a few years later he’s in Eurovision. Suspicious.&lt;/li&gt;
&lt;li&gt;022 The premise of &lt;a href=&quot;https://en.wikipedia.org/wiki/Crackerjack_(2002_film)&quot;&gt;Crackerjack&lt;/a&gt; sounds identical to &lt;a href=&quot;https://www.imdb.com/title/tt0337879/&quot;&gt;Blackball&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;022 “Perthsuaded” I hate this&lt;/li&gt;
&lt;li&gt;023 “&lt;em&gt;There still isn’t a good email app on iOS&lt;/em&gt;” - Andrew. This is because email is bad, stop looking for your own sanity&lt;/li&gt;
&lt;li&gt;023 “Everything surrounding email is wrong”&lt;/li&gt;
&lt;li&gt;023 &lt;a href=&quot;https://rknight.me/micro/110361312690891868/&quot;&gt;Here’s my homescreen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;023 I wish Apple would allow apps to be anywhere on the Home Screen too. Please Tim Apple.&lt;/li&gt;
&lt;li&gt;023 I have 203 apps installed&lt;/li&gt;
&lt;li&gt;025 Is Andrew still using the johnny decimal system?&lt;/li&gt;
&lt;li&gt;027 Game preservation is why I’ve tried as best I can to only buy physical games - currently I have around &lt;a href=&quot;https://rknight.me/collections/games&quot;&gt;300 across a bunch of consoles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;028 A few years ago we built a &lt;a href=&quot;http://knockoffia.devsdodesign.com&quot;&gt;Nokia 3310 simulator&lt;/a&gt; in the browser&lt;/li&gt;
&lt;li&gt;029 I wear shoes in the house, life is too short&lt;/li&gt;
&lt;li&gt;031 I wear the same black socks all year round, regardless of jeans or shorts. All my socks are identical so I don’t have to pair them up. I say no to funny socks&lt;/li&gt;
&lt;li&gt;031 Perhaps there’s a market for discounted once-used socks, then Jason could have new socks every day&lt;/li&gt;
&lt;li&gt;031 This is more than I ever needed to know about air conditioning&lt;/li&gt;
&lt;li&gt;033 I also love going to grocery stores in other countries&lt;/li&gt;
&lt;li&gt;033 I laughed at Andrew’s joke about going to Cloud 9&lt;/li&gt;
&lt;li&gt;034 My neighbour works at the Office of National Statistics and it sounds fascinating&lt;/li&gt;
&lt;li&gt;034 I’ve never seen rocky road with Turkish delight. That sounds incredible.&lt;/li&gt;
&lt;li&gt;036 I spat my drink out at “FinderJimbo”&lt;/li&gt;
&lt;li&gt;038 “Clean show”? Jason has definitely sworn on at least 4 episodes&lt;/li&gt;
&lt;li&gt;038 Movies our spouses don’t like? My partner refuses to watch any Fast and Furious movie despite the fact that &lt;a href=&quot;https://wegot.family&quot;&gt;I love them&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;038 TODAY!&lt;/li&gt;
&lt;li&gt;039 I know my neighbours now but didn’t at my last house that I lived at for 10 years. I did what Jason did when we moved and drew a map with names of everyone. It helped that we moved in around Christmas so everyone sent cards with their names&lt;/li&gt;
&lt;li&gt;040 I am furious Andrew doesn’t use “Grand Canion” as a username everywhere because that is so fucking good&lt;/li&gt;
&lt;li&gt;040 Pen licence! I never actually got mine because my writing was (and still is) terrible, I outlasted them until year 4 when everyone had to use a pen anyway&lt;/li&gt;
&lt;li&gt;042 Right at the start Jason swears and isn’t bleeped and then immediately after in the same sentence he is bleeped. No notes, just amused&lt;/li&gt;
&lt;li&gt;042 That stupid EA Sports intro in burned into my brain from play FIFA World Cup ‘98 on the N64. Immediately after Song 2 by Blur would play so it wasn’t all bad&lt;/li&gt;
&lt;li&gt;044 Never say “state daddy” again&lt;/li&gt;
&lt;li&gt;044 Fruit Loops is a garbage cereal. Lucky Charms all the way&lt;/li&gt;
&lt;li&gt;044 Andrew said the milk on the box looked too white and creamy. That’s because they usually use paint or PVA glue for milk in food photography&lt;/li&gt;
&lt;li&gt;045 I couldn’t use just spotlight. I have so many &lt;a href=&quot;https://rknight.me/alfred-workflows/&quot;&gt;workflows&lt;/a&gt; I use in Alfred&lt;/li&gt;
&lt;li&gt;046 The shuffling albums on Spotify drama with Adele was so stupid&lt;/li&gt;
&lt;li&gt;046 One arcade machine for my house? Time Crisis 2&lt;/li&gt;
&lt;li&gt;046 It’s 7am here and a breakfast lasagne sounds amazing&lt;/li&gt;
&lt;li&gt;046 What happened to &lt;a href=&quot;https://decimeal.com/&quot;&gt;Decimeal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;049 “&lt;em&gt;I don’t know if anyone does this but go back to the beginning of the RSS archive, apparently people have other things to do&lt;/em&gt;” - Martin&lt;/li&gt;
&lt;li&gt;049 The formal intro thing is unsettling&lt;/li&gt;
&lt;li&gt;050 What on earth was all this Dolly Parton talk?!&lt;/li&gt;
&lt;li&gt;051 I hadn’t considered the comparison to Dharma for Severance but that is an excellent observation&lt;/li&gt;
&lt;li&gt;051 🛎️ More Dolly Parton&lt;/li&gt;
&lt;li&gt;051 I watched Severance in one night until 6am while sleep-deprived when Baby Knight was born. It definitely gave it a different vibe&lt;/li&gt;
&lt;li&gt;052 Another recommendation for Punk Rock Factory: &lt;a href=&quot;https://www.youtube.com/watch?v=CUbul4f8AX8&quot;&gt;We Don&#39;t Talk About Bruno cover&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;053 The people saying sorry too much thing is a problem in the UK as well, I hate it&lt;/li&gt;
&lt;li&gt;054 I refuse to listen to podcasts that have dynamically inserted ads&lt;/li&gt;
&lt;li&gt;054 I have a disappearing dock and like it. Sorry Natasha&lt;/li&gt;
&lt;li&gt;055 My MX Master works fine on Bluetooth&lt;/li&gt;
&lt;li&gt;057 Martin on Elon buying Twitter “&lt;em&gt;I’m cautiously optimistic that something really useful will happen and it will change for the better&lt;/em&gt;”&lt;/li&gt;
&lt;li&gt;058 My entrance music would be &lt;a href=&quot;https://song.link/s/0q6Qyd2QaHMHp7APKyQsyi&quot;&gt;Not the Same by Bodyjar&lt;/a&gt; because it’s a banger&lt;/li&gt;
&lt;li&gt;059 I’m scared to do bad show notes lest I feel the wrath of Jason&lt;/li&gt;
&lt;li&gt;061 I have my school yearbook but I never look at it&lt;/li&gt;
&lt;li&gt;061 Perfect foods: pizza, spaghetti bolognese, donor kebab with lettuce and garlic sauce&lt;/li&gt;
&lt;li&gt;061 “Feld tip” 👀&lt;/li&gt;
&lt;li&gt;063 This was an excellent discussion about podcasts&lt;/li&gt;
&lt;li&gt;064 I refuse to believe it&#39;s pronounced ex-mouth&lt;/li&gt;
&lt;li&gt;064 This business corner was incredible&lt;/li&gt;
&lt;li&gt;065 I guessed the bus story was fake&lt;/li&gt;
&lt;li&gt;068 wtf was that Cappuccino talk&lt;/li&gt;
&lt;li&gt;069 We have Nobby’s nuts here too&lt;/li&gt;
&lt;li&gt;069 You’re making me want a Play Date&lt;/li&gt;
&lt;li&gt;069 My top five movies:
&lt;ul&gt;
&lt;li&gt;Back to the Future (I even have a Back to the Future tattoo)&lt;/li&gt;
&lt;li&gt;Hot Fuzz&lt;/li&gt;
&lt;li&gt;Baby Driver&lt;/li&gt;
&lt;li&gt;Captain America: Winter Soldier&lt;/li&gt;
&lt;li&gt;Straight Outta Compton&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;070 Benji said he doesn’t like the yellow bit of eggs. Notable.&lt;/li&gt;
&lt;li&gt;070 “&lt;em&gt;Be more negative&lt;/em&gt;” - Benji&lt;/li&gt;
&lt;li&gt;072 Martin will hate this sign from a UK chain where &lt;a href=&quot;https://www.alamy.com/stock-photo-a-poundland-store-sign-71740740.html?imageid=1F597E32-BEC1-46FC-9C74-1CCCBC895D64&amp;amp;p=179593&amp;amp;pn=1&amp;amp;searchId=8798bbaa288a340a187eb179f2e6aaea&amp;amp;searchtype=0&quot;&gt;“everyday” should be two words&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;074 My favourite photos from 2022:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/2022-criminal-damage.jpg&quot; alt=&quot;A phonebox with the words criminal damage graffitied on it&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A phone box in Edinburgh&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/2022-edinburgh.jpg&quot; alt=&quot;The Edinburgh skyline at night&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The Edinburgh skyline at night&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/2022-pantheon.jpg&quot; alt=&quot;Two wine glasses with the Pantheon in the background&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Having a drink in front of the Pantheon&lt;/p&gt;
&lt;h3&gt;one prime plus dot com member show&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;01 Now I need to make a home wiki&lt;/li&gt;
&lt;li&gt;02 The eighties &lt;em&gt;were&lt;/em&gt; sexy&lt;/li&gt;
&lt;li&gt;06 This number plate story is wonderful&lt;/li&gt;
&lt;li&gt;06 In the UK we didn’t line dance at school, but we did &lt;a href=&quot;https://en.m.wikipedia.org/wiki/Morris_dance&quot;&gt;Morris Dance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;07 I started podcasting because I said, kind of as a joke, “Lets do a podcast?” to John Voorhees ~8 years ago&lt;/li&gt;
&lt;li&gt;07 “&lt;em&gt;Am I being too intense?&lt;/em&gt;” - Martin. No Martin, you crack on.&lt;/li&gt;
&lt;li&gt;08 I guessed before I listened: I think Jason is tallest, then Andrew, then Martin.&lt;/li&gt;
&lt;li&gt;08 UK folks uses imperial for height and a lot of the time weight as well. Oh and speed limits and distances are usually imperial too.&lt;/li&gt;
&lt;li&gt;08 You are all very tall&lt;/li&gt;
&lt;li&gt;09 The health insurance I have through work has a scheme to get a discounted Apple Watch if you do a certain amount of steps/exercise minutes every week&lt;/li&gt;
&lt;li&gt;013 My mum was a social worker her entire career. I remember her saying “are you sure about these computers as a job?” when I was 16. Maybe she was right.&lt;/li&gt;
&lt;li&gt;013 I have it on good authority that a lot of universities use group work so the students who are doing worse still pass because they get paired up with one or two people who will do the work&lt;/li&gt;
&lt;li&gt;016 My pre-teen photo, 5 years old on my last day of a holiday in Cyprus:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/me-young.jpg&quot; alt=&quot;Me at 4 in Cyprus&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;016 wtf is ham sauce for beans&lt;/li&gt;
&lt;li&gt;019 The kebab story 👏&lt;/li&gt;
&lt;li&gt;020 A half onesie is mayhem&lt;/li&gt;
&lt;li&gt;021 I view someone not voting essentially as a vote for the “winner”. Ultimately if you didn’t vote, you don’t have the same legitimacy to complain as someone who did.&lt;/li&gt;
&lt;li&gt;023 Wogman. Just…wow. Incredible.&lt;/li&gt;
&lt;li&gt;024 I will not download Day One again. I will not download Day One again.&lt;/li&gt;
&lt;li&gt;026 I’ve been really enjoying Omnivore for my read later stuff&lt;/li&gt;
&lt;li&gt;027 Arc is definitely a “have you heard the good word” product for sure&lt;/li&gt;
&lt;li&gt;027 I like my gum the standard format&lt;/li&gt;
&lt;li&gt;029 Andrews ability to improvised over-the-top intros is amazing&lt;/li&gt;
&lt;li&gt;029 Food pleasures: crisps, literally any crisps&lt;/li&gt;
&lt;li&gt;030 bullying&lt;/li&gt;
&lt;li&gt;031 Some birds have been known to &lt;a href=&quot;https://www.independent.co.uk/news/science/from-modems-to-alarms-the-world-of-bird-mimics-6105998.html#&quot;&gt;mimic car alarm sounds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;031 We need a Mastodon instance called Screacher&lt;/li&gt;
&lt;li&gt;032 Sorry Jason the opening the crisps with scissors thing is weird&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>I listened to ~70 hours of Hemispheric Views and wrote down all my feedback</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Fix for Low Volume Exported Audio in GarageBand</title>
    <link href="https://rknight.me/blog/fix-for-low-volume-exported-audio-in-garageband/"/>
    <updated>2023-07-10T08:28:42Z</updated>
    <id>https://rknight.me/fix-for-low-volume-exported-audio-in-garageband/</id>
    <content type="html">&lt;p&gt;Yesterday &lt;a href=&quot;https://hachyderm.io/@mikestreety/110685303152811714&quot;&gt;Mike pointed out&lt;/a&gt; that the pilot episode of &lt;a href=&quot;https://wegot.family/0&quot;&gt;my new podcast&lt;/a&gt; was quiet compared to other shows. I opened up the project files in GarageBand and couldn&#39;t see anything that would be causing this so I started hunting around in the settings. It turns out the &amp;quot;Export projects at full volume&amp;quot; was causing this. I don&#39;t know what this setting is supposed to do but I turned it off, exported the episode again, and it was fixed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/garageband-setting.png&quot; alt=&quot;GarageBand setting for full volume export&quot; /&gt;&lt;/p&gt;
</content>
    <summary>My exports for my new podcast were really quiet compared to other podcasts. Turns out GarageBand has a setting causing this</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>A Threads Thread Blog Post</title>
    <link href="https://rknight.me/blog/a-threads-thread-blog-post/"/>
    <updated>2023-07-06T08:05:16Z</updated>
    <id>https://rknight.me/a-threads-thread-blog-post/</id>
    <content type="html">&lt;p&gt;I wanted to expand a bit on my &lt;a href=&quot;https://social.lol/@robb/110665866974743896&quot;&gt;Threads thread&lt;/a&gt; so instead of adding to the thread, I&#39;ve written a blog post about Threads. Clear? Good.&lt;/p&gt;
&lt;p&gt;The Mastodon blog has &lt;a href=&quot;https://blog.joinmastodon.org/2023/07/what-to-know-about-threads/&quot;&gt;a good post about Threads&lt;/a&gt; and what it means for the fediverse in general:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The fact that large platforms are adopting ActivityPub is not only validation of the movement towards decentralized social media, but a path forward for people locked into these platforms to switch to better providers&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have no intention of using Threads, signing up was purely an academic exercise. I&#39;m not even going to link to my profile but if you happen to find me, I&#39;ll be posting random emojis when I remember the app exists.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Threads shows me a load of crap from people I don’t follow.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I said &amp;quot;as expected&amp;quot; in my Mastodon post but I&#39;m not sure I&#39;d actually thought about this. &lt;em&gt;Of course&lt;/em&gt; they were going to dump random stuff into the timeline. And &lt;em&gt;of course&lt;/em&gt; this will include ads/promoted posts in the future. I wonder if they intend to inject ads into a persons timeline when they support ActivityPub so even if you follow from Mastodon you see ads (until I immediately unfollow them). We shall see.&lt;/p&gt;
&lt;p&gt;The app does that awful refresh like Instagram does when you open the app, start reading something, then it’s gone, never to be seen again. &lt;a href=&quot;https://mastodon.social/@CTD/110665895008825097&quot;&gt;CTD said&lt;/a&gt; they have muscle memory to favourite posts on Instagram when it opens just in case this happens? That is &lt;em&gt;wild&lt;/em&gt; that people feel the need to do that just because the app sucks. Now we have two apps that suck like that.&lt;/p&gt;
&lt;p&gt;Speaking of ActivityPub, they say it&#39;s coming, it&#39;s mentioned in help docs but I agree with &lt;a href=&quot;https://social.lol/@andyn/110665801776694098&quot;&gt;Andy&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;it either won’t happen at all, or won’t happen for a long time&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I made a &lt;a href=&quot;https://rknight.me/building-an-activitypub-server/&quot;&gt;basic ActivityPub server a few weeks ago&lt;/a&gt; and while it doesn&#39;t implement everything that ActivityPub has to offer, it&#39;s close enough. I&#39;m surprised a company the size of Meta, who has a huge team of engineers couldn&#39;t get this working for launch. To be clear I&#39;m not saying &amp;quot;herp derp I did it why can&#39;t they&amp;quot; but still, I find it surprising. If we don&#39;t see it within a month, I think we might never see it.&lt;/p&gt;
&lt;p&gt;Assuming they &lt;em&gt;do&lt;/em&gt; release AP support, I &lt;em&gt;am&lt;/em&gt; excited for that. Being able to follow people who will never join Mastodon sounds great. I don&#39;t want to use Threads (much like Bluesky) just to follow a handful of people. Here&#39;s hoping they &lt;em&gt;do&lt;/em&gt; release it and that they don&#39;t inject ads into a user&#39;s posts.&lt;/p&gt;
</content>
    <summary>A thread about Threads that turned in a blog post about Threads</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Custom Sidebar Icons in Finder</title>
    <link href="https://rknight.me/blog/custom-sidebar-icons-in-finder/"/>
    <updated>2023-06-29T16:28:34Z</updated>
    <id>https://rknight.me/custom-sidebar-icons-in-finder/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/custom-icons.png&quot; alt=&quot;Custom icons in the Finder&quot; /&gt;&lt;/p&gt;
&lt;p&gt;MacOS customisation is basically dead. Plenty of apps that used to work, no longer do. You can still have custom folder icons which is nice but I wanted custom sidebar icons for those folders, like &lt;a href=&quot;https://rknight.me/micro/110615734381939778/&quot;&gt;the developer one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I started googling around trying to find something for recent versions of MacOS and the only thing I found was &lt;a href=&quot;https://www.reddit.com/r/mac/comments/seig87/how_to_make_custom_finder_sidebar_icons_big_sur/&quot;&gt;this Reddit post&lt;/a&gt; outlining a method to do it with PNGs. Between me and &lt;a href=&quot;https://www.keiransell.com&quot;&gt;Keir&lt;/a&gt; we were able to make it work not only with any standard &lt;a href=&quot;https://developer.apple.com/sf-symbols/&quot;&gt;SF Symbol&lt;/a&gt; but custom made ones as well.&lt;/p&gt;
&lt;p&gt;You&#39;ll need Xcode installed to do this but the instructions relatively simple. I will say it&#39;s &lt;em&gt;really&lt;/em&gt; flaky when building, sometimes it works, sometimes it doesn&#39;t, sometimes it just shows a random icon instead. All of the instructions are on &lt;a href=&quot;https://github.com/rknightuk/custom-finder-sidebar-icons&quot;&gt;the GitHub repository&lt;/a&gt; including some dandy screencasts from Keir.&lt;/p&gt;
</content>
    <summary>Setting custom sidebar icons for folders in MacOS. Managed to get this working with a lot of trial and error</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Building an ActivityPub Server</title>
    <link href="https://rknight.me/blog/building-an-activitypub-server/"/>
    <updated>2023-06-28T05:48:41Z</updated>
    <id>https://rknight.me/building-an-activitypub-server/</id>
    <content type="html">&lt;p&gt;To start with, I&#39;m not convinced everything I&#39;ve done here is exactly to the ActivityPub specification or if there will be problems interacting with Bugle on various ActivityPub servers outside the main ones (Mastodon, Calckey, etc). I&#39;m also unclear on which parts of this are Mastodon-specific and which parts are pure ActivityPub. I will use Mastodon as the example external server throughout.&lt;/p&gt;
&lt;p&gt;I won&#39;t go over setting up my database or server for this but at minimum you&#39;ll need a way to handle requests, render JSON, and a database to store posts and activities.&lt;/p&gt;
&lt;h3&gt;WebFinger and Profile JSON&lt;/h3&gt;
&lt;p&gt;This is the easiest part of the whole thing, two JSON files: &lt;code&gt;.well-known/webfinger&lt;/code&gt; and &lt;code&gt;@bugle.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.well-known/webfinger&lt;/code&gt; is how ActivityPub finds links to your profile. Searching for &lt;code&gt;@bugle@bugle.lol&lt;/code&gt; on Mastodon, for example, will send a &lt;code&gt;GET&lt;/code&gt; request to &lt;code&gt;https://bugle.lol/.well-known/webfinger?resource=acct:bugle@bugle.lol&lt;/code&gt; which will return the following:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;subject&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;acct:bugle@bugle.lol&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;links&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;rel&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;self&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;application/activity+json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;href&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The server handles checking if the requested &lt;code&gt;resource&lt;/code&gt; exists and returning the correct data. The &lt;code&gt;links&lt;/code&gt; part is how it knows the account lives at &lt;code&gt;bugle.lol/@bugle&lt;/code&gt;. This might seems obvious but it isn&#39;t always the case that the username match the domain where the profile lives. For example, the profile for &lt;a href=&quot;https://mastodon.macstories.net/@viticci&quot;&gt;viticci@macstories.net&lt;/a&gt; is actually at &lt;code&gt;mastodon.macstories.net/@viticci&lt;/code&gt;, which is indicated by the webfinger.&lt;/p&gt;
&lt;p&gt;Once Mastodon has the link, it will make a request to that link (in this case &lt;code&gt;https://bugle.lol/@bugle&lt;/code&gt;) for the profile json file which includes general profile information like name, avatar, and bio, as well as which endpoints it should send requests to. These are usually called an inbox although the actually name and path isn&#39;t important.&lt;/p&gt;
&lt;p&gt;You can see a full example on &lt;a href=&quot;https://social.lol/@robb.json&quot;&gt;my Mastodon profile&lt;/a&gt; but I&#39;ll go through the main important parts here. The first part is the &lt;code&gt;@context&lt;/code&gt;, which as best I can tell it an indicator of the type of object(?) we&#39;re defining, in this case an activity stream.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;@context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token string&quot;&gt;&quot;https://w3id.org/security/v1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next part is an ID to identify your user, a type to define that this is a &lt;code&gt;Person&lt;/code&gt;, and endpoints for various features, some of which are Mastodon-specific (like &lt;code&gt;featured&lt;/code&gt; and &lt;code&gt;featuredTags&lt;/code&gt;).&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Person&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;following&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/following&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;followers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/followers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;inbox&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/inbox&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;outbox&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/outbox&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;featured&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/collections/featured&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;featuredTags&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/collections/tags&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;endpoints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;sharedInbox&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/inbox&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m not entirely sure when most of these are used aside from when first searching for a profile (because I see the requests in the logs) but the important ones here are &lt;code&gt;inbox&lt;/code&gt; and &lt;code&gt;endpoints.sharedInbox&lt;/code&gt;. This is where replies and mentions will get posted to (&lt;code&gt;sharedInbox&lt;/code&gt;) and activities such as likes, follows, and boosts (&lt;code&gt;inbox&lt;/code&gt;). I&#39;ll go into how that works further down.&lt;/p&gt;
&lt;p&gt;We also need information about the profile itself like name, bio, profile picture, and so on. The &lt;code&gt;icon&lt;/code&gt; attributes refer to your main profile image and &lt;code&gt;image&lt;/code&gt; refers to a header image.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bugle dot lol&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;p&gt;A bio goes here&amp;lt;/p&gt;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;manuallyApprovesFollowers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;discoverable&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2022-12-16T00:00:00Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;icon&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Image&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;mediaType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://placekitten.com/200/300&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Image&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;mediaType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://placekitten.com/600/300&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally we need a &lt;code&gt;publicKey&lt;/code&gt; attribute. This is used to validate requests to and from the server:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;publicKey&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle#main-key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;owner&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;publicKeyPem&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyB9YyNt5OB23VW3sFm5o\nPnV4phqSXgqwyqmjXIE6ZtwLE0I6JEeeqv+SD2pd9QDXiUfugEWuUyNImZCglNg2\nV3Vh/NNr/YX6tWW6VSkudJ/b8lNQF8Rr/Z9wK9jD0WUmFs+YjS0R/KePDtLt1HOX\nVfjPLyOCODO+ykXQkydLI1RZf3V+iJdiTP9e5nhBxQGHkbyVja/86uqJIC96zyX4\nQPteEtHjXngVgO6QozCQu6Null4WFOHUdPGHaN7wsJtkZV10BPp3yCOiirJQlXSp\no+7YfJuROFv8QU+jWitTPTYWQYEuRwUfDUsdThqSh/u6eZt2hHjTzcI0/qgpxWqI\n1wIDAQAB\n-----END PUBLIC KEY-----\n&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can generate these in most languages. Here&#39;s how I did it in PHP on profile creation to store in the database:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;private_key_bits&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2048&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;private_key_type&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OPENSSL_KEYTYPE_RSA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$keypair&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;openssl_pkey_new&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;openssl_pkey_export&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$keypair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$private_key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$public_key&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;openssl_pkey_get_details&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$keypair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$public_key&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$public_key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Receiving Activities&lt;/h3&gt;
&lt;p&gt;As mentioned above there are two endpoints for receiving activities: The global inbox (&lt;code&gt;/inbox&lt;/code&gt;) and the user inbox (&lt;code&gt;/@bugle/inbox&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;Validating Requests&lt;/h3&gt;
&lt;p&gt;All signature validation is handled in my &lt;a href=&quot;https://github.com/rknightuk/bugle/blob/main/app/Services/HttpSignature.php&quot;&gt;&lt;code&gt;HttpSignature&lt;/code&gt; class&lt;/a&gt; if you&#39;d prefer to look at the code directly.&lt;/p&gt;
&lt;p&gt;Every request that comes in should be validated against the signature to make sure it&#39;s a valid request. The first step is to extract the values into an array keyed by the name (other languages and frameworks might have an easier way to do this).&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$values&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// split the signature at &#39;,&#39; and assign each one&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// to $values, keyed by its name&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$parts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;signature&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$parts&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$pair&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;=&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$key&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// $values is now:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    &#39;keyId&#39; =&gt; &#39;https://mas.to/users/rknightuk#main-key&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    &#39;algorithm&#39; =&gt; &#39;rsa-sha256&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    &#39;headers&#39; =&gt; &#39;&#39;(request-target) host date digest content-type&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    &#39;signature&#39; =&gt; &#39;BIGLONGSIGNATURE&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ];&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we need to get the &lt;code&gt;headers&lt;/code&gt; value from the signature, and map over those, get the values from the request headers, and generate a string. This string is what we use to validate the request:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$inboxPath&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/@bugle/inbox&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$headerList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39; &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;headers&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// $headersList = [&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;(request-target)&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;host&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;date&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;digest&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//	&#39;content-type&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$expectedHeaders&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$headerList&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$h&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;(request-target)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token variable&quot;&gt;$expectedHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;(request-target): post &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$inboxPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token variable&quot;&gt;$expectedHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$h&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$h&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$signatureHeader&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;signature&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$signaturePairs&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;,&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$signatureHeader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$signatureHeaderMap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$signaturePairs&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$pairParts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;=&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$pair&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$key&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$pairParts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$pairParts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$signatureHeaderMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;implode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$expectedHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// $str:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// &quot;(request-target): post /@bugle/inbox&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// host: 9928-82-19-65-174.ngrok-free.app&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// date: Tue, 27 Jun 2023 15:27:11 GMT&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// digest: SHA-256=LdxwDtVsenhzJE0E3H2oj2C7cKPvZYEG5LrY0phH9Zc=&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// content-type: application/activity+json&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing to note here is if you set different inbox URLs for user and for local, then you need to specific which path you&#39;re validating for (either &lt;code&gt;/inbox&lt;/code&gt; or &lt;code&gt;/@bugle/inbox&lt;/code&gt;) otherwise the signatures won&#39;t match.&lt;/p&gt;
&lt;p&gt;Lastly, we need to fetch the public key for the actor, and use that to validate the request:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$keyId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$signatureHeaderMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;keyId&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$actor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name static-context&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;accept&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;application/activity+json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$keyId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$publicKeyPem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$actor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;publicKey&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;publicKeyPem&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$verifier&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;openssl_get_publickey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$publicKeyPem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$validate&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;openssl_verify&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;base64_decode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$signatureHeaderMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;signature&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$verifier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OPENSSL_ALGO_SHA256&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$isValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$validate&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;isValid&lt;/code&gt; is true, we can carry on and accept requests. You should do this for all requests that come into the inboxes.&lt;/p&gt;
&lt;h3&gt;Likes, Boosts, and Follows&lt;/h3&gt;
&lt;p&gt;The user inbox will &lt;code&gt;POST&lt;/code&gt; requests for follows, likes, and boosts. Likes and boosts are easy enough to handle as you don&#39;t need to respond to the request or even store them if you don&#39;t want to. A like is the simplest of the two. It contains an ID of the like, the type of activity, the actor, and the object - this is the post that has been liked.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;@context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/users/robb#likes/10253875&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Like&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;actor&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/users/robb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/f6dfebf6-1a73-4b3e-8afa-28a768698579&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Boosts are similar, but they also include &lt;code&gt;to&lt;/code&gt; and &lt;code&gt;cc&lt;/code&gt; arrays of users the post is being boosted to, as well as a &lt;code&gt;published_at&lt;/code&gt; date.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;@context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/users/robb/statuses/110592144954280515/activity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Announce&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;actor&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/users/robb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-06-23T06:36:51Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;to&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams#Public&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;cc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string&quot;&gt;&quot;https://8d19-82-19-65-174.ngrok-free.app/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/users/robb/followers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://8d19-82-19-65-174.ngrok-free.app/@bugle/f6dfebf6-1a73-4b3e-8afa-28a768698579&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Follow events are more complicated because they require a response. A follow activity will look something like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;@context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/9bb08aae-c666-432f-a3e6-35617e32830d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Follow&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;actor&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://aninstance.social/users/robb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To respond to a follow, we need to send an &lt;code&gt;Accept&lt;/code&gt; activity with a valid signature. To start with we need to build our activity message; it has an ID, type, actor (the user being followed) and an &lt;code&gt;object&lt;/code&gt; which in this case, is the &lt;code&gt;Follow&lt;/code&gt; activity we received.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// this isn&#39;t important unless you intend to store all&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// follow requests that come into the system but a unique(ish)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ID is required here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$guid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bin2hex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random_bytes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$message&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;@context&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://www.w3.org/ns/activitystreams&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;id&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://bugle.lol&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$guid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;type&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Accept&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;actor&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://bugle.lol/@bugle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;object&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;@context&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://www.w3.org/ns/activitystreams&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;id&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://aninstance.social/9bb08aae-c666-432f-a3e6-35617e32830d&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;type&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Follow&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;actor&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://aninstance.social/users/robb&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;object&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://bugle.lol/@bugle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To generate the signature we need the message we just created, the private key of the profile from the database, the host of the actor (in this case &lt;code&gt;aninstance.social&lt;/code&gt;), the inbox path (&lt;code&gt;/@bugle/inbox&lt;/code&gt;), and the url to the profile.&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$host&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;aninstance.social&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$path&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/@bugle/inbox&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$privateKey&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;a_private_key&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$keyId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://bugle.lol/@bugle&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$hash&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;sha256&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;json_encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$digest&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;base64_encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$date&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;D, d M Y H:i:s \G\M\T&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$signer&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;openssl_get_privatekey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$privateKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$stringToSign&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;(request-target): post &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$path&lt;/span&gt;&lt;/span&gt;\nhost: &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$host&lt;/span&gt;&lt;/span&gt;\ndate: &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$date&lt;/span&gt;&lt;/span&gt;\ndigest: SHA-256=&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$digest&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;openssl_sign&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$stringToSign&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$signature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$signer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OPENSSL_ALGO_SHA256&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$signature_b64&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;base64_encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$signature&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$header&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;keyId=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$keyId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&quot;,algorithm=&quot;rsa-sha256&quot;,headers=&quot;(request-target) host date digest&quot;,signature=&quot;&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$signature_b64&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&quot;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Host&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Date&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Signature&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$header&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Digest&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;SHA-256=&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$digest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;application/activity+json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Accept&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;application/activity+json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we send the &lt;code&gt;Accept&lt;/code&gt; activity:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$inbox&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://aninstance.social/users/robb/inbox&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name static-context&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json_encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;application/json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$inbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;ll need this same header signature generation later for notifying followers of new posts.&lt;/p&gt;
&lt;p&gt;If someone unfollows you, you&#39;ll receive an &lt;code&gt;Undo&lt;/code&gt; request. Check the &lt;code&gt;actor&lt;/code&gt; on that request and you can then remove them from your followers table.&lt;/p&gt;
&lt;h3&gt;Replies&lt;/h3&gt;
&lt;p&gt;The global inbox will receive a &lt;code&gt;POST&lt;/code&gt; request with data about replies and @mentions with data that looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/users/rknightuk/statuses/110617068531392295/activity&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Create&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;actor&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/users/rknightuk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-06-27T16:15:15Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;to&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	   &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams#Public&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;cc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/users/rknightuk/followers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@robb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/users/rknightuk/statuses/110617068531392295&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Note&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;inReplyTo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-06-27T16:15:15Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/@rknightuk/110617068531392295&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;attributedTo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/users/rknightuk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;to&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	        &lt;span class=&quot;token property&quot;&gt;&quot;0&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams#Public&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;cc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	        &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/users/rknightuk/followers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	        &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@robb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	    &lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;p&gt;&amp;lt;span class=\&quot;h-card\&quot;&gt;&amp;lt;a href=\&quot;https://bugle.lol/@robb\&quot; class=\&quot;u-url mention\&quot;&gt;@&amp;lt;span&gt;robb&amp;lt;/span&gt;&amp;lt;/a&gt;&amp;lt;/span&gt; hello!&amp;lt;/p&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you only have one profile setup then you&#39;re golden: just save the &lt;code&gt;object.content&lt;/code&gt; and the &lt;code&gt;object.id&lt;/code&gt; somewhere and you have your reply. If you have a server with multiple profiles, you can map over the &lt;code&gt;object.cc&lt;/code&gt; array to find matching profiles for your domain.&lt;/p&gt;
&lt;p&gt;As a bonus here, unrelated to ActivityPub, I setup &lt;a href=&quot;https://ntfy.sh/&quot;&gt;https://ntfy.sh/&lt;/a&gt; to send me notifications whenever I get a reply:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$ntfyKey&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;bugle.ntfy_key&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token class-name static-context&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Content-Type&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;text/plain&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Title&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;New mention from @&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$activity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getActorUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;click&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token class-name static-context&quot;&gt;Arr&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$input&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;object.url&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://ntfy.sh/&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$ntfyKey&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strip_tags&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$activity&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Formatting Posts&lt;/h3&gt;
&lt;p&gt;The post&#39;s content needs to be rendered to HTML. Bugle supports writing in Markdown so I use &lt;a href=&quot;https://github.com/thephpleague/commonmark&quot;&gt;&lt;code&gt;league/commonmark&lt;/code&gt;&lt;/a&gt; to format the content for sending to followers. I also extract @mentions to generate links in the posts and add them to &lt;code&gt;tags&lt;/code&gt; on the post JSON. See &lt;a href=&quot;https://github.com/rknightuk/bugle/blob/main/app/Services/TootFormatter.php&quot;&gt;&lt;code&gt;TootFormatter&lt;/code&gt;&lt;/a&gt; for the full implementation.&lt;/p&gt;
&lt;p&gt;A post that looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-md&quot;&gt;&lt;code class=&quot;language-md&quot;&gt;This toot has &lt;span class=&quot;token url&quot;&gt;[&lt;span class=&quot;token content&quot;&gt;a link&lt;/span&gt;](&lt;span class=&quot;token url&quot;&gt;https://example.com&lt;/span&gt;)&lt;/span&gt; and a mention: @robb@social.lol ahoy!&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is run through the formatter:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;This toot has [a link](https://example.com) and a mention: @robb@social.lol ahoy!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$converter&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CommonMarkConverter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;html_input&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;strip&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;allow_unsafe_links&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token constant boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$converter&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;convert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getContent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;nl2br&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$tags&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$pattern&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/@?\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,})\b/mi&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;preg_match_all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$pattern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$fullUsernames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$usernames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$domains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$matches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$fullUsernames&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$fu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$tags&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;type&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;Mention&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;href&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$domains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/@&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$usernames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;name&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$fu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token variable&quot;&gt;$fu&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token function&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&amp;lt;span class=&quot;h-card&quot;&gt;&amp;lt;a href=&quot;https://%s/@%s&quot; class=&quot;u-url mention&quot;&gt;@&amp;lt;span&gt;%s&amp;lt;/span&gt;&amp;lt;/a&gt;&amp;lt;/span&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token variable&quot;&gt;$domains&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token variable&quot;&gt;$usernames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token variable&quot;&gt;$usernames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;/(&amp;lt;br \/&gt;)+$/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token variable&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$tags&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Becomes:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;This toot has &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;a link&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; and a mention: &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;h-card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://social.lol/@robb&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;u-url mention&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;@&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;robb&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; ahoy!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&quot;,&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And the &lt;code&gt;tags&lt;/code&gt;, which we&#39;ll use later to determine who to notify of a mention, look like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mention&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;href&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://social.lol/@robb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@robb@social.lol&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Notifying Followers about New Posts&lt;/h3&gt;
&lt;p&gt;Unlike RSS where new posts can be fetched into a feed ActivityPub requires all followers are notified of new posts by the originating server. Here&#39;s an example payload to notify followers of a new post.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;@context&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/7c01aab9-bc96-4773-b235-703a6d2a1f76&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Create&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;actor&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;to&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams#Public&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;cc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/followers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token string&quot;&gt;&quot;https://example.com/users/robb&quot;&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/7c01aab9-bc96-4773-b235-703a6d2a1f76&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Note&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;inReplyTo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-06-27T20:42:43Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;updated&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-06-27T21:30:10Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;attributedTo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&amp;lt;p&gt;Toot toot!&amp;lt;/p&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;to&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		  &lt;span class=&quot;token string&quot;&gt;&quot;https://www.w3.org/ns/activitystreams#Public&quot;&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;cc&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;		  &lt;span class=&quot;token string&quot;&gt;&quot;https://bugle.lol/@bugle/followers&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		  &lt;span class=&quot;token string&quot;&gt;&quot;https://example.com/users/robb&quot;&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;senstive&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;summary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;attachment&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Document&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;mediaType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/jpeg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://placekitten.com/200/300&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A kitten&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;blurhash&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;L46[2Hofofof00j[offQ~qofofof&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token property&quot;&gt;&quot;tag&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mention&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;href&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://mas.to/@rknightuk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;				&lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;@rknightuk@mas.to&quot;&lt;/span&gt;&lt;br /&gt;			&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;		&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;type&lt;/code&gt; attribute has three possible values that I&#39;m using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Create&lt;/code&gt; - to notify of a new post&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Delete&lt;/code&gt; - to delete an existing post&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Update&lt;/code&gt; - to update an existing post after an edit. Mastodon (and I assume others) require the &lt;code&gt;updated&lt;/code&gt; timestamp for a &lt;code&gt;Update&lt;/code&gt; activity&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;cc&lt;/code&gt; field is how visibility is controlled on Mastodon (I think) but I haven&#39;t looked into it enough so Bugle only has the ability to send public posts.&lt;/p&gt;
&lt;p&gt;To notify followers of a new post, send a &lt;code&gt;POST&lt;/code&gt; request to the &lt;em&gt;global&lt;/em&gt; of the followers instance. For the sake of simplicity I&#39;m taking the users domain and appending &lt;code&gt;/inbox&lt;/code&gt; to it. This won&#39;t work in a few edge-cases (like the MacStories example above) so I need to update Bugle to fetch the users endpoints using webfinger either when they follow an account, or each time I need to send to them.&lt;/p&gt;
&lt;p&gt;If we assume I have one follower (@robb@example.com) and I make a post that mentioned another account (@dave@example.com) I need to make two requests to notify them both. A follower notification goes to the user inbox:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$follower&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://example.com/@robb&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$inbox&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://example.com/@robb/inbox&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// generate header signture as we did above for `Accept`  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$response&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name static-context&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json_encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;application/json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$inbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And an @mention goes to the global inbox. For mentions, you need to include the &lt;code&gt;tag&lt;/code&gt; array in the post data (see above).&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$mention&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://example.com/@dave&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$inbox&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://example.com/inbox&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$headers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// generate header signture as we did above for `Accept`  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token variable&quot;&gt;$response&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name static-context&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withHeaders&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;withBody&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json_encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;application/json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$inbox&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Replying to a post&lt;/h3&gt;
&lt;p&gt;If you look at the post data above you may have noticed a null value of &lt;code&gt;inReplyTo&lt;/code&gt;. This is the part that needs to be filled in to reply to a specific post. Say I was replying to &lt;a href=&quot;https://social.lol/@robb/109863669770547458&quot;&gt;this &lt;em&gt;excellent&lt;/em&gt; post&lt;/a&gt; by a handsome internet person I need to include the URL as the value for &lt;code&gt;inReplyTo&lt;/code&gt; like so:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;inReplyTo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string single-quoted-string&quot;&gt;&#39;https://social.lol/@robb/109863669770547458&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Any posts with that set will show up as replies to the original post.&lt;/p&gt;
&lt;h3&gt;A note on attachments&lt;/h3&gt;
&lt;p&gt;nb: I&#39;ve only tested images because it&#39;s unlikely I&#39;ll need video any time soon.&lt;/p&gt;
&lt;p&gt;Attachments are included as an array in the post JSON with their mime type, url, alt text, width/height, and something I hadn&#39;t heard of before: a &lt;a href=&quot;https://blurha.sh/&quot;&gt;blurhash&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Document&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;mediaType&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;imag/jpeg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;http://placekitten.com/200/300&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A kitten&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;blurhash&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;L46[2Hofofof00j[offQ~qofofof&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;width&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;	&lt;span class=&quot;token property&quot;&gt;&quot;height&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A blurhash is &amp;quot;&lt;em&gt;a compact representation of a placeholder for an image.&lt;/em&gt;&amp;quot;. So when you see blurry images loading on Mastodon, these are blurhashes. To make one you need a library for your chosen language which in my case was PHP and I used &lt;a href=&quot;https://github.com/bepsvpt/blurhash&quot;&gt;&lt;code&gt;bepsvpt/blurhash&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-php&quot;&gt;&lt;code class=&quot;language-php&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$hash&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;blurhash&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$attachment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// L46[2Hofofof00j[offQ~qofofof&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there you go. Everything I (think) I understand about ActivityPub. All of the code for Bugle is &lt;a href=&quot;https://github.com/rknightuk/bugle&quot;&gt;on GitHub&lt;/a&gt; for your perusal.&lt;/p&gt;
&lt;h3&gt;Links and Resources&lt;/h3&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://lewisdale.dev&quot;&gt;Lewis&lt;/a&gt; for his help with verify requests. Articles and implementations I found helpful to work out how all this works:&lt;/p&gt;
&lt;h4&gt;Articles&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://justingarrison.com/blog/2022-12-06-mastodon-files-instance/&quot;&gt;Mastodon instance with 6 files - Justin Garrison&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://macwright.com/2022/12/09/activitypub.html&quot;&gt;Playing with ActivityPub - macwright.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/&quot;&gt;How to make friends and verify requests - Mastodon Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hacks.mozilla.org/2018/11/decentralizing-social-interactions-with-activitypub/&quot;&gt;Decentralizing Social Interactions with ActivityPub - Mozilla Hacks - the Web developer blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lewisdale.dev/post/you-can-be-friends-with-my-blog/&quot;&gt;You can be friends with my blog | LewisDale.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://magazine.joomla.org/all-issues/february-2023/turning-the-joomla-website-into-an-activitypub-server&quot;&gt;Turning the Joomla website into an ActivityPub server and being an independent participant in the Fediverse - A start - The Joomla Community Magazine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://seb.jambor.dev/posts/activitypub-academy/&quot;&gt;ActivityPub.Academy - Sebastian Jambor&#39;s blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://seb.jambor.dev/posts/understanding-activitypub/&quot;&gt;Understanding ActivityPub - Sebastian Jambor&#39;s blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tinysubversions.com/notes/reading-activitypub/&quot;&gt;reading-activitypub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Implementations&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dariusk/express-activitypub&quot;&gt;dariusk/express-activitypub: A very simple reference implementation of an ActivityPub server using Express.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.org/plugins/activitypub/&quot;&gt;ActivityPub – WordPress plugin | WordPress.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/LewisDaleUK/slap&quot;&gt;LewisDaleUK/slap: Super Lightweight Activity Pub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/&quot;&gt;A (tiny, incomplete, single user, write-only) ActivityPub server in PHP – Terence Eden’s Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>I built Bugle, an ActivityPub server with Laravel and PHP. These are my notes on how it all works to the best of my understanding</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The Biology of the Hey Bear Fruits Makes No Sense</title>
    <link href="https://rknight.me/blog/biology-of-hey-bear-fruits/"/>
    <updated>2023-06-22T17:44:51Z</updated>
    <id>https://rknight.me/biology-of-hey-bear-fruits/</id>
    <content type="html">&lt;p&gt;Hey Bear is &lt;a href=&quot;https://www.youtube.com/channel/UCtf9cFBJkHVAf2qMqF01xYg&quot;&gt;a YouTube channel&lt;/a&gt; with videos of dancing fruits, vegetables, and other nonsense designed to &lt;s&gt;make kids stfu&lt;/s&gt; entertain young children. It works. &lt;a href=&quot;https://rknight.me/micro/tags/babyknight/&quot;&gt;Baby Knight&lt;/a&gt; loves it.&lt;/p&gt;
&lt;p&gt;Last night my partner asked if I was okay because I looked distant and downtrodden. I wasn&#39;t sad or tired, I was pondering the biology of the fruits that dance in these videos.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/hey-bear-fruit-banner.jpg&quot; alt=&quot;Hey Bear Fruits&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The pineapple, Baby Knight&#39;s favourite, is a classic fruit-with-a-face; eyes and a mouth on the outside rind of the pineapple. Same with the strawberry, blueberry, and a bunch of others. Pretty standard fare for a children&#39;s cartoon, they seem to love it. Beyond those it gets a bit weird.&lt;/p&gt;
&lt;p&gt;A single orange, in the Hey Bear cinematic universe, is actually two creatures. The face is on the fleshy inside of each half but how did they get like that? Does a bigger fruit, or a human perhaps, have to cut them in half so they can see and talk and do whatever a living orange half does? What happens if said cutter slices off-centre, does one of them die while the other stays alive but has a part of their sibling&#39;s face on theirs, forever haunted by the memory.&lt;/p&gt;
&lt;p&gt;The banana&#39;s face is &lt;em&gt;inside&lt;/em&gt; the peel, able to see only when it&#39;s pulled back. Is there a ceremony for this with family and friends gathered round as the local face-revealer performs the act? Perhaps cards are sent to the parents, adorned with &amp;quot;congrats on your baby&#39;s face&amp;quot; and &amp;quot;Let&#39;s face it, today is a good day&amp;quot; on the front. They don&#39;t seem to have the ability to hear or make sound so the face is probably pretty important. Maybe the movie Face-Off is unsettling in their world, or that sewed-up-mouth scene from the Matrix.&lt;/p&gt;
&lt;p&gt;And finally the millennial favourite, the avocado. The one we see on screen has the stone in tact but we never other half, the sibling. Is the stoneless sibling an outcast in Hey Bear world or are they lauded for surviving without a fairly important part of an avocado? We might never know.&lt;/p&gt;
</content>
    <summary>I've watched too much Hey Bear and wrote about how weird it is</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Asset Lifespan Spreadsheet</title>
    <link href="https://rknight.me/blog/asset-lifespan-spreadsheet/"/>
    <updated>2023-06-02T16:22:40Z</updated>
    <id>https://rknight.me/asset-lifespan-spreadsheet/</id>
    <content type="html">&lt;p&gt;In &lt;a href=&quot;https://listen.hemisphericviews.com/020&quot;&gt;episode 20 of Hemispheric Views&lt;/a&gt; Andrew talks about his asset lifespan spreadsheet which shows the cost of an item, the date purchased, and the cost per week for said item.&lt;/p&gt;
&lt;p&gt;I figured I&#39;d have a crack at making my own and after some wrangling with formula in Numbers I was able to get something up and running. The key part was using the &lt;code&gt;DATEDIF&lt;/code&gt; function to get how many days it has been since purchase:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=(cost_of_item / DATEDIF(date_purchased, todays_date, diff_type))

=(B3 / DATEDIF(B2, TODAY, &amp;quot;D&amp;quot;) / 7) // for cost per week
=(B3 / DATEDIF(B2, TODAY, &amp;quot;M&amp;quot;)) // for cost per month
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which gives me an output like this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;A&lt;/th&gt;
&lt;th&gt;B&lt;/th&gt;
&lt;th&gt;C&lt;/th&gt;
&lt;th&gt;D&lt;/th&gt;
&lt;th&gt;E&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Product&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Purchase Date&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cost Per Week&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Cost Per Month&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ATH-M50X&lt;/td&gt;
&lt;td&gt;2015-12-13&lt;/td&gt;
&lt;td&gt;£85.60&lt;/td&gt;
&lt;td&gt;£0.22&lt;/td&gt;
&lt;td&gt;£0.96&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I don&#39;t know what I&#39;m going to do with this information beyond obsess over it but I do know I&#39;m getting my money&#39;s worth with those Audio-Technica headphones.&lt;/p&gt;
</content>
    <summary>My asset lifespan spreadsheet</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Brian Butterfield Diet Soundboard</title>
    <link href="https://rknight.me/blog/brian-butterfield-diet-soundboard/"/>
    <updated>2023-05-22T14:27:43Z</updated>
    <id>https://rknight.me/brian-butterfield-diet-soundboard/</id>
    <content type="html">&lt;p&gt;Over the weekend I spent some time splitting the audio from &lt;a href=&quot;https://www.youtube.com/watch?v=1NjTWvl8x-U&quot;&gt;the Brian Butterfield Diet sketch&lt;/a&gt; and then subsequently the &lt;a href=&quot;https://www.youtube.com/watch?v=Nyk6sXHY9Vg&quot;&gt;Christmas version&lt;/a&gt;. Both of these sketches are from &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Peter_Serafinowicz_Show&quot;&gt;The Peter Serafinowicz Show&lt;/a&gt; from 2007.&lt;/p&gt;
&lt;p&gt;I split the audio using &lt;a href=&quot;https://www.felttip.com/ss/&quot;&gt;Sound Studio&lt;/a&gt; which has a handy &amp;quot;split by markers&amp;quot; feature then used &lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy data files&lt;/a&gt; to output those files including some titles from a JSON files of all the audio. As much as I&#39;d like to sit and sketch some terrible icons for each food item I went with &lt;a href=&quot;https://fontawesome.com&quot;&gt;Font Awesome&lt;/a&gt; to save some time.&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&quot;https://treatday.rknight.me/&quot;&gt;Brian Butterfield Diet Soundboard&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A soundboard for the Brian Butterfield Diet</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>One Year of Pizza Making</title>
    <link href="https://rknight.me/blog/one-year-of-pizza-making/"/>
    <updated>2023-05-03T12:24:32Z</updated>
    <id>https://rknight.me/one-year-of-pizza-making/</id>
    <content type="html">&lt;p&gt;In November 2021 I bought an &lt;a href=&quot;https://uk.ooni.com/products/ooni-fyra&quot;&gt;Ooni Frya 12&lt;/a&gt; (thanks Black Friday discounts!) and since then I&#39;ve used it somewhere between 10 and 15 times. Each time I&#39;ve managed to make &lt;em&gt;something&lt;/em&gt; about the pizza better; the sauce, the dough, the topping ratio. Herein lies my notes about making better pizzas.&lt;/p&gt;
&lt;p&gt;For all my pizzas, I&#39;ve used the &lt;a href=&quot;https://ooni.com/blogs/recipes/classic-pizza-dough&quot;&gt;Ooni classic dough recipe&lt;/a&gt; and I&#39;m always aiming for a (sort of) Neapolitan style pizza.&lt;/p&gt;
&lt;h3&gt;Equipment&lt;/h3&gt;
&lt;p&gt;When I bought the oven I also picked up two peels: a &lt;a href=&quot;https://uk.ooni.com/collections/accessories/products/ooni-wooden-pizza-peel&quot;&gt;wooden one&lt;/a&gt; and a &lt;a href=&quot;https://uk.ooni.com/collections/accessories/products/ooni-pizza-peel&quot;&gt;metal one&lt;/a&gt;. I tend to only use the metal one so the wooden one has just become a standard chopping board. Ooni&#39;s accessories are far more expensive than other brands so I picked up a much cheaper &lt;a href=&quot;https://www.amazon.co.uk/dp/B08BFJ3QX5&quot;&gt;dough scraper&lt;/a&gt; on Amazon and I plan to get a &lt;a href=&quot;https://uk.ooni.com/collections/accessories/products/ooni-pizza-turning-peel&quot;&gt;turning peel&lt;/a&gt; at some point but I won&#39;t be paying Ooni&#39;s price.&lt;/p&gt;
&lt;h3&gt;Dough&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pizza-first.jpg&quot; alt=&quot;My first attempt&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My first batch was reasonably tasty but completely misshapen and definitely not thin enough. I figured using a rolling pin would be fine for rolling out the dough but that doesn&#39;t really get it thin enough and also removes a lot of the gas that makes a nice fluffy but crunchy crust. Rolling also made the dough stick to the peel and was really difficult to slide it off into the oven, even with a lot of flour underneath.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Entzcl8q7H4&quot;&gt;This video from Ooni&lt;/a&gt; helped a lot with working out the stretching technique. I&#39;d also recommend any of &lt;a href=&quot;https://www.youtube.com/playlist?list=PL_f8scwrXT8tfSJpDPfGozK2QKj-mEmCA&quot;&gt;Brian Lagerstrom&#39;s pizza videos&lt;/a&gt; to see how he strengthens the dough before proofing.&lt;/p&gt;
&lt;p&gt;I used bread flour I had lying around for the first attempt which I&#39;ve since found out is not ideal. 00 flour, which is a much finer flour, is far better. I switched to &lt;a href=&quot;https://www.sainsburys.co.uk/gol-ui/product/all-flour/sainsburys-grade-pasta-flour--taste-the-difference-1kg&quot;&gt;Sainsbury&#39;s 00 flour&lt;/a&gt; and then recently to &lt;a href=&quot;https://www.rattonpantry.co.uk/products/caputo%C2%AE-blue-pizzeria-00-italian-pizza-flour&quot;&gt;Caputo Pizzeria 00&lt;/a&gt;. Each time the dough has gotten tastier and much easier to stretch and shape. One other change I&#39;ve made is better yeast. I previously used Tesco dried yeast but I found this wasn&#39;t raising the dough as much as I liked, so I switched to &lt;a href=&quot;https://www.rattonpantry.co.uk/products/caputo-yeast-100g&quot;&gt;Caputo yeast&lt;/a&gt; which has much better results.&lt;/p&gt;
&lt;p&gt;I mix everything by hand (if someone wants to buy me a stand mixer I won&#39;t say no) in a metal mixing bowl, and use that for the first 2 hour proofing, then transfer the individual balls of dough into &lt;a href=&quot;https://www.amazon.co.uk/dp/B07D7MNHVP&quot;&gt;these pots&lt;/a&gt;, with a bit of oil to stop them from sticking, and leave them to proof for another 2 hours. If I&#39;m making more than I need I freeze after the first proof and get them out 12-24 hours before I need them and defrost in the fridge.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pizza-pot.jpg&quot; alt=&quot;Dough in a pot&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Sauce&lt;/h3&gt;
&lt;p&gt;I want my sauce to be as easy as possible to make and after some messing around with different recipes, this is what I&#39;ve come up with for a tasty but easy-to-make sauce:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;400g chopped tomatoes or passata&lt;/li&gt;
&lt;li&gt;100g tomato puree&lt;/li&gt;
&lt;li&gt;5g garlic powder&lt;/li&gt;
&lt;li&gt;5g salt&lt;/li&gt;
&lt;li&gt;5g pepper&lt;/li&gt;
&lt;li&gt;5g chilli flakes (optional)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is usually enough for 6-10 pizzas.&lt;/p&gt;
&lt;h3&gt;Toppings&lt;/h3&gt;
&lt;p&gt;My partner is a bit fussier than I am so we&#39;ve mostly stuck to chicken and ham for toppings but if I have friends round I&#39;ll grab some pepperoni or similar from the supermarket. We&#39;ve used cheap ham if we have it in the fridge and even that tastes great when combined with the sauce and cheese.&lt;/p&gt;
&lt;p&gt;Speaking of cheese, because of availability we&#39;ve mostly used cheddar which has been fine. Recently I picked up some aged mozzarella and used a 50/50 mix of that and cheddar and it tastes fantastic. &lt;a href=&quot;https://www.sainsburys.co.uk/gol-ui/product/galbani-cucina-mozzarella%C2%A0cheese%C2%A0400g&quot;&gt;Galbani Cucina Mozzarella&lt;/a&gt; is the only aged mozzarella I&#39;ve been able to find that is available in UK supermarkets.&lt;/p&gt;
&lt;p&gt;Finally some other ingredients I&#39;ve been enjoying:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://jdshothoney.com&quot;&gt;JDs Hot Honey&lt;/a&gt; which I pop on right as the pizza comes out the over adds a nice bit of sweet flavour.&lt;/li&gt;
&lt;li&gt;Candied Jalapenos. I&#39;ve been using &lt;a href=&quot;https://www.amazon.co.uk/Haynes-Gourmet-Candied-Jalapenos-%C2%AE/dp/B07JDSP47S/&quot;&gt;these ones from Haynes&lt;/a&gt; but I have some fresh jalapenos on the way to attempt to make my own.&lt;/li&gt;
&lt;li&gt;A liberal sprinkle of parmesan (or whatever hard italian cheese I can get my hands on).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pizza-latest.jpg&quot; alt=&quot;My latest pizza&quot; /&gt;&lt;/p&gt;
</content>
    <summary>Things I've learnt in a year or so of making pizza</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The Knightpool</title>
    <link href="https://rknight.me/blog/the-knightpool/"/>
    <updated>2023-03-09T10:02:00Z</updated>
    <id>https://rknight.me/the-knightpool/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://social.lol/@robb/109988701670297916&quot;&gt;From me, yesterday&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We setup a baby name pool at work, £1 a guess. We have 50 names, £51 in the pot. Someone has guessed the name so no money for me.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some additional rules we discussed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the correct answer is guessed by more than one person, the pot is split&lt;/li&gt;
&lt;li&gt;Spelling is not important. So &amp;quot;Emelia&amp;quot; and &amp;quot;Amelia&amp;quot; are the same name for the purposes of the Knightpool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m calling this the Knightpool because I can and definitely not &lt;a href=&quot;https://www.marvel.com/characters/deadpool-wade-wilson/in-comics&quot;&gt;stealing the idea from Marvel&lt;/a&gt;. Here are the 50 names that have been guessed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Abby&lt;/li&gt;
&lt;li&gt;Alice&lt;/li&gt;
&lt;li&gt;Amy&lt;/li&gt;
&lt;li&gt;Ava&lt;/li&gt;
&lt;li&gt;Ayla&lt;/li&gt;
&lt;li&gt;Beth&lt;/li&gt;
&lt;li&gt;Blair&lt;/li&gt;
&lt;li&gt;Chantell&lt;/li&gt;
&lt;li&gt;Chloe&lt;/li&gt;
&lt;li&gt;Claire&lt;/li&gt;
&lt;li&gt;Cleo&lt;/li&gt;
&lt;li&gt;Daisy&lt;/li&gt;
&lt;li&gt;Ella&lt;/li&gt;
&lt;li&gt;Ellie&lt;/li&gt;
&lt;li&gt;Elsie&lt;/li&gt;
&lt;li&gt;Emilia&lt;/li&gt;
&lt;li&gt;Emma&lt;/li&gt;
&lt;li&gt;Eve&lt;/li&gt;
&lt;li&gt;Evie&lt;/li&gt;
&lt;li&gt;Faye&lt;/li&gt;
&lt;li&gt;Flick&lt;/li&gt;
&lt;li&gt;Freya&lt;/li&gt;
&lt;li&gt;Gemma&lt;/li&gt;
&lt;li&gt;Grace&lt;/li&gt;
&lt;li&gt;Hannah&lt;/li&gt;
&lt;li&gt;Jane&lt;/li&gt;
&lt;li&gt;Jess&lt;/li&gt;
&lt;li&gt;Jill&lt;/li&gt;
&lt;li&gt;Jo (note: Two people guessed this name)&lt;/li&gt;
&lt;li&gt;Joy&lt;/li&gt;
&lt;li&gt;Kate&lt;/li&gt;
&lt;li&gt;Kayleigh&lt;/li&gt;
&lt;li&gt;Laura&lt;/li&gt;
&lt;li&gt;Leah&lt;/li&gt;
&lt;li&gt;Lilly&lt;/li&gt;
&lt;li&gt;Liz&lt;/li&gt;
&lt;li&gt;Lucy&lt;/li&gt;
&lt;li&gt;Maisie&lt;/li&gt;
&lt;li&gt;Mia&lt;/li&gt;
&lt;li&gt;Millie&lt;/li&gt;
&lt;li&gt;Nora&lt;/li&gt;
&lt;li&gt;Olivia&lt;/li&gt;
&lt;li&gt;Paige&lt;/li&gt;
&lt;li&gt;Phoebe&lt;/li&gt;
&lt;li&gt;Quinn&lt;/li&gt;
&lt;li&gt;Rose&lt;/li&gt;
&lt;li&gt;Sarah&lt;/li&gt;
&lt;li&gt;Sophie&lt;/li&gt;
&lt;li&gt;Tess&lt;/li&gt;
&lt;li&gt;Zoe&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>The list of baby name guesses in the Knightpool</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Food Graveyard</title>
    <link href="https://rknight.me/blog/food-graveyard/"/>
    <updated>2023-02-24T22:54:57Z</updated>
    <id>https://rknight.me/food-graveyard/</id>
    <content type="html">&lt;p&gt;Discontinued food items I miss.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gFurmW0iajM&quot;&gt;Fruit Allsorts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://inews.co.uk/inews-lifestyle/food-and-drink/brannigans-crisps-discontinued-pub-classic-britons-mourning-657852&quot;&gt;Brannigans beef and mustard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.collectingcandy.com/wordpress/?attachment_id=4204&quot;&gt;Wonkalate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://candymail.co.uk/products/campino-strawberry-and-yogurt-120g&quot;&gt;Campino Strawberry and Yoghurt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ukfoodexport.com/nestle_toffee_crisp_honeycomb_38g/&quot;&gt;Toffee Crisp honeycomb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mirror.co.uk/news/uk-news/nestl-discontinued-tooty-frooties-after-14175754&quot;&gt;Tooty Frooties&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mingles&quot;&gt;Mingles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.betterretailing.com/br/product-news/walkers-launches-limited-edition-sensations-to-mark-coronation/&quot;&gt;Sensations Regal Lamb and Mint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>Discontinued food that I want back</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>No More Ratings</title>
    <link href="https://rknight.me/blog/no-more-ratings/"/>
    <updated>2023-02-14T09:52:15Z</updated>
    <id>https://rknight.me/no-more-ratings/</id>
    <content type="html">&lt;p&gt;When I used to use &lt;a href=&quot;http://plotapp.io/&quot;&gt;Plot&lt;/a&gt; (RIP) to track movies that had a thumbs up or down system. When I switched to my own CMS for this I did the same thing. Then when I switched to Letterboxd I translated what was essentially a 1-3 rating system to the five-star system (even though it&#39;s actually out of ten not five) Letterboxd uses. From &lt;a href=&quot;https://letterboxd.com/rknightuk/&quot;&gt;my Letterboxd profile&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;★☆☆☆☆ : Never again&lt;/p&gt;
&lt;p&gt;★★★☆☆ : Fine&lt;/p&gt;
&lt;p&gt;★★★★★ : Good movie, would watch again&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The problem with this system is I mostly don&#39;t watch bad movies. Or a better way to put it is I kinda like &lt;a href=&quot;https://en.wikipedia.org/wiki/Fast_&amp;amp;_Furious&quot;&gt;bad movies&lt;/a&gt;. Despite knowing intellectually that &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Shawshank_Redemption&quot;&gt;Shawshank Redemption&lt;/a&gt; is a &amp;quot;better&amp;quot; movie than &lt;a href=&quot;https://en.wikipedia.org/wiki/Olympus_Has_Fallen&quot;&gt;Olympus Has Fallen&lt;/a&gt; they&#39;re both rated 5 stars in my system. I could change my system to use the full spectrum of the five stars but I just don&#39;t have the energy or the inclination to do it. How do I decide what gets 4.5 stars and what gets a 5? Is there really a discernible difference between those two ratings? Also, who gives a shit what number I&#39;ve ordained upon a movie?&lt;/p&gt;
&lt;p&gt;So fuck it. No more ratings.&lt;/p&gt;
</content>
    <summary>Why I'm not rating movies (or anything) any more</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Add to MusicThread Shortcut</title>
    <link href="https://rknight.me/blog/add-to-musicthread-shortcut/"/>
    <updated>2023-02-06T18:04:43Z</updated>
    <id>https://rknight.me/add-to-musicthread-shortcut/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://musicthread.app/&quot;&gt;MusicThread&lt;/a&gt; is &amp;quot;&lt;em&gt;a website to create and share lists of music&lt;/em&gt;&amp;quot; by &lt;a href=&quot;https://mastodon.social/@edwellbrook&quot;&gt;Ed Wellbrook&lt;/a&gt;. I recently started using it to save &lt;a href=&quot;https://musicthread.app/thread/2L6IuBPKCCo7fsA8SFyXZLirH5W&quot;&gt;new tracks I&#39;ve found&lt;/a&gt; and &lt;a href=&quot;https://musicthread.app/thread/2L6LZz60026Onq3waGuwt7WdJ5x&quot;&gt;new albums&lt;/a&gt;, which are then cross-posted to &lt;a href=&quot;https://social.lol/@robb&quot;&gt;my Mastodon account&lt;/a&gt; with &lt;a href=&quot;https://echo.rknight.me&quot;&gt;Echo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The iOS app, currently in beta, has a share sheet extension for adding to a thread, but for MacOS I needed to make something in Shortcuts. The shortcut I&#39;ve made (after a lot of ranting about how bad shortcuts is) can either ask for a music link to add, or be used directly from Apple Music under the share menu. It then asks which thread to add the link to.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/d127fd30d412423b86c06bcff7f9cea6&quot;&gt;Download Add to MusicThread Shortcut&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>A shortcut to add new tracks or albums to MusicThread</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Notes on Migrating a Wordpress Site to Eleventy</title>
    <link href="https://rknight.me/blog/note-on-migrating-wordpress-site-eleventy/"/>
    <updated>2023-01-31T22:13:16Z</updated>
    <id>https://rknight.me/note-on-migrating-wordpress-site-eleventy/</id>
    <content type="html">&lt;p&gt;I recently helped my friend Tim move &lt;a href=&quot;https://nahumck.me/&quot;&gt;his site&lt;/a&gt; from a Wordpress install to a much simpler Eleventy setup. The biggest hurdle was transforming the Wordpress exported data into Markdown files. Thankfully &lt;a href=&quot;https://github.com/lonekorean/wordpress-export-to-markdown&quot;&gt;&lt;code&gt;wordpress-export-to-markdown&lt;/code&gt;&lt;/a&gt; exists. This is a command line tool that takes a wordpress export, puts all the posts in markdown files, and downloads all the images contained in the posts.&lt;/p&gt;
&lt;p&gt;I did make an adjustment to this script so I could add a &lt;code&gt;permalink&lt;/code&gt; attribute to each post by editing the &lt;code&gt;parser.js&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-diff&quot;&gt;&lt;code class=&quot;language-diff&quot;&gt;frontmatter: {&lt;br /&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   title: getPostTitle(post),&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token inserted-sign inserted&quot;&gt;&lt;span class=&quot;token prefix inserted&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   permalink: `${getPostSlug(post)}/index.html`,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token unchanged&quot;&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   date: getPostDate(post),&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   categories: getCategories(post),&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token prefix unchanged&quot;&gt; &lt;/span&gt;&lt;span class=&quot;token line&quot;&gt;   tags: getTags(post)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The image download will take a while but once it was done I had all the posts and all the images ready to pop into an Eleventy site.&lt;/p&gt;
&lt;p&gt;To match Tim&#39;s existing site it needed support for markdown footnotes and image captions. As a side note here, footnotes &lt;em&gt;do not&lt;/em&gt; export well from Wordpress via the CLI tool so I had to manually fix all of them which was not fun. &lt;a href=&quot;https://www.alpower.com/&quot;&gt;Al Power&lt;/a&gt; had an article for both of these features which was handy. To add footnote support I followed the steps in &lt;a href=&quot;https://www.alpower.com/tutorials/configuring-footnotes-with-eleventy/&quot;&gt;this article&lt;/a&gt; which outlines how to include &lt;code&gt;markdown-it-footnote&lt;/code&gt; for the markdown parsing and &lt;a href=&quot;https://www.alpower.com/tutorials/adding-figures-with-captions-to-images-in-markdown-with-eleventy/&quot;&gt;this article&lt;/a&gt; to add image captions.&lt;/p&gt;
&lt;p&gt;All in all it went fairly smoothly - without &lt;code&gt;wordpress-export-to-markdown&lt;/code&gt; I would have had to write my own parsing script which I&#39;m very glad I didn&#39;t have to do.&lt;/p&gt;
</content>
    <summary>Some helpful notes and tools for migrating an existing Wordpress site to Eleventy</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Additional Webmention Resources</title>
    <link href="https://rknight.me/blog/additional-webmention-resources/"/>
    <updated>2023-01-31T00:00:00Z</updated>
    <id>https://rknight.me/additional-webmention-resources/</id>
    <content type="html">&lt;p&gt;Some more links and tools I&#39;ve found or had saved about webmentions. Read my post on &lt;a href=&quot;/adding-webmentions-to-your-site/&quot;&gt;adding webmentions here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/remy/wm&quot;&gt;@remy/webmention&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Sadly the webapp side of this is &lt;a href=&quot;https://remysharp.com/2023/01/30/on-vercel-if-some-of-my-sites-are-down&quot;&gt;down at the moment&lt;/a&gt; but the command line tool for &lt;em&gt;sending&lt;/em&gt; webmentions is completely standalone.&lt;/p&gt;
&lt;p&gt;You can pass the script a url or an RSS feed and it will scan it to find links, confirm those sites accept web mentions, and send those mentions. I ran it once on my whole feed to send any mentions and then added it to my build steps to run it on the latest post:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;npx webmention /path/to/feed.xml &lt;span class=&quot;token parameter variable&quot;&gt;--limit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--send&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/CodeFoodPixels/eleventy-plugin-webmentions&quot;&gt;eleventy-plugin-webmentions&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;An eleventy plugin to fetch webmentions and helper methods to display them&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why didn&#39;t I look for a plugin when I was doing webmentions? No idea. This is going on my list to review and see if I can streamline my code a bit.&lt;/p&gt;
&lt;h3&gt;Links&lt;/h3&gt;
&lt;p&gt;Some other articles I had saved related to this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://ashleykolodziej.com/add-webmentions-to-static-site/&quot;&gt;How I added Webmentions support to my static website | Ashley Kolodziej - Boston Freelance Web Designer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sia.codes/posts/webmentions-eleventy-in-depth/&quot;&gt;An In-Depth Tutorial of Webmentions + Eleventy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rowanmanning.com/posts/webmentions-for-your-static-site/&quot;&gt;Webmentions for your Static Site | Rowan Manning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-irl.info/scheduling-netlify-deployments-with-github-actions/&quot;&gt;Scheduling Netlify Deployments with Github Actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cactus.chat/&quot;&gt;Cactus Comments - Federated Web Comments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cassidyjames.com/blog/fediverse-blog-comments-mastodon/&quot;&gt;Toot toot! Mastodon-powered Blog Comments ⋅ Cassidy James Blaede&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git.lewisdale.dev/lewis/webmentions&quot;&gt;lewis/webmentions - OpenWebmentions - Gitea: Git with a cup of tea&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>Some more links and tools related to webmentions</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Adding Webmentions to Your Site</title>
    <link href="https://rknight.me/blog/adding-webmentions-to-your-site/"/>
    <updated>2023-01-30T00:00:00Z</updated>
    <id>https://rknight.me/adding-webmentions-to-your-site/</id>
    <content type="html">&lt;p&gt;Right off the bat, I read the following two articles to get a sense of how to do this so I won&#39;t go over too much of the same content but rather add some thoughts of my own about the process. I would highly recommend reading both of these.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://janmonschke.com/adding-webmentions-to-your-static-blog/&quot;&gt;Adding webmentions to your static blog by Jan Monschke&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mxb.dev/blog/using-webmentions-on-static-sites/&quot;&gt;Using Webmentions in Eleventy by Max Böck&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, I feel like I muddled through this to get it to work. JSON and API requests I can understand. The &lt;em&gt;how&lt;/em&gt; of webmentions I&#39;m still a bit confused on but we will proceed nonetheless.&lt;/p&gt;
&lt;h3&gt;What are webmentions?&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://webmention.net/&quot;&gt;Webmentions are&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a simple way to notify any URL when you link to it from your site&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sounds simple enough. It&#39;s a link (or a comment, or reply, or like) to an article on my site. What I do know of webmentions from sites like &lt;a href=&quot;https://localghost.dev/&quot;&gt;Sophie&#39;s&lt;/a&gt; and &lt;a href=&quot;https://www.zachleat.com/&quot;&gt;Zach&#39;s&lt;/a&gt; is that &lt;em&gt;somehow&lt;/em&gt; I can have likes, boosts, and replies from Mastodon show up on my blog posts.&lt;/p&gt;
&lt;h3&gt;How though?&lt;/h3&gt;
&lt;p&gt;This bit has confused me for months (I had a note about this dated November last year). Admittedly I didn&#39;t look too far into it but pretty much every article about webmentions will link to two sites: &lt;a href=&quot;https://webmention.io/&quot;&gt;webmention.io&lt;/a&gt; and &lt;a href=&quot;https://brid.gy/&quot;&gt;Bridgy&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Webmention dot io and IndieLogin&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt; is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a hosted service created to easily receive webmentions on any web page&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt; &lt;em&gt;collects&lt;/em&gt; your webmentions and exposes an API to be able to fetch these mentions but to start off you need to login which was my first hurdle: &lt;code&gt;We couldn&#39;t find any way to authenticate you using your website.&lt;/code&gt;. &lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt; uses &lt;a href=&quot;https://indielogin.com/setup&quot;&gt;IndieLogin&lt;/a&gt; to log you in and apparently I hadn&#39;t added &lt;code&gt;rel=&amp;quot;me&amp;quot;&lt;/code&gt; to any of my social links. So I added a Github link, deployed it, and was then able to login. Success.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; none&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://github.com/rknightuk&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;me&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;github.com/rknightuk&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once I logged in I was presented with tags to add to my site to accept webmentions so I promptly added those:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;webmention&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://webmention.io/rknight.me/webmention&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;pingback&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://webmention.io/rknight.me/xmlrpc&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, this system will work for &amp;quot;proper&amp;quot; webmentions (although not added to my site yet) but what about conversations on Mastodon? That&#39;s where Bridgy comes in.&lt;/p&gt;
&lt;h4&gt;Bridgy&lt;/h4&gt;
&lt;p&gt;Bridgy &amp;quot;connects your web site to social media&amp;quot; according to the home page but moreso it converts conversations on social media to webmentions to send back to &lt;a href=&quot;http://webmention.io&quot;&gt;webmention.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I went ahead and signed in with my Mastodon account. After a few minutes Bridgy started showing responses to some recent Mastodon posts that had links to my blog posts. I then went back to &lt;a href=&quot;http://webmention.io&quot;&gt;webmention.io&lt;/a&gt; and there they all were. I&#39;m not sure of the limitations of the initial scan but it only showed the last few posts I had done so I manually went and grabbed some Mastodon posts linking to my blog and put them in the &amp;quot;Resend for post&amp;quot; input box to grab some earlier responses.&lt;/p&gt;
&lt;h3&gt;Showing Webmentions on my Site&lt;/h3&gt;
&lt;p&gt;I&#39;m using &lt;a href=&quot;https://www.11ty.dev/docs/data-global/&quot;&gt;Eleventy data files&lt;/a&gt; extensively to power my &lt;a href=&quot;https://rknight.me/automating-my-now-page/&quot;&gt;now page&lt;/a&gt; so I knew this would be trivial to pull into my site. Because I already have my &lt;a href=&quot;https://github.com/rknightuk/api&quot;&gt;&amp;quot;api&amp;quot;&lt;/a&gt; I decided to fetch it there instead and &lt;em&gt;then&lt;/em&gt; pull it into my site. For the sake of simplicity assume you don&#39;t like making your life difficult and all this would exist in Eleventy (or your site of choice).&lt;/p&gt;
&lt;h4&gt;Fetching Mentions&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt; has &lt;a href=&quot;https://github.com/aaronpk/webmention.io#api&quot;&gt;an API&lt;/a&gt; to fetch mentions. There are a few different endpoints but I wasn&#39;t able to work out what all the differences were so I went with the &lt;code&gt;mention.jf2&lt;/code&gt; with no other options. &lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/webmentions.js&quot;&gt;Source on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// this API also accepts `since_id` to only get new mentions&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://webmention.io/api/mentions.jf2?token=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;webmentionskey&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;amp;per-page=1000&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newMentions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; body&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;children&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;ve set this up to run every hour on a cron, merge new data with the existing data, and then write the data to &lt;a href=&quot;https://api.rknight.me/api/webmentions.json&quot;&gt;a JSON file&lt;/a&gt;. &lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt; &lt;em&gt;does&lt;/em&gt; have an option for sending a webhook when a new mention comes in (under &amp;quot;settings&amp;quot;) but that might be a lot of rebuilding if a post gets popular so I&#39;m sticking with this method for now. Then in Eleventy, I fetch this data in &lt;a href=&quot;https://github.com/rknightuk/rknight.me/blob/master/src/_data/webmentions.js&quot;&gt;&lt;code&gt;src/_data/webmentions.js&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To get this to render on my post pages, I lifted most of &lt;a href=&quot;https://mxb.dev/blog/using-webmentions-on-static-sites/&quot;&gt;Max&#39;s solution&lt;/a&gt; with a few changes like grouping the different types of responses together. As an aside, I still don&#39;t know what a &lt;code&gt;mention-of&lt;/code&gt; webmention looks like or how one happens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 07/07/2023&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I finally got some data to see what &lt;code&gt;mention-of&lt;/code&gt; gives. I decided against showing these though because at least half of them didn&#39;t exist after only ~6 months.&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;entry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;author&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;card&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;photo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://blog.luiscarlospando.com/coding/2023/02/hay-nuevo-sistema-de-comentarios-en-mi-blog-2/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;published&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token null keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;wm-received&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023-07-07T00:18:46Z&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;wm-id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1693400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;wm-source&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://blog.luiscarlospando.com/coding/2023/02/hay-nuevo-sistema-de-comentarios-en-mi-blog-2/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;wm-target&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/adding-webmentions-to-your-site/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;mention-of&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://rknight.me/adding-webmentions-to-your-site/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;wm-property&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mention-of&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;wm-private&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// .eleventy.js&lt;/span&gt;&lt;br /&gt;eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addFilter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;webmentionsByUrl&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;webmentions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; allowedTypes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;in-reply-to&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;like-of&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;repost-of&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&#39;like-of&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&#39;repost-of&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token string-property property&quot;&gt;&#39;in-reply-to&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;hasRequiredFields&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; published&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; content &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; entry&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; author&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; published &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; content&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; filtered &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; webmentions&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; entry&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wm-target&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://rknight.me&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; allowedTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;entry&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wm-property&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    filtered&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wm-property&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isReply &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wm-property&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;in-reply-to&#39;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isValidReply &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isReply &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hasRequiredFields&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isReply&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isValidReply&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;                    m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sanitized &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sanitizeHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                    data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wm-property&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unshift&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;            data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;wm-property&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unshift&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; data&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// _templates/post.njk&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;set&lt;/span&gt; webmentionUrl &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; stripIndex &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; endset &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; include &lt;span class=&quot;token string&quot;&gt;&#39;webmentions.njk&#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// webmentions.njk&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Then the same again as this for `repost-of` and `in-reply-to`&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; mentions&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;like-of&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;h4&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Likes&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;h4&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;webmentions--likeboost&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; like &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; mentions&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;like-of&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;a target&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;_blank&quot;&lt;/span&gt; rel&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;noopener&quot;&lt;/span&gt; href&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{like.author.url}}&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;img src&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{like.author.photo}}&quot;&lt;/span&gt; title&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{{like.author.name}}&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; endfor&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; endif &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A little bit of CSS later and we have lift off:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/webmentions.png&quot; alt=&quot;Webmentions example&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You might even see some webmentions below this post if I&#39;m lucky.&lt;/p&gt;
</content>
    <summary>Some notes on what webmentions are and how I implemented them for this site</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Twitter Backup and Archiving Options</title>
    <link href="https://rknight.me/blog/twitter-backup-and-archiving-options/"/>
    <updated>2023-01-29T00:00:00Z</updated>
    <id>https://rknight.me/twitter-backup-and-archiving-options/</id>
    <content type="html">&lt;p&gt;If you want to make your Twitter archive a bit more useful than the standard backup Twitter give you, there are 3 options of varying complexity I&#39;m aware of.&lt;/p&gt;
&lt;h3&gt;Option 0: Don&#39;t do anything&lt;/h3&gt;
&lt;p&gt;This is by far the easiest option. Don&#39;t care about your tweets. Let them wither away into the ether. Be free from the shackles of hoarding your data.&lt;/p&gt;
&lt;h3&gt;Option 1: Tiny Subversions&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://tinysubversions.com/twitter-archive/make-your-own/&quot;&gt;Darius Kazemi of Tiny Subversions&lt;/a&gt; made this tool to make a self hosted, searchable archive. It&#39;s as simple as uploading the &lt;code&gt;.zip&lt;/code&gt; file of your archive, give it a minute, and the new archive will be downloaded.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/twitter-tiny-subversions.png&quot; alt=&quot;Tiny Subversions twitter archive&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Option 2: TwitVault&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://terhechte.github.io/twitvault/&quot;&gt;TwitVault/&lt;/a&gt; is a desktop App for Mac, Windows, and Linux that has the biggest feature set. Download it, login with your Twitter credentials, and let it do it&#39;s thing. This initial setup will pull everything is can from the Twitter API but that has limits: 3200 tweets and 800 mentions. Once that part of the setup is done (this can take a while), you can then pull in your full archive in the terminal.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/twitter-twitvault.png&quot; alt=&quot;TwitVault screenshot&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Option 3: Tweetback&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/tweetback/tweetback&quot;&gt;Tweetback&lt;/a&gt; is a tool built with &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; and is my current choice for making my archive available. You can see mine at &lt;a href=&quot;https://hellsite.rknight.me/&quot;&gt;hellsite.rknight.me&lt;/a&gt;. The steps to get this working are more involved than the previous options but I&#39;m a big fan of the output. I won&#39;t go through the steps here but the &lt;a href=&quot;https://github.com/tweetback/tweetback/blob/main/README.md&quot;&gt;readme&lt;/a&gt; has detailed instructions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/twitter-tweetback.png&quot; alt=&quot;Tweetback screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One other related part of Tweetback is &lt;a href=&quot;https://github.com/tweetback/tweetback-canonical&quot;&gt;tweetback-canonical&lt;/a&gt;. If you add your archive and username to the repository, anyone who uses Tweetback and has tweets that mention you, those tweets will link back to your archive rather than Twitter&#39;s website itself. For example, &lt;a href=&quot;https://hellsite.rknight.me/1489618994000805889/&quot;&gt;this tweet&lt;/a&gt; where I mention Zach links to &lt;a href=&quot;https://www.zachleat.com/twitter/1489616692678434816&quot;&gt;his archive&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>Three different options for managing your Twitter archive</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Letters with Jason Becker</title>
    <link href="https://rknight.me/blog/letters/"/>
    <updated>2023-01-28T00:00:00Z</updated>
    <id>https://rknight.me/letters/</id>
    <content type="html">&lt;p&gt;Letters is a ongoing project by &lt;a href=&quot;https://json.blog/2022/11/28/a-new-project.html&quot;&gt;Jason Becker&lt;/a&gt; that I was involved in for this month. The what:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Letters will involve me corresponding with someone else on the internet over the course of a month. Each week, we will each write a letter to each other. There are no set topics.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The why:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I was thinking about how much of our history (in the West at least) comes from important figures having extensive private correspondences that were saved, catalogued, and released after their deaths. And while I’d love some private pen pals, it just got me thinking that public letters are a rich way to discuss complex issues.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jason posted that in November and I thought it sounded like an interesting thing to be involved in. While I don&#39;t think we hit the heights of &amp;quot;historical figures discussing complex issues&amp;quot;, we did have conversations about taking stock, finding time for personal projects and hobbies, and of course my Topic of the Year™ 2022: DIY. Below are the four emails from me with Jason&#39;s responses (and links to the posts on Jason&#39;s site).&lt;/p&gt;
&lt;p&gt;Jason is doing this for the rest of the year which I&#39;m looking forward to.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;&lt;a href=&quot;https://json.blog/2023/01/01/letters-january-w.html&quot;&gt;Week 1: 2023-01-01&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Jason,&lt;/p&gt;
&lt;p&gt;We have only interacted briefly on Micro.blog so I figured I should start by introducing myself. I’m a 30-something developer working on software for the property industry. I live with my partner, Jess, and two cats in Portsmouth on the south coast of the UK.&lt;/p&gt;
&lt;p&gt;We have spent the past 12 months decorating and redoing every room in our house - the previous owners lived here since it was built in 1971 and hadn’t done any work to it since then. This involved me learning a whole set of new skills like floor laying, wallpapering, and fitting new skirting boards (baseboards for Americans).&lt;/p&gt;
&lt;p&gt;In July we found out my partner was pregnant with a girl and she is due in March 2023. This accelerated the timeline of getting the house finished but we are now ready for her arrival at least in terms of furniture and the nursery. Mentally ready? I’m not so sure.&lt;/p&gt;
&lt;p&gt;Look forward to hearing from you, Robb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Robb,&lt;/p&gt;
&lt;p&gt;First of all, congratulations on pending fatherhood! I’m glad we were able to slip in our month of correspondance before the pending sleep depravation.&lt;/p&gt;
&lt;p&gt;What an exciting and busy year. Even though we moved into our home 5 years ago (and it was new construction), I still feel like we need to keep decorating and redoing. Our work has been less skills-based and more “accumulating more stuff than I am comfortable owning”-based, since our new(ish) home is much larger than the 700 square feet we lived in previously. I have always found that I have ambitious of being handy in theory, but mostly fail when it comes to applying that ambition. At this stage, my partner Elsa just pays people to do things before telling me they’ve gone wrong or haven’t happened.&lt;/p&gt;
&lt;p&gt;I am curious, what room or project are you most proud of? I’m not quite “done”, but pretty close to having my office set up how I’d like. It was a big pandemic project since we got rid of the company office right away. Having my own space has changed my whole relationship with my home.&lt;/p&gt;
&lt;p&gt;I took a peek at the work you do and it’s fascinating. I have actually discussed this area (home management, focused on home inspections in the US followed by “asset management” and warranty support nad the like) with my work partner multiple times as an idea to pursue{^tech]. The intersection of home-renovation and your work must have been an interesting exercise. I’d be curious what you’ve learned managing your house that suprised you or changed your perspective on the work you do day to day.&lt;/p&gt;
&lt;p&gt;Thanks for your participation in Letters. I’m already enjoying this project, and I hope others will as well.&lt;/p&gt;
&lt;p&gt;Jason&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;https://json.blog/2023/01/10/letters-january-w.html&quot;&gt;Week 2: 2023-01-10&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Good Morning Jason,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;what room or project are you most proud of?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The office was my top priority (my partner had different ideas) as I spend 3-4 days a week working in there and I’m very proud of how that turned out. I built the desktop and matching shelves myself from scaffold boards because finding something in the exact size I wanted turned out to be fairly difficult. This was a project that took a few weekends of lots of sanding, glueing, and staining but the final results is something I’m very proud of. Here’s an in-progress shot and the final result in situ. I also did the faux wood-panelling in our bedroom which we’re both very pleased with.&lt;/p&gt;
&lt;p&gt;The work I do is primarily focused on property reports for tenants (inventories, fire risk assessments, etc) so there isn’t much crossover with renovating the house but I what I did learn is that planning is key. We wish we had spent a few weeks planning what we wanted to achieve before jumping into the renovation. There were definitely things that made our life a bit more difficult because we did some work when we should have waited for another job to be finished first.&lt;/p&gt;
&lt;p&gt;That sounds like an interesting job but it must be difficult to work with organisations like schools that can be slow and unwieldy to get new tech implemented. How long have you been doing that?&lt;/p&gt;
&lt;p&gt;I saw you posted yesterday about being ill, hope you’re feeling a bit better today?&lt;/p&gt;
&lt;p&gt;Speak soon,&lt;br /&gt;
Robb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Robb,&lt;/p&gt;
&lt;p&gt;Luckily, I am feeling better. Note to self, when you order a steak medium and it comes out &lt;em&gt;just barely rare&lt;/em&gt; just send the damn thing back. The day of suffering that followed was not worth it.&lt;/p&gt;
&lt;p&gt;I&#39;ve done some more work in my office since this last photo, but this is a &lt;a href=&quot;https://json.blog/2021/07/18/current-state-of.html&quot;&gt;not-terribly-inaccurate representation of where things are&lt;/a&gt;. I also use the IKEA pegboard. I did not quite get as fancy on the desk itself-- which is an IKEA Karlby 98&amp;quot; top that I had a friend cut to 80&amp;quot; and then added some really cool metal legs from an Etsy shop. When the pandemic hit we went 100% remote, which meant tha this room got transformed into an office. I probably have 6-10 scattered blog posts about the process that landed on the setup linked above-- most of the changes by now are additional plants and things hung on the wall (plus some equipment changes).&lt;/p&gt;
&lt;p&gt;I think it&#39;s pretty natural for the office to be the place you&#39;re most proud of-- it&#39;s one you get to call your own and the spot you&#39;re probably stuck spending the most time in.&lt;/p&gt;
&lt;p&gt;We&#39;ve been thinking about doing a similar paneling look either behind our bed or possibly behind our TV. Maybe that&#39;ll be a project for when we return home. It&#39;s hard to have a big wall behind a TV-- it looks bare without anything, but most things we could put there would be distracting.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://json.blog/uploads/2023/938df46b2f.jpg&quot;&gt;https://json.blog/uploads/2023/938df46b2f.jpg&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&#39;ve been working at my current company nearly 9 years. Before that, I worked at a university research center working with school districts on early warning systems, and before that, I worked for the state department of education. I think what&#39;s most challenging is that everyone is well-established. There aren&#39;t new school districts popping up building their systems and processes from scratch. The people, organizations, culture, and work processes are all fairly fixed. So we have to do things much more completely and better than most companies to even get in the door. Then we have to get a large set of folks on board so that we can deliver on our promise. We&#39;re a small team and we&#39;re supporting billions of dollars of budgeting and monitoring. There&#39;s a lot of technical/systems and cultural debt that we have to work with to succeed.&lt;/p&gt;
&lt;p&gt;That said, the opportunity for improvement is huge, and it&#39;s very satisfying when someone gets it and we can make their work so much easier and more effective.&lt;/p&gt;
&lt;p&gt;Looking forward to next week&lt;br /&gt;
Jason&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;https://json.blog/2023/01/19/letters-january-w.html&quot;&gt;Week 3: 2023-01-19&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Jason,&lt;/p&gt;
&lt;p&gt;A late reply this week - I completely forgot about this until very late last night.&lt;/p&gt;
&lt;p&gt;Your TV setup looks very similar to ours but we&#39;re lucky enough to have two wall lights behind it so the wall looks much less bare but you&#39;re right it&#39;s hard to put anything to garish there otherwise it&#39;s distracting.&lt;/p&gt;
&lt;p&gt;With 10 weeks to go, I&#39;ve been thinking a lot about technology and how that will affect my duaghter. &lt;a href=&quot;https://sallylait.com/blog/2022/08/25/digital-shadow-inheritance/&quot;&gt;This post&lt;/a&gt; in particular made me think about how much I&#39;m going to share about her online once she&#39;s here. I don&#39;t think there&#39;s any right answer but it has occupied my mind the past few days.  Come to think of it, the impending birth is basically the only thing I can think about at the moment. I&#39;m sure that we&#39;ll be fine but I can&#39;t help but worry that we won&#39;t have enough clothes or nappies, or something I haven&#39;t even thought of will go wrong.&lt;/p&gt;
&lt;p&gt;As for non-baby things, I&#39;ve been having fun messing around with the omg.lol API &lt;a href=&quot;https://github.com/rknightuk/omglolcli&quot;&gt;building a CLI to interact with the service&lt;/a&gt; and I&#39;m working on add a /now page to my website (as well as the new omg.lol now pages). How has your week been this week?&lt;/p&gt;
&lt;p&gt;Speak soon,&lt;br /&gt;
Robb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Robb,&lt;/p&gt;
&lt;p&gt;Easily excusing the &amp;quot;late&amp;quot; reply (rules are once per week, doesn&#39;t have to be right at the start), with a later reply of my own. This week has been incredibly busy at work as the post-holiday break, post-three day weekend, we&#39;re really back at it and in it, started to kick in. It&#39;s been long but rewarding-- one of those weeks where you&#39;re exhausted, but I&#39;m doing the kind of work I do well bringing the energy and attention I need to.&lt;/p&gt;
&lt;p&gt;In particular, I&#39;ve recently reorganized our team so that I have slightly smaller set of direct reports that are more &amp;quot;coherent&amp;quot; structurally-- I am managing directly one person who leads each function below me. It&#39;s too early to say if this is working better for the whole team, but this week made me feel confident that it works better for &lt;em&gt;me&lt;/em&gt;, which is really important for avoiding burn out.&lt;/p&gt;
&lt;p&gt;On the TV side, wall lights were another thing we considered-- a sconce on each side just to give it &lt;em&gt;something&lt;/em&gt;. It just feels strange to have so much blank space &lt;em&gt;above&lt;/em&gt; the TV as well. I need someone to, I don&#39;t know, share a Pinterest board or something with me so I can figure out what people actually do. The entire dilemma of what to do behind the TV reinforces a personal frustration of mine. It feels wrong that our &amp;quot;living room&amp;quot; is oriented toward a television. I would like for things to be different, but I don&#39;t think my partner or her mother would be sufficiently on board to make that change. It&#39;s more aspirational, really, to make sure that all television time is &lt;em&gt;appointment&lt;/em&gt; time and not casual watching.&lt;/p&gt;
&lt;p&gt;I cannot imagine the stack of worry that comes with being just weeks away from being a dad. It&#39;s good to work with fun new tools right now while you can-- a good distraction before side projects get put aside for a while. My gut is that it&#39;s not worth worrying too much about online presence. I&#39;m not a parent, and I&#39;m not facing that decision, but my gut is that it&#39;s easy to overthink the consequences (or lack thereof). Short of straight up exploitation, which is rare, these things seem to work out ok for parents and kids regardless of the choices they make. That&#39;s not to say the choices don&#39;t matter, but it seems like there aren&#39;t wrong choices.&lt;/p&gt;
&lt;p&gt;I&#39;m a big fan of /now pages (I really need to update mine). I really value the narrative of a Now page. For me, it&#39;s a time I get to think about what matters that gets lost in the series of smaller posts or dripped out updates. I have resisted adding any &amp;quot;automated&amp;quot; elements-- it&#39;d be easy to add the book I&#39;m currently reading, for example, or maybe something like starred articles from my RSS reader. Something to think about.&lt;/p&gt;
&lt;p&gt;We&#39;re coming to the end of our time in Mexico. I&#39;m thinking a lot about what makes home, well, home, and what I&#39;ve learned about where I want to live and what I want my life to be like from 2+ months away. It&#39;s a different kind of taking stock than becoming a parent, but I find myself taking stock nonetheless.&lt;/p&gt;
&lt;p&gt;Looking forward to next week,&lt;br /&gt;
Jason&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;&lt;a href=&quot;https://json.blog/2023/01/28/hi-jason.html&quot;&gt;Week 4: 2023-01-28&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Jason,&lt;/p&gt;
&lt;p&gt;Another later-in-the-week reply for our last week of this project. To what you said about taking stock, I think a break or a big life change is an excellent time to think about these things. We found ourselves doing that when we moved into this house and once again when we knew we were having a child.&lt;/p&gt;
&lt;p&gt;Onto which, the final preparations are now taking place: washing the clothes, organising the nursery, and prepping the hospital bag (a long with many pregnancy and post-pregnancy products I&#39;d never realised even existed). I&#39;ve gone past the worrying stage now for the most part and I&#39;m focusing on things I &lt;em&gt;can&lt;/em&gt; control.&lt;/p&gt;
&lt;p&gt;Mexico sounds wonderful and I hope you&#39;ve been able to relax and enjoy it - spending an extended time away from home in somewhere so different sounds lovely.&lt;/p&gt;
&lt;p&gt;Now to get a little bit meta about this project of yours. Having done this for four weeks now I&#39;m struck by how difficult I&#39;ve found being committed to writing &lt;em&gt;something&lt;/em&gt; every week - it&#39;s certainly a good job I suggested early in the year pre-baby else I&#39;m not sure it would have gone quite as well. Despite having ideas here and there for little projects or blog posts something about the somewhat stricter schedule I&#39;ve struggled to do it &amp;quot;on time&amp;quot; (despite the loose rules).&lt;/p&gt;
&lt;p&gt;I have, however, really enjoyed being part of this project and I&#39;m looking forward to reading in the coming months.&lt;/p&gt;
&lt;p&gt;Speak soon,&lt;br /&gt;
Robb&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi Robb,&lt;/p&gt;
&lt;p&gt;It’s funny, because here at the beginning of this project, while taking stock, I’ve had two contrary reactions. First, it does take a surprising amount of discipline to sit down and write to someone. It’s certainly harder than just shooting off whatever is at the top of my mind. Second, it feels so feeble to just write a letter once a week while I see all the progression you’ve been making on several side projects, while preparing for the baby, during this same month.&lt;/p&gt;
&lt;p&gt;You’ve been &lt;a href=&quot;https://rknight.me/automating-my-now-page/&quot;&gt;automating your now page&lt;/a&gt;, &lt;a href=&quot;https://rknightuk.github.io/mac-30-font-svg/&quot;&gt;released a widely celebrated set of icons&lt;/a&gt;, built a &lt;a href=&quot;https://github.com/rknightuk/omglolcli&quot;&gt;CLI for omg.lol&lt;/a&gt;, and a host of other small projects. Based on &lt;a href=&quot;https://chaosweb.space&quot;&gt;chaosweb.space&lt;/a&gt;, I think you’d like &lt;a href=&quot;https://mynameiser.in&quot;&gt;mavica’s work&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It’s generating that itch in me again to figure out how to leave some energy at the end of the day to do the things I love on the computer after doing those things at work all day on the computer. Part of my taking stock is realizing that I have to find a way to push over that activation energy hump so that I can just work on small tools for myself all the time.&lt;/p&gt;
&lt;p&gt;I’m glad this first month felt like just writing letters to a friend about what’s happening— it feels like an easy introduction. Maybe they’ll all go this way, but maybe some folks will want to really dig into a specific topic. I’m glad that I am not responsible for writing the first letter, because I think that makes it more likely that each month will be a bit different based on who is participating.&lt;/p&gt;
&lt;p&gt;Thanks for helping me kick off this project.&lt;br /&gt;
Jason&lt;/p&gt;
&lt;/blockquote&gt;
</content>
    <summary>An idea by Jason Becker involving Jason and myself writing an email to each other every week for a month</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Get Mastodon Account ID from Username</title>
    <link href="https://rknight.me/blog/get-mastodon-account-id-from-username/"/>
    <updated>2023-01-27T00:00:00Z</updated>
    <id>https://rknight.me/get-mastodon-account-id-from-username/</id>
    <content type="html">&lt;p&gt;Note: Every Mastodon has an RSS feed you can use to get statuses if you don&#39;t need the data in JSON format &lt;code&gt;https://example.social/@foobar.rss&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to get a user&#39;s statuses from Mastodon you can&#39;t just look these up with the username. You need, to quote the documentation, &amp;quot;the ID of the Account in the database&amp;quot;. To get this, we can use the &lt;a href=&quot;https://docs.joinmastodon.org/methods/accounts/#lookup&quot;&gt;lookup endpoint&lt;/a&gt; that will return what we need:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# for an account on example.social&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://example.social/api/v1/accounts/lookup?acct&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;foobar&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# also works for remote accounts&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://example.social/api/v1/accounts/lookup?acct&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;foobar@another.social&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assuming the username is valid, you will receive a response like this:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1234567891011121314&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;acct&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foobar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;username&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foobar&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can use that ID to make a request for a users statuses:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; https://example.instance/api/v1/accounts/1234567891011121314/statuses&lt;/code&gt;&lt;/pre&gt;
</content>
    <summary>The Mastodon API requires the account ID for making API requests</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Everything Should Have an API: I&#39;m Done with Closed Services</title>
    <link href="https://rknight.me/blog/im-done-with-closed-services/"/>
    <updated>2023-01-24T00:00:00Z</updated>
    <id>https://rknight.me/im-done-with-closed-services/</id>
    <content type="html">&lt;p&gt;I&#39;m not signing up to any service that doesn&#39;t offer at minimum RSS feeds for my data. Ideally an API, even a simple one. No more apps that aren&#39;t &lt;a href=&quot;https://www.jwz.org/blog/2022/11/psa-do-not-use-services-that-hate-the-internet/&quot;&gt;part of the web&lt;/a&gt;. I&#39;m done.&lt;/p&gt;
&lt;p&gt;To quote &lt;a href=&quot;https://localghost.dev/blog/everything-should-have-an-api-adventures-in-trying-to-automate-stuff/&quot;&gt;Sophie&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why bother tracking what you&#39;re playing/reading/watching if you can&#39;t then do fun stuff with that data?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Is it too much to ask for an RSS feed of listen history from my podcast apps? Every single one of them collects and stores that data but (as far as I know) don&#39;t make that data available easily via RSS or an API. One of the apps must have this, please let me know.&lt;/p&gt;
&lt;p&gt;There are a loads of mobile apps for tracking game collections, movies watched, habits logged, but most of of them have no way to access the data on the web, let alone programatically; god forbid I want to access stuff from a browser on my Mac instead of using my phone all the time.&lt;/p&gt;
&lt;p&gt;I shouldn&#39;t need to set a reminder every week/month/year to go and request an export of &lt;em&gt;my&lt;/em&gt; data just to have it backed up, posted to my blog, or whatever else I want to do with it.&lt;/p&gt;
&lt;p&gt;I&#39;m done with closed services.&lt;/p&gt;
</content>
    <summary>I'm no longer willing to use services that don't allow me to access my data via an API or RSS</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Web Scraping with Node and Cheerio</title>
    <link href="https://rknight.me/blog/web-scraping-with-node-and-cheerio/"/>
    <updated>2023-01-22T00:00:00Z</updated>
    <id>https://rknight.me/web-scraping-with-node-and-cheerio/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;This post is a spin-off from &lt;a href=&quot;/automating-my-now-page/&quot;&gt;Automating My Now Page&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you want to programatically get data from a site that doesn&#39;t have an API, scraping is the solution. Keep in mind scraping could be against the terms of service of some websites or illegal in some places. To scrape a website there are (at least in this tutorial) two steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get the web page content&lt;/li&gt;
&lt;li&gt;Find the data inside the HTML you&#39;ve collected&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For this tutorial, we&#39;ll scrape two things from &lt;a href=&quot;https://psnprofiles.com/rknightuk&quot;&gt;my PSN profile&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The latest game I&#39;m playing&lt;/li&gt;
&lt;li&gt;The link to the game&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We should end up with an object that looks something like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;scrapedData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Marvel&#39;s Guardians of the Galaxy&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token literal-property property&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://psnprofiles.com/trophies/14419-marvels-guardians-of-the-galaxy/rknightuk&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Setup&lt;/h3&gt;
&lt;p&gt;For this tutorial you&#39;ll need &lt;a href=&quot;https://nodejs.org/en/&quot;&gt;Node&lt;/a&gt; installed - version 17 or higher to make use of the native version of &lt;code&gt;fetch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Create a directory and navigate to it:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; psn-scraper&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; psn-scraper&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we will initialise the project. You can either fill in all the details or append &lt;code&gt;-y&lt;/code&gt; to the command to skip all the questions:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# with questions&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; init&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# skip all questions&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; init &lt;span class=&quot;token parameter variable&quot;&gt;-y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we need to install &lt;a href=&quot;https://www.npmjs.com/package/cheerio&quot;&gt;Cheerio&lt;/a&gt;. Cheerio is a subset of jQuery designed to run on the server for DOM parsing and manipulation.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; cheerio&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If then install works correctly you should have a &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package.lock&lt;/code&gt; file in your directory.  In the &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Finally, we&#39;ll create our scraper file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;touch index.js
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Fetching the HTML&lt;/h3&gt;
&lt;p&gt;The first step is to fetch the HTML of the page we want to scrape which we&#39;ll do with &lt;code&gt;fetch&lt;/code&gt;. In your &lt;code&gt;index.js&lt;/code&gt; require &lt;code&gt;cheerio&lt;/code&gt; and add a &lt;code&gt;run&lt;/code&gt; function that using &lt;code&gt;async&lt;/code&gt; (we&#39;ll be using &lt;code&gt;await&lt;/code&gt; so this needs to be in a function).&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cheerio &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;cheerio&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://psnprofiles.com/rknightuk&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we call &lt;code&gt;node index.js&lt;/code&gt; a large amount of HTML will be output to the terminal. At this point we could use regex to find the data we want but using regex on HTML is notoriously difficult and unreliable. Instead Cheerio will do all the heavy lifting for us.&lt;/p&gt;
&lt;h3&gt;Parsing the Data&lt;/h3&gt;
&lt;p&gt;The first thing we need to do is find a class name or ID on the list of games so we can correctly target it. If we inspect the first game in the list of games on my profile, we can see that the link itself which contains the title and url has a class of &lt;code&gt;title&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/psn-profile-inspector.png&quot; alt=&quot;Web inspector showing the link with class names&quot; /&gt;&lt;/p&gt;
&lt;p&gt;On some websites this might be enough to get what we need, but a quick check in the console with &lt;code&gt;document.getElementsByClassName(&#39;title&#39;).length&lt;/code&gt; shows there are 91 elements on the profile page with that class but the games list only has 75 games in it so we need to be more specific. The list of games is inside a &lt;code&gt;table&lt;/code&gt; element with an ID of &lt;code&gt;gamesTable&lt;/code&gt; so we can use that in combination with the &lt;code&gt;title&lt;/code&gt; class name. If you&#39;ve used jQuery before the syntax will be familiar to you:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// load the HTML into Cheerio&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; $ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cheerio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// this will return elements we don&#39;t want&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; games &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;.title&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// this is more specific and only returns elements inside the games table&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; games &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#gamesTable .title&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 75&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now have an array of games which we can get the title and link from. Because Cheerio&#39;s API is the same as jQuery we can used &lt;code&gt;first&lt;/code&gt;,  &lt;code&gt;attr&lt;/code&gt;, and &lt;code&gt;text&lt;/code&gt; to get the values we need:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; games &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#gamesTable .title&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;href&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parsedData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token literal-property property&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://psnprofiles.com&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;path&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// the href doesn&#39;t include the domain so we add it here&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsedData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//  title: &quot;Marvel&#39;s Guardians of the Galaxy&quot;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//  link: &#39;/trophies/14419-marvels-guardians-of-the-galaxy/rknightuk&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we wanted to get &lt;em&gt;all&lt;/em&gt; the games in the list, we can use &lt;code&gt;each&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parsedData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; el&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;href&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt; games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;el&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://psnprofiles.com&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;path&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsedData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// [&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//  {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    title: &quot;Marvel&#39;s Guardians of the Galaxy&quot;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    link: &#39;https://psnprofiles.com/trophies/14419-marvels-guardians-of-the-galaxy/rknightuk&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//  },&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//  {&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    title: &#39;Peggle 2&#39;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//    link: &#39;https://psnprofiles.com/trophies/2935-peggle-2/rknightuk&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;//  }&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All together:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cheerio &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;cheerio&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://psnprofiles.com/rknightuk&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; body &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; $ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cheerio&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;body&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; games &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#gamesTable .title&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; parsedData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; games&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;href&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;parsedData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we have that data, we could do anything we want with it like post it to a blog or add it to an RSS feed. The source code for this tutorial is &lt;a href=&quot;https://github.com/rknightuk/psn-scraper-demo&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A short tutorial on how to use Node and Cheerio to scrape some data from PSN profiles</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Automating My Now Page</title>
    <link href="https://rknight.me/blog/automating-my-now-page/"/>
    <updated>2023-01-21T00:00:00Z</updated>
    <id>https://rknight.me/automating-my-now-page/</id>
    <content type="html">&lt;p&gt;This post outlines how I automated my now page(s) but I should start with what a now page &lt;em&gt;is&lt;/em&gt;. From &lt;a href=&quot;https://nownownow.com/about&quot;&gt;nownownow.com&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a website with a link that says “now” goes to a page that tells you what this person is focused on at this point in their life. For short, we call it a &amp;quot;now page&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I had heard of now pages a long time ago and always meant to add one to my site but just never got round to it. A few weeks ago &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;omg.lol&lt;/a&gt; launched their now page feature which made me think about this again (and I want to keep both my personal site and the omg.lol now page up to date and in sync). One problem with a page that should, in theory, be updated regularly is I will &lt;em&gt;definitely&lt;/em&gt; forget to do it. Automation to the rescue! Or more specifically a veritable grab-bag of python and node scripts, web scraping, and APIs.&lt;/p&gt;
&lt;p&gt;If you just want to see the pages here are the links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/now&quot;&gt;/now&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://robb.omg.lol/now&quot;&gt;robb.omg.lol/now&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/rknightuk/api&quot;&gt;source code is on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;For each service I&#39;m pulling data from I&#39;m doing mostly the same thing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fetch some data from &lt;em&gt;somewhere&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Format that data to make is easier to work with&lt;/li&gt;
&lt;li&gt;Add it to &lt;a href=&quot;https://api.rknight.me/api/data.json&quot;&gt;&lt;code&gt;data.json&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I then call &lt;a href=&quot;https://github.com/rknightuk/api/blob/main/now/generate.js&quot;&gt;&lt;code&gt;now/generate.js&lt;/code&gt;&lt;/a&gt; which goes through each key in &lt;code&gt;data.json&lt;/code&gt; and outputs it to two markdown files: &lt;a href=&quot;https://api.rknight.me/api/now-omg.txt&quot;&gt;&lt;code&gt;now-omg.txt&lt;/code&gt;&lt;/a&gt; (for omg.lol) and &lt;a href=&quot;https://api.rknight.me/api/now-web.txt&quot;&gt;&lt;code&gt;now-web.txt&lt;/code&gt;&lt;/a&gt; (for my website). The web version skips the omg.lol-specific syntax and intro section.&lt;/p&gt;
&lt;p&gt;For omg.lol, I wanted to append icons to each line so they display as the bullet on my omg.lol now page. I grabbed icons for each section from &lt;a href=&quot;https://fontawesome.com/&quot;&gt;Font Awesome&lt;/a&gt; and apply them as I loop through item in a section:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Some text from an item &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getIcon&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;making&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getIcon&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; icons &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;making&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;microphone-lines&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;laptop-code&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;terminal&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;code-pull-request&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;bug&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;reading&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;book&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;book-bookmark&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;book-open&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;book-open-reader&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;bookmark&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;music&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;headphones&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;radio&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;guitar&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;compact-disc&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;drum&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;sliders&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;volume-high&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;podcast&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;headphones&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;microphone-lines&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;comments&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;tower-broadcast&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;podcast&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; icons&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/now-podcasts.png&quot; alt=&quot;Example of icons on omg.lol&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Getting the data&lt;/h3&gt;
&lt;h4&gt;Music&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/lastfm.js&quot;&gt;&lt;code&gt;services/lastfm.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was a nice easy one: show the albums, tracks, and artists I&#39;ve been listening to the past seven days. &lt;a href=&quot;https://www.last.fm/api&quot;&gt;Last.fm&lt;/a&gt; have a decent, if slightly oddly designed, API to get this data.&lt;/p&gt;
&lt;p&gt;Not so easy is that &lt;a href=&quot;http://Last.fm&quot;&gt;Last.fm&lt;/a&gt; no longer return artist or track images. To get around this I do a lookup with the &lt;a href=&quot;https://musicbrainz.org/doc/MusicBrainz_API&quot;&gt;MusicBrainz&lt;/a&gt; which gives me a link to &lt;a href=&quot;https://www.allmusic.com/artist/mn0000289599&quot;&gt;AllMusic&lt;/a&gt; which I then scrape and grab the main image with &lt;a href=&quot;https://cheerio.js.org/&quot;&gt;Cheerio&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I also use &lt;a href=&quot;https://www.npmjs.com/package/text-to-image&quot;&gt;&lt;code&gt;text-to-image&lt;/code&gt;&lt;/a&gt; to generate images for artists and albums where I&#39;m unable to get one either from &lt;a href=&quot;http://Last.fm&quot;&gt;Last.fm&lt;/a&gt; or AllMusic:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; textToImage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;generate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; by &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;album&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;artist&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;maxWidth&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;customHeight&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;textColor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;white&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;textAlign&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;center&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;bgColor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;black&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;verticalAlign&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;center&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/now-albums.png&quot; alt=&quot;Example of top album output&quot; /&gt;&lt;/p&gt;
&lt;h4&gt;Github, Books, and Statuses&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/github.js&quot;&gt;&lt;code&gt;services/github.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/books.js&quot;&gt;&lt;code&gt;services/books.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/statuses.js&quot;&gt;&lt;code&gt;services/statuses.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are all straight-forward API calls with a slightly manually process of tagging projects on GitHub with &lt;code&gt;now&lt;/code&gt; - I don&#39;t want every recent project showing up and GitHub doesn&#39;t have an API for star lists yet.&lt;/p&gt;
&lt;h4&gt;Games&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/psn.js&quot;&gt;&lt;code&gt;services/psn.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Like the missing artist images, this involved scraping a page because PSN doesn&#39;t have an API. I scrape my &lt;a href=&quot;https://psnprofiles.com/rknightuk&quot;&gt;PSN Profiles&lt;/a&gt; and use Cheerio to grab the latest games I&#39;ve got trophies for. It&#39;s not a perfect system, but it&#39;s likely the current game I&#39;m playing will be the top of that list.&lt;/p&gt;
&lt;h4&gt;Overcast&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/overcast&quot;&gt;&lt;code&gt;services/overcast.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;This export isn&#39;t a secret, nor are the scripts to download it but don&#39;t hammer this endpoint. I&#39;m downloading once a week. I have emailed Marco to ask if he&#39;d implement an RSS feed of listen history so this isn&#39;t required.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This one was trickier but doable. Overcast offers an &lt;a href=&quot;https://overcast.fm/account&quot;&gt;&amp;quot;All Data&amp;quot; export&lt;/a&gt; but you need to be logged in to access it. And it&#39;s in OPML format. So this is a two step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;a href=&quot;https://github.com/rknightuk/api/tree/main/services/overcast/fetcher&quot;&gt;this python script&lt;/a&gt; to login and download the export&lt;/li&gt;
&lt;li&gt;Run &lt;a href=&quot;https://github.com/rknightuk/api/tree/main/services/overcast/parser&quot;&gt;this node script&lt;/a&gt; to convert the OPML to JSON and then to &lt;a href=&quot;https://api.rknight.me/api/podcasts.json&quot;&gt;a valid JSON feed&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One thing I noticed is that &lt;a href=&quot;https://www.relay.fm/membership&quot;&gt;Relay&#39;s member show&lt;/a&gt; feeds show the episode and show URL as &lt;code&gt;relay.fm/membership&lt;/code&gt; so I had to handle this myself. Example here with &lt;a href=&quot;https://www.relay.fm/connected&quot;&gt;Connected Pro&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isConnectedPro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; podcast&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Connected Pro&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; episodeUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; episode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isConnectedPro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; episodeNumber &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; episode&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;title&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;:&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    episodeUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://relay.fm/connected/&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;episodeNumber&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From this data, I take the last 30 episodes, group them by show, and rank them by episode count which then becomes the podcasts section of the now page.&lt;/p&gt;
&lt;h4&gt;Other&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rknightuk/api/blob/main/services/other&quot;&gt;&lt;code&gt;services/other.js&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the &amp;quot;about&amp;quot; and &amp;quot;tv&amp;quot; sections, I wanted to be able to update these from anywhere so I opted to dump some yaml in an &lt;a href=&quot;https://robb.paste.lol/now.yaml&quot;&gt;omg.lol pastebin&lt;/a&gt; and fetch it from there.&lt;/p&gt;
&lt;h3&gt;Syncing the changes&lt;/h3&gt;
&lt;p&gt;Each data source doesn&#39;t need to be updated every hour or day, so I split them out into a &lt;a href=&quot;https://github.com/rknightuk/api/blob/main/makefile&quot;&gt;&lt;code&gt;makefile&lt;/code&gt;&lt;/a&gt; for jobs to run on a Monday (music, books, games), a Friday (Overcast), and daily (about, tv, github projects). (I could have done these all as separate cron jobs but it was easier to split them in a make file and just have three scheduled jobs instead).&lt;/p&gt;
&lt;p&gt;Each time a job runs, it updates the &lt;code&gt;data.json&lt;/code&gt; file so I can run &lt;code&gt;generate.js&lt;/code&gt; and &lt;a href=&quot;https://github.com/rknightuk/api/blob/main/now/update.js&quot;&gt;&lt;code&gt;update.js&lt;/code&gt;&lt;/a&gt; at any time throughout the week to update my now pages. The &lt;code&gt;update&lt;/code&gt; script posts the contents of &lt;code&gt;web-omg.txt&lt;/code&gt; to the &lt;a href=&quot;https://api.omg.lol/&quot;&gt;omg.lol API&lt;/a&gt; and sends a webhook to &lt;a href=&quot;https://forge.laravel.com&quot;&gt;Forge&lt;/a&gt; to deploy my main site.&lt;/p&gt;
&lt;p&gt;All of the code for this is &lt;a href=&quot;https://github.com/rknightuk/api/&quot;&gt;on GitHub&lt;/a&gt; if you want to do something similar.&lt;/p&gt;
</content>
    <summary>How I automated my now page updates</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Navigate Project Folders with Pick</title>
    <link href="https://rknight.me/blog/navigate-project-folders-with-pick/"/>
    <updated>2023-01-19T00:00:00Z</updated>
    <id>https://rknight.me/navigate-project-folders-with-pick/</id>
    <content type="html">&lt;p&gt;When I started my industrial placement at Radweb nearly 10 years ago (👴), &lt;a href=&quot;https://github.com/danharper&quot;&gt;Dan Harper&lt;/a&gt; sent me his &lt;a href=&quot;https://github.com/danharper/dotfiles&quot;&gt;bash aliases&lt;/a&gt; which included a lot of handy Git ones including this one that uses &lt;a href=&quot;https://github.com/mptre/pick&quot;&gt;&lt;code&gt;pick&lt;/code&gt;&lt;/a&gt; to list git branches. I can either do &lt;code&gt;gco&lt;/code&gt;, search, and enter to checkout to that branch, or do &lt;code&gt;gco branchName&lt;/code&gt; to checkout immediately to a branch:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-name function&quot;&gt;gco&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$#&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; pick&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I do use &lt;a href=&quot;https://github.com/martvdmoosdijk/zsh-marks&quot;&gt;&lt;code&gt;zsh-marks&lt;/code&gt;&lt;/a&gt; already to jump to folders I&#39;ve expicitly marked (as well as jumping to the root of projects with &lt;code&gt;jump sites&lt;/code&gt;) but last night while doing the &lt;code&gt;cd ..; cd project-name&lt;/code&gt; dance between different projects I &lt;em&gt;hadn&#39;t&lt;/em&gt; marked I realised I could apply this same thing to my personal sites folder which as the time of this writing has 97 folders. To do this, I needed to list out the directories with &lt;code&gt;ls&lt;/code&gt; and the &lt;code&gt;-1&lt;/code&gt; option which tells &lt;code&gt;ls&lt;/code&gt; to show one per line and just the folder name:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-name function&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$#&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-eq&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/path/to/sites/&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-1&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;~/path/to/sites&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; pick&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/path/to/sites/&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So now to jump directly to the folder for this website instead of doing &lt;code&gt;j sites&lt;/code&gt; then &lt;code&gt;cd personal/rknight.me&lt;/code&gt; I can simply do &lt;code&gt;site rknight.me&lt;/code&gt;. You can see all my aliases in &lt;a href=&quot;https://github.com/rknightuk/dotfiles&quot;&gt;my dotfiles on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>Using pick to jump to a project quickly</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Link Dump</title>
    <link href="https://rknight.me/blog/link-dump/"/>
    <updated>2023-01-15T00:00:00Z</updated>
    <id>https://rknight.me/link-dump/</id>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://austinkleon.com/2014/04/29/a-brief-history-of-my-newspaper-blackout-poems/&quot;&gt;A brief history of my newspaper blackout poems&lt;/a&gt;. Not sure how I&#39;ve not seen this before, but I&#39;ll be buying &lt;a href=&quot;https://austinkleon.com/newspaperblackout/&quot;&gt;the book ASAP&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.razzem.com/these-ai-generated-marvel-cat-characters-could-make-for-a-cute-animated-series/&quot;&gt;AI generated Marvel cat-characters&lt;/a&gt;. Cute AF.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pocket-lint.com/phones/reviews/sony-mobile/71544-sony-ericsson-xperia-pureness-review/&quot;&gt;Sony Ericsson Xperia Pureness&lt;/a&gt;. Not sure why this was in my read later list but very cool (article is from 2009)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.wearerewind.com/&quot;&gt;Audio Cassette Player | We Are Rewind&lt;/a&gt;. A cassette player with Bluetooth. It&#39;s like this product was made for me.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ngagesdk/wordle&quot;&gt;A portable clone of Wordle designed for the Nokia N-Gage&lt;/a&gt;. Cool.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://writteninstone.photo/&quot;&gt;Written in Stone • A gallery of sidewalks, and the stamps and seals left by the people who laid them.&lt;/a&gt; I already posted this but figured I&#39;d pop it here too.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>A selection of interesting links from my overflowing read later list</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Bye Almanac, Hello Lantern</title>
    <link href="https://rknight.me/blog/bye-almanac-hello-lantern/"/>
    <updated>2023-01-14T00:00:00Z</updated>
    <id>https://rknight.me/bye-almanac-hello-lantern/</id>
    <content type="html">&lt;p&gt;I am a hoarder of data. I have exports from dead Tumblr sites, Twitter accounts,  Pinboard, Instapaper, and probably more I&#39;m not thinking of. I also like to be able to check when I did something, watched something, or just tweeted something funny (it happened &lt;a href=&quot;https://hellsite.rknight.me/656762307494682624/&quot;&gt;at least once&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;Bye Almanac&lt;/h3&gt;
&lt;p&gt;In February 2015 &lt;a href=&quot;https://hellsite.rknight.me/569782414899355648/&quot;&gt;I started using&lt;/a&gt; &lt;a href=&quot;http://plotapp.io/&quot;&gt;Plot&lt;/a&gt; (RIP) for tracking movies I&#39;ve watched. This was before I&#39;d heard of &lt;a href=&quot;https://letterboxd.com/&quot;&gt;Letterboxd&lt;/a&gt; and before the proliferation of the many TV and movie tracking apps on iOS. Within a few months I decided I wanted the same for TV shows I&#39;d watched and games I played so I started work on the first version of Almanac. I built this with &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; which worked well but was missing any kind of search and I couldn&#39;t post from my phone (I suppose I could but I &lt;em&gt;hate&lt;/em&gt; doing things on my phone). Sadly I don&#39;t have a copy of this version of site but I do have this rather natty screenshot of it:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/almanac-screenshot.png&quot; alt=&quot;A screenshot of version one of Almanac&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Fast forward to 2018 and I did the &lt;a href=&quot;https://github.com/rknightuk/almanac/commit/2595bc622f75ef5ddc9a85cd745dd216b69fbddc&quot;&gt;first commit&lt;/a&gt; on version two. This version was built on Laravel for the backend and a React front end. It used the &lt;a href=&quot;https://www.themoviedb.org/&quot;&gt;TMDB API&lt;/a&gt; for movies and TV, and the &lt;a href=&quot;https://www.giantbomb.com/api/&quot;&gt;GiantBomb API&lt;/a&gt; for games. I built a &lt;a href=&quot;https://github.com/rknightuk/almanac/blob/master/app/LetterboxdFetcher.php&quot;&gt;Letterboxd importer&lt;/a&gt; to poll my profile RSS feed to grab new reviews and store them in Almanac, kept track of how many times I&#39;d watched a movie, and more recently used it to cross-post Letterboxd reviews to Micro.blog. This has now been replaced with &lt;a href=&quot;https://echo.rknight.me&quot;&gt;Echo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When I started using Micro.blog early last year I realised it made no sense to have all these different places I was posting things so I spent some time exporting the ~1200 posts from Almanac and importing them into Micro.blog. Since then I&#39;ve been posting directly to Micro.blog, with the exception of movies which are still fed in from Letterboxd. For the sake of posterity, here&#39;s a couple of screenshots of Almanac as it exists now:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/almanac-screenshot-1.png&quot; alt=&quot;A screenshot of the front end of Almanac&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/almanac-screenshot-4.png&quot; alt=&quot;A screenshot of the backend of Almanac&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Hello Lantern&lt;/h3&gt;
&lt;p&gt;Like version one of Almanac, I&#39;ve missed being able to quickly search for a movie or TV show to grab the year or link when posting to Micro.blog. Which is why I built &lt;a href=&quot;https://lantern.rknight.me&quot;&gt;Lantern&lt;/a&gt;. Lantern uses the same APIs as Almanac (and even shares some of the same design for search). It grabs the year (release or first aired) as well as the poster and converts it to Markdown for posting to Micro.blog. Of course it also pops the &lt;a href=&quot;https://help.micro.blog/t/emoji-in-discover/34&quot;&gt;discover emoji&lt;/a&gt; in there too.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/lantern-screenshot.png&quot; alt=&quot;Lantern screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I started with a version that logged you in and would post automatically but realised that made it more complicated that it needs to be. I switched it over to use &lt;a href=&quot;https://www.netlify.com/products/functions/&quot;&gt;Netlify functions&lt;/a&gt; for the API and a mess of vanilla JS for the front end. Micro.blog has the posting UI so I just needed to generated the main content. Micro.blog already has book support so I don&#39;t think I&#39;ll be adding too many features to Lantern but please let me know if you find any bugs or you have any litte requests.&lt;/p&gt;
</content>
    <summary>Retiring my media blogging engine Almanac and launching it's spirtual successor Lantern</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Import RSS to Micro.blog and Mastodon with Echo</title>
    <link href="https://rknight.me/blog/echo-rss-to-microblog/"/>
    <updated>2023-01-10T00:00:00Z</updated>
    <id>https://rknight.me/echo-rss-to-microblog/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/echo-screenshot.png&quot; alt=&quot;Screenshot of Echo running in a terminal&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 13/01/23&lt;/strong&gt;: Echo now supports Mastodon and webhooks as well as Micro.blog. &lt;a href=&quot;https://echo.rknight.me&quot;&gt;Check out the website for more details&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After a conversation with &lt;a href=&quot;https://zoeaubert.me&quot;&gt;Zoe&lt;/a&gt; about &lt;a href=&quot;https://status.lol&quot;&gt;status.lol&lt;/a&gt;, as well as &lt;a href=&quot;https://micro.blog/muhh/15830286&quot;&gt;this reply from Markus&lt;/a&gt;, I decided to write &lt;a href=&quot;https://github.com/rknightuk/echo&quot;&gt;Echo&lt;/a&gt; last night (do I know how to party on my birthday or what?). From the readme:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Echo is a node script to post new items from an RSS feed to Micro.blog&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Micro.blog already supports importing RSS feeds and handles it very well but &lt;s&gt;I&#39;m a control freak&lt;/s&gt; I wanted a bit more control over the formatting as well as assigning categories on import.&lt;/p&gt;
&lt;p&gt;Echo takes a config of RSS feeds as well as some formatting functions for items and posts them to Micro.blog. I run mine every 15 minutes but you could set it up to run whenever you want. The only requirements are &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; and a server to run it on (or you could run it on your computer and manually run it as and when).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rknightuk/echo&quot;&gt;Download Echo on GitHub&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>Echo is a node script to post new items from an RSS feed to Micro.blog</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Blogs and Wikis and Links</title>
    <link href="https://rknight.me/blog/blogs-and-wikis-and-links/"/>
    <updated>2023-01-07T00:00:00Z</updated>
    <id>https://rknight.me/blogs-and-wikis-and-links/</id>
    <content type="html">&lt;p&gt;I&#39;ve been thinking about how better to handle all the different places I&#39;m posting too including this site,  &lt;a href=&quot;https://micro.blog/rknightuk&quot;&gt;Micro.blog&lt;/a&gt;, and &lt;a href=&quot;https://intersect.rknight.me/&quot;&gt;my wiki&lt;/a&gt;.  To quote &lt;a href=&quot;https://toot.rknight.me/2023/01/07/starting-to-think.html&quot;&gt;myself&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Starting to think some things I’ve put into my wiki might be better served as a blog post that I just update as and when I find things. The discoverability of pages is kinda crappy for anyone who isn’t me (because I know to go there to look for things)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For example, &lt;a href=&quot;https://intersect.rknight.me/buying-a-house/&quot;&gt;this page about buying a house&lt;/a&gt;. Why isn&#39;t this a blog post? It &lt;em&gt;looks&lt;/em&gt; just like one, it&#39;s unlikely I&#39;m going to buy another house so this is likely to be all I ever write about it. &lt;a href=&quot;https://intersect.rknight.me/cli/git/&quot;&gt;This git page&lt;/a&gt;. There&#39;s no reason I couldn&#39;t have this as a blog post and just update it as I find other things. People are more likely to find it as a blog post than a page on my wiki.&lt;/p&gt;
&lt;p&gt;Then there&#39;s the opposite: &lt;a href=&quot;https://intersect.rknight.me/hardware/raspberry-pi/pisight/&quot;&gt;this PiSight page&lt;/a&gt; is 100% links. I wonder if a link system with tags would be better than posting to a specific page each time I find a new link. Or I could add the links to &lt;a href=&quot;https://rknight.me/building-a-pisight/&quot;&gt;the PiSight blog post I wrote&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Intersect was fun to build but it&#39;s &lt;em&gt;complicated&lt;/em&gt;. The build process takes a while, making any structural changes is a pain. Something simpler might be better. I should reduce it to the bare minimum of things that I need from it.&lt;/p&gt;
&lt;p&gt;Should I incorporate the wiki into my personal site instead of having it on a different domain perhaps? Should I just do more blog posts when I find interesting things and not worry if it&#39;s &amp;quot;worth it&amp;quot; to post? Who knows.&lt;/p&gt;
</content>
    <summary>A brain dump of thoughts of how to handle links, wikis, and websites</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Using PageFind with Eleventy for Search</title>
    <link href="https://rknight.me/blog/using-pagefind-with-eleventy-for-search/"/>
    <updated>2023-01-04T00:00:00Z</updated>
    <id>https://rknight.me/using-pagefind-with-eleventy-for-search/</id>
    <content type="html">&lt;p&gt;In the past, I have implemented my own search for static sites and while it&#39;s good &lt;em&gt;enough&lt;/em&gt;, it&#39;s not great. Recently &lt;a href=&quot;https://github.com/tweetback/tweetback&quot;&gt;Tweetback&lt;/a&gt;, a self-hosted Twitter archive, added search using &lt;a href=&quot;https://pagefind.app&quot;&gt;PageFind&lt;/a&gt; so I dug into the code to see how it&#39;s done. PageFind is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a fully static search library that aims to perform well on large sites, while using as little of your users’ bandwidth as possible, and without hosting any infrastructure&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I hadn&#39;t even heard of PageFind until a few weeks ago so most of what I&#39;ve learnt here came from the PageFind docs and the &lt;a href=&quot;https://github.com/tweetback/tweetback/pull/27&quot;&gt;pull request&lt;/a&gt; that added search to Tweetback so a big thanks to &lt;a href=&quot;https://alistairshepherd.uk&quot;&gt;Alistair&lt;/a&gt; for writing the PR.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;Note: I had to change some directories for &lt;a href=&quot;https://github.com/rknightuk/eleventy-pagefind-demo/&quot;&gt;the demo&lt;/a&gt; to get this to work on GitHub pages but everything works exactly the same as below.&lt;/p&gt;
&lt;p&gt;To get started, install &lt;a href=&quot;https://www.npmjs.com/package/pagefind&quot;&gt;the package&lt;/a&gt; to your Eleventy project. PageFind has &lt;a href=&quot;https://pagefind.app/docs/installation/&quot;&gt;more detailed installation instructions on their website here&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; --save-dev pagefind&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Build the index&lt;/h3&gt;
&lt;p&gt;PageFind works by scanning a bunch of HTML files and looking for &lt;a href=&quot;https://pagefind.app/docs/indexing/&quot;&gt;one of the &lt;code&gt;data-pagefind&lt;/code&gt; attributes&lt;/a&gt;.  We&#39;ll add the &lt;code&gt;data-pagefind-body&lt;/code&gt; attribute to the article element that wraps the posts to tell it to index the post content:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;article&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;data-pagefind-body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    {{ content | safe }}&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;article&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We want to run the PageFind CLI &lt;em&gt;after&lt;/em&gt; the site has been built so we use the &lt;a href=&quot;https://www.11ty.dev/docs/events/#eleventy.after&quot;&gt;&lt;code&gt;after&lt;/code&gt; Eleventy event&lt;/a&gt; and run the command with &lt;a href=&quot;https://nodejs.org/api/child_process.html#child_processexecsynccommand-options&quot;&gt;&lt;code&gt;execSync&lt;/code&gt;&lt;/a&gt; on all HTML files in the built site:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; execSync &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;child_process&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;eleventy.after&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;execSync&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;npx pagefind --source _site --glob \&quot;**/*.html\&quot;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;utf-8&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update 24/07/23&lt;/strong&gt;: If you have a lot (read: ~3000) of pages like I do then you might find the build crashes trying to build the index. If that&#39;s the case, do the pagefind command &lt;em&gt;after&lt;/em&gt; your Eleventy site build script has finished instead of in the &lt;code&gt;after&lt;/code&gt; event.&lt;/p&gt;
&lt;p&gt;Note the &lt;code&gt;_site&lt;/code&gt; source option - if your site is built to a different directory then change this. This outputs a &lt;code&gt;_pagefind&lt;/code&gt; directory to the build folder.&lt;/p&gt;
&lt;h3&gt;Add a Search Box&lt;/h3&gt;
&lt;p&gt;PageFind has &lt;a href=&quot;https://pagefind.app/docs/api/&quot;&gt;an API&lt;/a&gt; if you want to make your own search interface but for this we&#39;ll use the built-in UI. Add the following to wherever you want the search box to appear, in the case of this demo it&#39;s going on the home page.&lt;/p&gt;
&lt;p&gt;Add the PageFind stylesheet either in the head or above your search box element. The additional styles are optional and only needed if you need a dark theme/mode.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/_pagefind/pagefind-ui.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token atrule&quot;&gt;&lt;span class=&quot;token rule&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; dark&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token selector&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--pagefind-ui-primary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #eeeeee&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--pagefind-ui-text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #eeeeee&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--pagefind-ui-background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #152028&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--pagefind-ui-border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #152028&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;--pagefind-ui-tag&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; #152028&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PageFind requires an element with an ID which can then be passed to the script.&lt;/p&gt;
&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;search&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/_pagefind/pagefind-ui.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onload&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PagefindUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;#search&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;showImages&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run your Eleventy serve script and if everything has worked, you should have a functioning search that searches all your posts:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pagefind-eleventy.png&quot; alt=&quot;Search box with McFly as the search term and three results&quot; /&gt;&lt;br /&gt;
The code for this is &lt;a href=&quot;https://github.com/rknightuk/eleventy-pagefind-demo&quot;&gt;on GitHub&lt;/a&gt; and there is a &lt;a href=&quot;https://rknightuk.github.io/eleventy-pagefind-demo&quot;&gt;live demo here&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>How to use PageFind to implement search for an Eleventy site</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Just 2022 Things</title>
    <link href="https://rknight.me/blog/just-2022-things/"/>
    <updated>2022-12-30T00:00:00Z</updated>
    <id>https://rknight.me/just-2022-things/</id>
    <content type="html">&lt;p&gt;Inspired by &lt;a href=&quot;https://localghost.dev/blog/2022-the-year-in-lists/&quot;&gt;Sophie&#39;s post&lt;/a&gt; I decided to do a little roundup of things I&#39;ve done the year.&lt;/p&gt;
&lt;h3&gt;House Project&lt;/h3&gt;
&lt;p&gt;We purchased our house in November 2021 and it hadn&#39;t been decorated since 1971 so everything needed doing; most of this year has been spent getting all the rooms fixed up. In July, we found out my partner was pregnant (🎉) which is very exciting but also added an extra bit of stress to making sure the house was done by the end of this year. Things I learnt how to do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/11/06/its-finally-finished.html&quot;&gt;Fitting laminate flooring&lt;/a&gt; - This isn&#39;t difficult per se, but it is &lt;em&gt;hard&lt;/em&gt; work.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/08/07/my-first-and.html&quot;&gt;Wallpapering&lt;/a&gt; - This is a pain in the arse, I hate it, and will never do it again. I do like the finished wall &lt;a href=&quot;https://toot.rknight.me/2022/12/27/final-floor-in.html&quot;&gt;now it has the mirror and radiator though&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/11/24/in-better-news.html&quot;&gt;Installing skirting boards&lt;/a&gt; - Again, a bit of a pain but with a decent mitre saw and some &lt;a href=&quot;https://trade.evo-stik.co.uk/products/grab-adhesives/gripfill&quot;&gt;Gripfill&lt;/a&gt; it doesn&#39;t take too long.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/04/06/im-like-ron.html&quot;&gt;Building a desk from scratch&lt;/a&gt; - This was a fun woodworking project. I&#39;m pretty happy with &lt;a href=&quot;https://toot.rknight.me/2022/04/22/i-heard-were.html&quot;&gt;how it turned out.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Travel&lt;/h3&gt;
&lt;p&gt;In February we went to Rome, visited all the normal sites, and ate so much &lt;a href=&quot;https://toot.rknight.me/2022/02/24/pizza.html&quot;&gt;incredible pizza&lt;/a&gt;. We stayed right near &lt;a href=&quot;https://en.wikipedia.org/wiki/Pantheon,_Rome&quot;&gt;The Pantheon&lt;/a&gt; which was perfect for walking everywhere we needed to go.&lt;/p&gt;
&lt;p&gt;In April we went to Bournemouth for a few days and saw &lt;a href=&quot;https://en.wikipedia.org/wiki/Bowling_for_Soup&quot;&gt;Bowling for Soup&lt;/a&gt; on the last day.&lt;/p&gt;
&lt;p&gt;Right before Christmas we went to Edinburgh to visit the Christmas market (which was a bit disappointing) but we did a tour of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Edinburgh_Vaults&quot;&gt;Edinburgh Vaults&lt;/a&gt;, rubbed the nose of &lt;a href=&quot;https://toot.rknight.me/2022/12/19/edinburgh-day.html&quot;&gt;Greyfriar&#39;s Bobby&lt;/a&gt;, and visited some great book shops.&lt;/p&gt;
&lt;p&gt;We saw a bunch of theatre shows this year as well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.hamiltonwestendshop.com&quot;&gt;Hamilton&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sixthemusical.com&quot;&gt;Six&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://thebookofmormonmusical.com/london/?utm_source=search&amp;amp;utm_medium=google&amp;amp;campaign_id=17961066709&amp;amp;adset_id=&amp;amp;ad_id=&amp;amp;gclid=Cj0KCQiAtbqdBhDvARIsAGYnXBPs12fWJd3GhcOAKGkJVZVY33b3MIfGN8yz0HqLDzKh0NCaommr2GQaAgAPEALw_wcB&quot;&gt;Book of Mormon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.backtothefuturemusical.com&quot;&gt;Back to the Future: The Musical&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cinderella_(Lloyd_Webber_musical)&quot;&gt;Cinderella&lt;/a&gt; - This was an interesting one because the front 8 rows rotate with the stage so you&#39;re facing everyone else. This got cancelled right after we saw it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Web&lt;/h3&gt;
&lt;p&gt;I made a bunch of little plugins/webapps for &lt;a href=&quot;https://mbtools.rknight.me&quot;&gt;Micro.blog&lt;/a&gt; and the &lt;a href=&quot;https://potimages.rknight.me&quot;&gt;Monzo Pot Image Generator&lt;/a&gt; hit over 40k images generated. I stopped using Twitter so I&#39;m &lt;a href=&quot;https://rknight.me/two-social-networks-in-this-economy/&quot;&gt;using a combination&lt;/a&gt; of &lt;a href=&quot;https://micro.blog&quot;&gt;Micro.blog&lt;/a&gt; and Mastodon - the latter is run by &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;omg.lol&lt;/a&gt;. omg.lol is such a fun site and has a bunch of services, including a Mastodon instance. You can get it for $5 a year until tomorrow.&lt;/p&gt;
&lt;h3&gt;Games&lt;/h3&gt;
&lt;p&gt;I didn&#39;t play many games due to the aforementioned home project but I did manage to play through the &lt;a href=&quot;https://store.rockstargames.com/game/buy-grand-theft-auto-the-trilogy-the-definitive-edition&quot;&gt;GTA Trilogy&lt;/a&gt; as well as &lt;a href=&quot;https://www.playstation.com/en-gb/games/horizon-forbidden-west/&quot;&gt;Horizon Forbidden West&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Movies&lt;/h3&gt;
&lt;p&gt;According to &lt;a href=&quot;https://letterboxd.com/rknightuk/films/diary/for/2022/&quot;&gt;Letterboxd&lt;/a&gt; I&#39;ve watched 103 movies this year. Of those, 12 of them came out this year. My favourites of those are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://letterboxd.com/rknightuk/film/thor-love-and-thunder/1/&quot;&gt;Thor: Love and Thunder&lt;/a&gt; - This movie is a bit divisive but I loved it.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://letterboxd.com/rknightuk/film/glass-onion-a-knives-out-mystery/&quot;&gt;Glass Onion: A Knives Out Mystery&lt;/a&gt; - An excellent sequel to Knives Out.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://letterboxd.com/rknightuk/film/the-guardians-of-the-galaxy-holiday-special/&quot;&gt;The Guardians of the Galaxy Holiday Special&lt;/a&gt; - This was so much fun and &lt;a href=&quot;https://www.youtube.com/watch?v=-E1ULv6LcOk&quot;&gt;the main song&lt;/a&gt; is a banger.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TV&lt;/h3&gt;
&lt;p&gt;I didn&#39;t watch all that much TV this year but the two stands outs were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/07/14/finished-the-first.html&quot;&gt;Reacher&lt;/a&gt; -  As a fan of the books, I was impressed how closely this matched up. A really great adaptation.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/08/16/cant-believe-better.html&quot;&gt;Better Call Saul&lt;/a&gt; - This show is perfect in every way.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://toot.rknight.me/2022/09/09/for-all-mankind.html&quot;&gt;For All Mankind&lt;/a&gt; - No other show builds suspense like For All Mankind does&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Books&lt;/h2&gt;
&lt;p&gt;I read zero books this year which is embarrassing, I hope to change this next year. I did start &lt;a href=&quot;https://micro.blog/books/9781728236254&quot;&gt;Men Who Hate Women&lt;/a&gt; and hopefully will finish it soon.&lt;/p&gt;
</content>
    <summary>A big list of things that happened in 2022</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Building a Podcast Site with Eleventy</title>
    <link href="https://rknight.me/blog/bulding-podcast-site-eleventy/"/>
    <updated>2022-12-28T00:00:00Z</updated>
    <id>https://rknight.me/bulding-podcast-site-eleventy/</id>
    <content type="html">&lt;p&gt;When me and John started &lt;a href=&quot;https://ruminatepodcast.com&quot;&gt;Ruminate&lt;/a&gt;, we didn&#39;t know much about hosting podcasts so we decided to go with &lt;a href=&quot;https://simplecast.com&quot;&gt;Simplecast&lt;/a&gt; to host and manage the podcast. Seven years later, Simplecast has changed quite a bit to the point that it&#39;s hindering rather than helping me post the show. It&#39;s not a bad service, but it&#39;s overkill for posting one episode every two weeks.&lt;/p&gt;
&lt;p&gt;I &lt;a href=&quot;https://toot.rknight.me/2022/12/23/has-anyone-moved.html&quot;&gt;asked&lt;/a&gt; last week if anyone had self-hosted a podcast and a few people I trust said it should be easy enough to do so I got to work. As with most of my projects, I used &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;. Eleventy is a very powerful static site generator that this site is built with. &lt;a href=&quot;https://www.marclittlemore.com/create-an-eleventy-podcast-feed/&quot;&gt;This post&lt;/a&gt; was very helpful in pointing me in the right direction.&lt;/p&gt;
&lt;h2&gt;Importing existing posts&lt;/h2&gt;
&lt;p&gt;The first step was to import the existing 156 episodes into the new site. I had a look at the RSS feed to see what metadata each episode would need. Here is an example from &lt;a href=&quot;https://ruminatepodcast.com/156/&quot;&gt;episode 156&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; episode&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;guid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ff7d5a18&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;c87c&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4420&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;a6dd&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;965be716aa12&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;156 - For Listeners Only&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;published&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Wed, 7 Dec 2022 20:55:06 +0000&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;permalink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 156/index.html&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://ruminatepod.s3-us-west-2.amazonaws.com/156.mp3&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10993430&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;00:22:49&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Baguettes and Obsidian.&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token key atrule&quot;&gt;episodeNumber&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;156&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I created a new script called &lt;a href=&quot;https://github.com/rknightuk/ruminate/blob/main/scripts/feedtomarkdown.js&quot;&gt;&lt;code&gt;feedtomarkdown.js&lt;/code&gt;&lt;/a&gt;, used &lt;a href=&quot;https://www.npmjs.com/package/node-fetch&quot;&gt;&lt;code&gt;node-fetch&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.npmjs.com/package/xml2json&quot;&gt;&lt;code&gt;xml2json&lt;/code&gt;&lt;/a&gt;  to parse the feed, and then looped through each episode to get the data. For the shownotes, I needed to covert that back to markdown with &lt;a href=&quot;https://www.npmjs.com/package/turndown&quot;&gt;&lt;code&gt;turndown&lt;/code&gt;&lt;/a&gt;. I also learnt about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart&quot;&gt;&lt;code&gt;padStart/padEnd&lt;/code&gt;&lt;/a&gt; to pad the episode numbers from &lt;code&gt;21&lt;/code&gt; to &lt;code&gt;021&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;21&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;padStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;0&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 021&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally I output all the file names into &lt;code&gt;filenames.sh&lt;/code&gt; to download all the episodes with &lt;code&gt;wget&lt;/code&gt; with consistent naming:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; http://path.to/file &lt;span class=&quot;token parameter variable&quot;&gt;-O&lt;/span&gt; 001.mp3&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; http://path.to/file &lt;span class=&quot;token parameter variable&quot;&gt;-O&lt;/span&gt; 002.mp3&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# and so on&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Creating new episodes&lt;/h2&gt;
&lt;p&gt;I&#39;m hosting the episode files on S3 and I didn&#39;t want to have to manually get the filesize, duration, and generate a UUID for each episode so I wrote &lt;a href=&quot;https://github.com/rknightuk/ruminate/blob/main/scripts/new.js&quot;&gt;&lt;code&gt;new.js&lt;/code&gt;&lt;/a&gt;. This script takes an episode number, finds the mp3 file, reads the duration, title, and summary from the mp3 and outputs a new episode (with a UUID as well). This uses &lt;a href=&quot;https://www.npmjs.com/package/mp3-duration&quot;&gt;&lt;code&gt;mp3-duration&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://www.npmjs.com/package/node-id3&quot;&gt;&lt;code&gt;node-id3&lt;/code&gt;&lt;/a&gt; to extract that data. I can then fill in the shownotes and push the new episode.&lt;/p&gt;
&lt;h2&gt;RSS feed&lt;/h2&gt;
&lt;p&gt;I was able to replicate &lt;a href=&quot;https://ruminatepodcast.com/feed.xml&quot;&gt;the RSS feed&lt;/a&gt; from Simplecast with this new setup but for some reason Safari doesn&#39;t auto-recognise it as a feed that can be opened in Podcasts/NetNewsWire. If anyone knows what attribute triggers this, I&#39;d love to know.&lt;/p&gt;
&lt;p&gt;All of the code for this is &lt;a href=&quot;https://github.com/rknightuk/ruminate&quot;&gt;on GitHub&lt;/a&gt; and you can see see the &lt;a href=&quot;https://ruminatepodcast.com&quot;&gt;new website here&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>Moving Ruminate's site from Simplecast to Eleventy</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Two Social Networks? In This Economy?</title>
    <link href="https://rknight.me/blog/two-social-networks-in-this-economy/"/>
    <updated>2022-12-22T00:00:00Z</updated>
    <id>https://rknight.me/two-social-networks-in-this-economy/</id>
    <content type="html">&lt;p&gt;The past few months Micro.blog (M.b.) has improved its support for Mastodon and thanks to Space Karen doing what he does best, I&#39;ve been following more and more people from there as they join via M.b.&lt;/p&gt;
&lt;p&gt;This has led to my timeline being busy which &lt;em&gt;is&lt;/em&gt; good, but the way people post on Mastodon is very different to M.b. Threads (write a damn blog post please), posts with content that warnings (which rightly in my opinion M.b doesn&#39;t support), boosts (again not supported on M.b.), as well as hashtags have made the timeline feel messy and disconnected from the rest of M.b.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href=&quot;https://omg.lol&quot;&gt;omg.lol&lt;/a&gt;. omg.lol is a service that has a whole bunch of features, one of which is a Mastodon instance for users, &lt;a href=&quot;social.lol&quot;&gt;social.lol&lt;/a&gt;. As a side note, until the end of the year it&#39;s only $5 a year (going up to $20 in 2023) so now is a good time to &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;sign up&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One thing that had put me off signing up on any given instance is what if it shuts down because most of them are free and although some have Patreons, I&#39;m not sure that&#39;s a sustainable model for smaller instances in the long run. Because social.lol is linked directly to a service I&#39;m paying for I feel confident it&#39;s not going anywhere any time soon.&lt;/p&gt;
&lt;p&gt;After &lt;a href=&quot;https://toot.rknight.me/2022/12/16/those-of-you.html&quot;&gt;asking on M.b&lt;/a&gt; about how people use both I made the decision to cross-post everything to Mastodon, keeping M.b as the source of truth. This has worked pretty well the past week, although I did hit some cross-posting issues of my own doing but I should be able to iron these out as I go. I&#39;m also boosting some posts on Mastodon and may even do a &lt;a href=&quot;https://social.lol/@sophie/109550690932963078&quot;&gt;bit of shitposting&lt;/a&gt; from time to time.&lt;/p&gt;
&lt;p&gt;I don&#39;t really have a conclusion here other than I&#39;m using both things for now. I might even checkout &lt;a href=&quot;https://pixelfed.org/&quot;&gt;Pixelfed&lt;/a&gt; at some point.&lt;/p&gt;
&lt;p&gt;If you want to follow me you can do so on &lt;a href=&quot;https://micro.blog/rknightuk&quot;&gt;Micro.blog&lt;/a&gt; or on &lt;a href=&quot;https://social.lol/@robb&quot;&gt;social.lol/@robb&lt;/a&gt;. But probably don&#39;t follow me on both lest you see every post twice.&lt;/p&gt;
</content>
    <summary>Why I'm using Micro.blog and Mastodon</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Prami&#39;s Challenge</title>
    <link href="https://rknight.me/blog/pramis-challenge/"/>
    <updated>2022-12-18T07:43:47Z</updated>
    <id>https://rknight.me/pramis-challenge/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://social.lol/@prami/109530090151262300&quot;&gt;Prami posted a challenge on social.lol&lt;/a&gt; to decode this string and win a lifetime subscription to &lt;a href=&quot;https://home.omg.lol/referred-by/robb&quot;&gt;omg.lol&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The string below is an encoded lifetime omg.lol gift code:&lt;/p&gt;
&lt;p&gt;eoad1o1fpoawctnjeiri11dmj7rir6d8ehadkt4seo6u4&lt;/p&gt;
&lt;p&gt;[...]&lt;/p&gt;
&lt;p&gt;in this format: XXXX-XXXX-XXXX-XXXX&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I figured I&#39;d have a go which ended up being a good few hours. Then I &lt;a href=&quot;https://toot.rknight.me/2022/12/17/this-challenge-from.html&quot;&gt;kind of lost my mind a bit&lt;/a&gt;. Then went to bed having given up (and needing to be up for a flight this morning).&lt;/p&gt;
&lt;p&gt;Overnight, &lt;a href=&quot;https://social.lol/@jmj&quot;&gt;Joanna&lt;/a&gt; solved it and I felt like I&#39;d been presented with a sock, I was free. &lt;a href=&quot;https://social.lol/@prami/109531877004198974&quot;&gt;The solution&lt;/a&gt; was 3 schemes: &lt;code&gt;z-base-32&lt;/code&gt; then &lt;code&gt;rot13&lt;/code&gt; then &lt;code&gt;base64&lt;/code&gt;. I googled &lt;em&gt;a lot&lt;/em&gt; last night and not once did I see &lt;a href=&quot;https://en.wikipedia.org/wiki/Base32#z-base-32&quot;&gt;&lt;code&gt;z-base-32&lt;/code&gt;&lt;/a&gt; so I had no chance (although I &lt;em&gt;was&lt;/em&gt; &lt;a href=&quot;https://cryptii.com/pipes/z-base-32&quot;&gt;on a website that supports it&lt;/a&gt; but clearly didn&#39;t see it).&lt;/p&gt;
&lt;p&gt;Other things I tried:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Various different cypher detectors&lt;/li&gt;
&lt;li&gt;Asking &lt;a href=&quot;https://chat.openai.com/chat&quot;&gt;ChatGPT&lt;/a&gt; nicely&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://hashcat.net/hashcat/&quot;&gt;hashcat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Ciphey/Ciphey&quot;&gt;Ciphey&lt;/a&gt; - this one crashed my computer trying to run overnight&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>I attempted Prami's challenge and didn't even get close</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>ChatGPT and mySQL Database Schemas</title>
    <link href="https://rknight.me/blog/chatcgt-and-mysql-database-schemas/"/>
    <updated>2022-12-16T19:38:40Z</updated>
    <id>https://rknight.me/chatcgt-and-mysql-database-schemas/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://chat.openai.com/chat&quot;&gt;ChatGPT&lt;/a&gt; is wild. I entered &amp;quot;&lt;em&gt;Describe a mysql database schema for tracking the owned books of multiple people&lt;/em&gt;&amp;quot; and it came back with the queries to write the tables including foreign keys:&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; people &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  id &lt;span class=&quot;token keyword&quot;&gt;INTEGER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  name &lt;span class=&quot;token keyword&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; books &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  id &lt;span class=&quot;token keyword&quot;&gt;INTEGER&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  title &lt;span class=&quot;token keyword&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  author &lt;span class=&quot;token keyword&quot;&gt;VARCHAR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;INTEGER&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; owned_books &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  person_id &lt;span class=&quot;token keyword&quot;&gt;INTEGER&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  book_id &lt;span class=&quot;token keyword&quot;&gt;INTEGER&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;person_id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; book_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;FOREIGN&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;person_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;REFERENCES&lt;/span&gt; people&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;FOREIGN&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;book_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;REFERENCES&lt;/span&gt; books&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I do things like this regularly so I &lt;em&gt;can&lt;/em&gt; do this no problem but having a rough draft dumped in front of me within seconds is handy. It even gives examples of what queries you could run with the data, so I followed up with &amp;quot;&lt;em&gt;What would the query for how many books each person owns look like?&lt;/em&gt;&amp;quot;&lt;/p&gt;
&lt;pre class=&quot;language-sql&quot;&gt;&lt;code class=&quot;language-sql&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;COUNT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ob&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;book_id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AS&lt;/span&gt; num_books&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; people p&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;JOIN&lt;/span&gt; owned_books ob &lt;span class=&quot;token keyword&quot;&gt;ON&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ob&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;person_id&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;GROUP&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;BY&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;m not convinced I&#39;m getting replaced &lt;em&gt;yet&lt;/em&gt; but I&#39;m a tiny bit more worried than I was a few weeks ago.&lt;/p&gt;
</content>
    <summary>I tried ChatGPT for a common task and it worked pretty well</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Lite YouTube for Micro.blog</title>
    <link href="https://rknight.me/blog/lite-youtube-for-micro-blog/"/>
    <updated>2022-12-06T00:00:00Z</updated>
    <id>https://rknight.me/lite-youtube-for-micro-blog/</id>
    <content type="html">&lt;p&gt;I&#39;ve published a new &lt;a href=&quot;https://micro.blog&quot;&gt;Micro.blog&lt;/a&gt; plugin called &lt;a href=&quot;https://github.com/rknightuk/micro-blog-lite-youtube&quot;&gt;Lite YouTube&lt;/a&gt; which does one thing: finds YouTube links in posts and appends a &lt;a href=&quot;https://github.com/paulirish/lite-youtube-embed&quot;&gt;lite-youtube-embed&lt;/a&gt; to the post. Example before and after below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/lite-youtube-before.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/lite-youtube-after.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can see it working on &lt;a href=&quot;https://toot.rknight.me/2022/12/04/last-of-us.html&quot;&gt;this post about The Last of Us&lt;/a&gt; or on &lt;a href=&quot;https://toot.rknight.me/2022/11/22/i-just-realised.html&quot;&gt;this post with two videos&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Why did I do this instead of using &lt;a href=&quot;https://discourse.gohugo.io/t/embed-youtube-video/2692/7&quot;&gt;YouTube shortcodes&lt;/a&gt;? Two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Shortcodes are great but what if I change where my site is hosted? Those links won&#39;t work any more&lt;/li&gt;
&lt;li&gt;(This is the real reason) I will forget, I&#39;m too lazy to do it, this is automatic.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can install it &lt;a href=&quot;https://micro.blog/account/plugins/view/83&quot;&gt;from the plug-in directory&lt;/a&gt; and &lt;a href=&quot;https://github.com/rknightuk/micro-blog-lite-youtube&quot;&gt;view the code on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A plugin to automatically append Lite YouTube embeds to posts</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My Office Setup</title>
    <link href="https://rknight.me/blog/office-setup/"/>
    <updated>2022-12-05T00:00:00Z</updated>
    <id>https://rknight.me/office-setup/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/office-setup-tv.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;A couple of weeks ago I posted a photo in the MacStories Discord and Federico &lt;s&gt;demanded&lt;/s&gt; asked very nicely if I would write about it, so here we are. I have a lot of consoles which means I have a lot of games and controllers. I’ve never been one to sell games after I’ve finished them so I always had a collection of some sort. I worked at a second hand game shop while I was at university so my collection grew rapidly in the 11 months I was there and I have continued to pick up games here and there over the years. As of right now I have 315 games across 12 systems, a third of which are for the PlayStation 2. A lot of my all-time favourite games are for the PS2 including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tony Hawk Pro Skater 3 and 4&lt;/li&gt;
&lt;li&gt;Jak and Daxter&lt;/li&gt;
&lt;li&gt;Grand Theft Auto: Vice City (side note: despite the launch bugs, the remaster version of this is excellent)&lt;/li&gt;
&lt;li&gt;Mashed: Fully Loaded&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m a big fan of single-player story-driven games so the majority of my collection are those types of games. I’m currently playing through Horizon Forbidden West which I am loving.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/office-setup-cupboard.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My setup consists of a PS5, a PS3, a pink PS2 which I adore, an Xbox 360, and an Xbox One all hooked up to a HiSense 4K 43&amp;quot; TV that I bought a few years ago. I’m not sure in 2022 if I would even be able to buy a TV with this many inputs. The modern consoles use HDMI and the PS2 and 360 use &lt;a href=&quot;https://en.wikipedia.org/wiki/SCART&quot;&gt;SCART cables&lt;/a&gt; which was widely used on TVs in the UK and Europe and is somewhat better than using component input.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://gameye.app/&quot;&gt;GameEye&lt;/a&gt; to keep track of my the games and consoles I own. I log the games I’ve played with Almanac, a custom blogging system I made for tracking things I’ve watched and played. (Update: I now use &lt;a href=&quot;https://micro.blog/rknightuk&quot;&gt;Micro.blog&lt;/a&gt; for this). In my attic I have a Sega Master System, Nintendo 64, and a Nintendo Wii, plus there is a Nintendo Switch in the living room.&lt;/p&gt;
&lt;p&gt;Until I add shelves to my office to have at least some of my games on display, I’m using the built-in cupboard as storage for my games. I built the shelves in there myself so they are a perfect size for double-stacking games. I added an &lt;a href=&quot;https://www.ikea.com/gb/en/p/skadis-pegboard-combination-white-s09216595/&quot;&gt;Ikea Skadis&lt;/a&gt; to the inside of the door to various gaming-related things like cables, controllers, and memory cards for the older consoles.&lt;/p&gt;
&lt;p&gt;I have some ideas for the office including a custom controller holder, shelves to display my games and my many collector’s edition statues (these are also in storage right now), and I’m also considering wall-mounting the TV. I also need to alphabetise the games instead of dumping them in the cupboard like they are right now.&lt;/p&gt;
</content>
    <summary>My office setup</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My Favourite Albums of 2022</title>
    <link href="https://rknight.me/blog/my-favourite-albums-of-2022/"/>
    <updated>2022-12-02T19:50:00Z</updated>
    <id>https://rknight.me/my-favourite-albums-of-2022/</id>
    <content type="html">&lt;p&gt;It&#39;s been a really good year for music especially for artists I&#39;ve been listening to for years.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/gb/album/love-sux-deluxe/1655449416&quot;&gt;Avril Lavinge - Love Sux&lt;/a&gt; - This is the link to the deluxe version which contains some excellent acoustic versions of some of the tracks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/gb/album/kings-of-the-new-age/1607207409&quot;&gt;State Champs - Kings of the New Age&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/harder-than-it-looks/1600965603&quot;&gt;Simple Plan - Hard Than It Looks&lt;/a&gt; - This is as good an album as they&#39;ve ever made.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/gb/album/holy-fvck/1628440994&quot;&gt;Demi Levato - HOLY FVCK&lt;/a&gt; - this was a suprise entry for me, I didn&#39;t expect to like it as much as I do.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/gb/album/just-woke-up/1603918127&quot;&gt;Jaret Jay Reddick - Just Woke Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/gb/album/super-relatable/1637732324&quot;&gt;Beefy - Super Relatable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/gb/album/a-whole-new-wurst-2/1625667455&quot;&gt;Punk Rock Factory - A Whole New Wurst 2&lt;/a&gt; - Their  cover of &lt;em&gt;Surface Pressure&lt;/em&gt; is amazing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The released tracks on &lt;a href=&quot;https://music.apple.com/gb/album/tear-me-to-pieces/1647133854&quot;&gt;Story of the Year&#39;s new album&lt;/a&gt; are fantastic. I can&#39;t wait to hear the rest of them.&lt;/p&gt;
&lt;p&gt;Finally I discovered &lt;a href=&quot;https://music.apple.com/gb/album/never-look-back-deluxe/1634447768&quot;&gt;Never Look Back by Goldfinger&lt;/a&gt;. Apparently it came out in 2020 and I completely missed it. There&#39;s a great version of &lt;em&gt;Here In Your Bedroom&lt;/em&gt; featuring Avril on this deluxe version of the album.&lt;/p&gt;
</content>
    <summary>My favourite albums of 2022</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>How to Copy Gifs to Clipboard Programatically</title>
    <link href="https://rknight.me/blog/how-not-to-copy-gif-to-clipboard-programatically/"/>
    <updated>2022-12-01T00:00:00Z</updated>
    <id>https://rknight.me/how-not-to-copy-gif-to-clipboard-programatically/</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;Update 1&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/edwellbrook/grabgif&quot;&gt;Ed Wellbrook solved this with grabgif&lt;/a&gt; like the absolute hero he is.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Turns out in my frustrated state, some of the things I tried &lt;em&gt;did&lt;/em&gt; work but I just didn&#39;t notice (or I did something like clear the clipboard by accident). After looking at Ed&#39;s solution it clicked. This solution &lt;em&gt;does&lt;/em&gt; work:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;osascript &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &#39;set the clipboard to POSIX &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/path/to/animated.gif&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I will leave the rest of the article but everything below is kind of useless now.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you&#39;ve come to this post to find out how to copy an animated gif to the clipboard programatically: I&#39;m sorry. All I have is many solutions that either don&#39;t work at all, or only partially work.&lt;/p&gt;
&lt;p&gt;Why was I doing this? I&#39;ve had an idea for an &lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt; workflow for a while that would list all the gifs in my gif folder then copy it to the clipboard so I can paste in to Slack (or anywhere that supports copy/pasting animated gifs). I like to keep things as simple as possible with &lt;a href=&quot;https://github.com/rknightuk/alfred-workflows&quot;&gt;my Alfred workflows&lt;/a&gt; so I figured I&#39;d try AppleScript/JXA first.&lt;/p&gt;
&lt;h2&gt;AppleScript and JXA&lt;/h2&gt;
&lt;p&gt;There are loads of StackOverflow posts describing how to copy &lt;em&gt;images&lt;/em&gt;, some of which even say it works with gifs. They do not. At best, some of them will copy the first frame of the gif to the clipboard, at worst they flat out don&#39;t work.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# these work but will only get the first frame&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;osascript &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;set the clipboard to (read (POSIX file &quot;/path/to/animated.gif&quot;) as {«class GIFf»})&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;osascript &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;set the clipboard to (read &quot;/path/to/animated.gif&quot; as GIF picture)&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;# these do not work at all&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;osascript &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;set the clipboard to (read (POSIX file &quot;/path/to/animated.gif&quot;)&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;osascript &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;set the clipboard to POSIX file &quot;/path/to/animated.gif&quot;&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Command Line Tools&lt;/h2&gt;
&lt;p&gt;I found a number of CLI tools that looked promising. The first of these I came across was &lt;a href=&quot;https://gist.github.com/mwender/49609a18be41b45b2ae4&quot;&gt;&lt;code&gt;impbcopy&lt;/code&gt;&lt;/a&gt; but this only works with &lt;code&gt;png&lt;/code&gt; files. Perhaps there&#39;s a way to modify this to work but I wasn&#39;t able to see how to do that. Likewise with &lt;a href=&quot;https://github.com/moicci/pngpaste&quot;&gt;&lt;code&gt;pngpaste&lt;/code&gt;&lt;/a&gt; which claims to support gifs.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Having spent a good few hours on this at this point I am assuming this can&#39;t be done. If someone knows of a way to do this I would be very interested to see a solution.&lt;/p&gt;
</content>
    <summary>My futile attempts at trying to copy a gif to the clipboard programatically</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Music Replay 2022</title>
    <link href="https://rknight.me/blog/music-replay-2022/"/>
    <updated>2022-11-29T16:33:59Z</updated>
    <id>https://rknight.me/music-replay-2022/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://replay.music.apple.com&quot;&gt;Apple Music Replay&lt;/a&gt; is a vast improvement on last year. I grabbed some of the data so I have a record of it (I have no idea if you can access a previous years data or not).&lt;/p&gt;
&lt;p&gt;No suprises Hamilton is top again with Lin-Manuel Miranda and Leslie Odom, Jr. taking 2 of the top artist spots. Combined, they take the real top spot.&lt;/p&gt;
&lt;p&gt;I was in the top 100 listeners for Punk Rock Factory and Goldfinger.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3695 songs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;696 Artists&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Top artists:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/punk-rock-factory/975678831&quot;&gt;Punk Rock Factory&lt;/a&gt; - 4,447 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/goldfinger/2089079&quot;&gt;Goldfinger&lt;/a&gt; - 3,354 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/lin-manuel-miranda/329027198&quot;&gt;Lin-Manuel Miranda&lt;/a&gt; - 3,292 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/linkin-park/148662&quot;&gt;Linkin Park&lt;/a&gt; - 3,046 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/leslie-odom-jr/580650079&quot;&gt;Leslie Odom, Jr.&lt;/a&gt; - 2,886 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/simple-plan/150861&quot;&gt;Simple Plan&lt;/a&gt; - 2,303 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/bowling-for-soup/1650849&quot;&gt;Bowling for Soup&lt;/a&gt; - 2,015 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/machine-gun-kelly/465954501&quot;&gt;Machine Gun Kelly&lt;/a&gt; - 1,920 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/avril-lavigne/459885&quot;&gt;Avril Lavigne&lt;/a&gt; - 1,837 minutes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/artist/mc-lars/45378751&quot;&gt;MC Lars&lt;/a&gt; - 1,772 minutes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;231 Albums&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have no idea how it works out the play count on albums but I assume this is individual tracks so I&#39;ve worked out the times I&#39;ve played an album based on this. Apple doesn&#39;t give numbers for albums 6-10.&lt;/p&gt;
&lt;p&gt;Top Albums:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/hamilton-an-american-musical-original-broadway-cast/1025210938&quot;&gt;Hamilton: An American Musical (Original Broadway Cast Recording)&lt;/a&gt; - 1,581 plays / ~35 times&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/never-look-back-deluxe/1634447768&quot;&gt;Never Look Back (Deluxe) - Goldfinger&lt;/a&gt; - 1,099 plays / ~57 times&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/harder-than-it-looks/1600965603&quot;&gt;Harder Than It Looks - Simple Plan&lt;/a&gt; 503 plays / ~50 times&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/love-sux-deluxe/1655449416&quot;&gt;Love Sux - Avril Lavigne&lt;/a&gt; - 464 plays / ~38 times&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/just-woke-up/1603918127&quot;&gt;Just Woke Up - Jaret Ray Reddick&lt;/a&gt; - 448 plays / ~37 times&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/tickets-to-my-downfall-sold-out-deluxe/1533882860&quot;&gt;Tickets to My Downfall (SOLD OUT Deluxe)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/recharged/701162375&quot;&gt;RECHARGED - Linkin Park&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/kings-of-the-new-age/1607207409&quot;&gt;Kings of the New Age - State Champs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/with-sprinkles/372936293&quot;&gt;With Sprinkles - Beefy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://music.apple.com/us/album/single-and-famous/328126452&quot;&gt;Single and Famous - K.Flay and MC Lars&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
    <summary>My 2022 music replay from Apple Music</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Importing Tweets into Micro.blog</title>
    <link href="https://rknight.me/blog/importing-tweets-into-microblog/"/>
    <updated>2022-11-17T00:00:00Z</updated>
    <id>https://rknight.me/importing-tweets-into-microblog/</id>
    <content type="html">&lt;p&gt;I wanted to import a bunch of tweets from my archive (mostly cat photos and a few other bits) but I didn&#39;t want to have to manually go through each tweet, copy the text and download the photos. So I wrote a script to do it for me once I had the IDs (which I got with my &lt;a href=&quot;https://rknight.me/get-safari-tabs-shortcut/&quot;&gt;Safari shortcut&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;One thing that had annoyed me for a while is I didn&#39;t keep a diary/note of things that happened and my thoughts during the first year of so of the pandemic but thanks to going through my archive I now &lt;a href=&quot;https://toot.rknight.me/categories/covid/&quot;&gt;have that&lt;/a&gt;. On a cheerier note I have a lovely collection of animals in the &lt;a href=&quot;https://toot.rknight.me/categories/pets/&quot;&gt;pets category&lt;/a&gt;. These additional categories were done manually (with the help of &lt;a href=&quot;https://github.com/sbarex/QLMarkdown&quot;&gt;QLMarkdown&lt;/a&gt;) as I couldn&#39;t think of a way to automate this.&lt;/p&gt;
&lt;p&gt;Once I had the IDs it was a case of getting the format correctly (for example, Micro.blog will fail an import with empty categories in the YAML). I was able to take ~450 tweets, convert them to markdown and &lt;a href=&quot;https://toot.rknight.me/categories/imported-tweets/&quot;&gt;import them into Micro.blog&lt;/a&gt;. For example, this tweet:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/boristweet.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;becomes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
date: 2022-10-20T13:56:19+00:00
categories: Imported Tweets
---

&amp;quot;You could not live with your own failure. Where did that bring you? Back to me&amp;quot;

![](https://pbs.twimg.com/media/Ffg6jkDXkAARD4p.jpg)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The script isn&#39;t perfect. It doesn&#39;t do anything with hashtags or usernames, nor does it check if a tweet is a reply or a retweet. The &lt;a href=&quot;https://github.com/rknightuk/twitter-to-micro-blog&quot;&gt;project readme.md&lt;/a&gt; has steps for using it on your own archive.&lt;/p&gt;
</content>
    <summary>A script to import tweets from your tweet archive to Micro.blog</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The &quot;Best&quot; Tweets</title>
    <link href="https://rknight.me/blog/the-best-tweets/"/>
    <updated>2022-11-15T00:00:00Z</updated>
    <id>https://rknight.me/the-best-tweets/</id>
    <content type="html">&lt;p&gt;A few days ago &lt;a href=&quot;https://twitter.com/jamesthomson/status/1591538731756191745&quot;&gt;James Thomson posted&lt;/a&gt; that you can find your tweets based on how many likes they got with the following link (switching my username for yours):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/search?q=from%3Arknightuk%20min_faves%3A1000&amp;amp;src=typed_query&amp;amp;f=live&quot;&gt;https://twitter.com/search?q=from%3Arknightuk%20min_faves%3A1000&amp;amp;src=typed_query&amp;amp;f=live&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I think it&#39;s very likely my account will be deleted at some point so I figured I&#39;d have a little look at my best tweets and archive them here (I am using &amp;quot;best&amp;quot; in the loosest possible way here).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Back to the Future Day tweet - 2015-10-21 (&lt;a href=&quot;https://hellsite.rknight.me/656762307494682624&quot;&gt;link&lt;/a&gt;&lt;/strong&gt;)&lt;/p&gt;
&lt;p&gt;This has a typo that will haunt me forever (should be &amp;quot;Emmett&amp;quot; not &amp;quot;Emmet&amp;quot;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Are you Marty McFly? I’ve got something for you”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;opens letter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;“Emmet Brown would like you to join his professional network on LinkedIn”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I also did &lt;s&gt;the same tweet&lt;/s&gt; a totally original tweet when GDPR caused everyone to send a thousand emails (&lt;a href=&quot;https://hellsite.rknight.me/999648514534764544&quot;&gt;link&lt;/a&gt;).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Are you Marty McFly? I’ve got something for you”&lt;/p&gt;
&lt;p&gt;&lt;em&gt;opens letter&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;“Please confirm you want to continue to receive letters from Dr. Emmett Brown”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Alt Key - 2016-08-21 (&lt;a href=&quot;https://hellsite.rknight.me/767337245133144064&quot;&gt;link&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The alt symbol (⌥) is like a track switch. An alternate route. Alt.&lt;/p&gt;
&lt;p&gt;Mind blown.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dark Pattern - 2018-05-27 (&lt;a href=&quot;https://hellsite.rknight.me/1000748036367310848&quot;&gt;link&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This “no I hate myself” pattern is horrible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/hate_discounts.jpg&quot; width=&quot;600&quot; height=&quot;282&quot; alt=&quot;&quot; /&gt;
&lt;p&gt;&lt;strong&gt;Boris × Thanos - 2022-10-20 (&lt;a href=&quot;https://hellsite.rknight.me/1583079656760410112&quot;&gt;link&lt;/a&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I didn&#39;t make this image. I had the idea and then grabbed the image from &lt;a href=&quot;https://twitter.com/mattlcapon/status/1421631601902039043&quot;&gt;this tweet&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;You could not live with your own failure. Where did that bring you? Back to me&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/boris_thanos.jpg&quot; width=&quot;600&quot; height=&quot;332&quot; alt=&quot;&quot; /&gt;
</content>
    <summary>My post popular tweets before Twitter dies</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Year of Renovation</title>
    <link href="https://rknight.me/blog/year-of-renovation/"/>
    <updated>2022-11-08T00:00:00Z</updated>
    <id>https://rknight.me/year-of-renovation/</id>
    <content type="html">&lt;p&gt;We moved into our house November 3rd 2021, just over a year ago. Most of the house hadn&#39;t been decorated since it was built in the &#39;70s so everything needed redoing. With the exception of a few carpets and a bit of painting, everything is now done.&lt;/p&gt;
&lt;h3&gt;Bathroom&lt;/h3&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/bathroom_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/bathroom_after.jpg&quot; /&gt;
&lt;h3&gt;Main Bedroom&lt;/h3&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/main_bedroom_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/main_bedroom_after.jpg&quot; /&gt;
&lt;h3&gt;Spare Room&lt;/h3&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/spare_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/spare_after.jpg&quot; /&gt;
&lt;h3&gt;Office&lt;/h3&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/office_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/office_after.jpg&quot; /&gt;
&lt;h3&gt;Nursery&lt;/h3&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/nursery_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/nursery_after.jpg&quot; /&gt;
&lt;h3&gt;Kitchen&lt;/h3&gt;
&lt;p&gt;This was the biggest project. We extended into the garage to make a kitchen/diner and add a utility room.&lt;/p&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/kitchen_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/kitchen_after.jpg&quot; /&gt;
&lt;h3&gt;Living Room&lt;/h3&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/lounge_before.jpg&quot; /&gt;
&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/house/lounge_after.jpg&quot; /&gt;
</content>
    <summary>Before and after photos of our house after renovation</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Follow Mastodon User on Micro.blog Shortcut</title>
    <link href="https://rknight.me/blog/follow-mastodon-user-on-micro.blog-shortcut/"/>
    <updated>2022-11-03T00:00:00Z</updated>
    <id>https://rknight.me/follow-mastodon-user-on-micro.blog-shortcut/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://micro.blog&quot;&gt;Micro.blog&lt;/a&gt; has support for following and replying to Mastodon users but getting from someone&#39;s profile on Mastodon to the follow page on Micro.blog can be a pain. To search for a user you need have it in the format of &lt;code&gt;cooluser@mastodon.instance&lt;/code&gt; which isn&#39;t the same as the profile URLs. To make this easier I made a shortcut that does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Takes the current Safari URL, for example &lt;code&gt;https://mastodon.instance/@cooluser&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Gets the domain (&lt;code&gt;mastodon.instance&lt;/code&gt;) and the path (&lt;code&gt;@cooluser&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Swaps those round to become &lt;code&gt;cooluser@mastodon.instance&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Opens the page on Micro.blog to be able to follow that user (&lt;code&gt;https://micro.blog/cooluser@mastodon.instance&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It will also check to see if the path/username contains an &lt;code&gt;@&lt;/code&gt; symbol and if it doesn&#39;t will show an alert instead. This isn&#39;t ideal but given that Mastodon can have any domain, it&#39;s much harder to detect if it&#39;s a Mastodon site or not.&lt;/p&gt;
&lt;p&gt;There is a meta tag in the HTML with &lt;code&gt;profile:username&lt;/code&gt; as the property name but I don&#39;t know enough about Shortcuts to do this.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/fe47f7e4ed104f7dbb8202b49c3482c4&quot;&gt;Download Follow Mastodon User on Micro.blog shortcut v1.1&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Previous Versions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/c055237a4b744d9eb5b120fe017b8356&quot;&gt;v1.0&lt;/a&gt; - this version won&#39;t work if the user hasn&#39;t been seen before by Micro.blog&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>A shortcut to redirect to the correct follow page to follow a Mastodon user on Micro.blog</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Fix for Bluetooth Audio Cutting Out on the Mac</title>
    <link href="https://rknight.me/blog/fix-for-bluetooth-audio-cutting-out-on-the-mac/"/>
    <updated>2022-09-14T00:00:00Z</updated>
    <id>https://rknight.me/fix-for-bluetooth-audio-cutting-out-on-the-mac/</id>
    <content type="html">&lt;p&gt;Bluetooth cutting out randomly on my Mac when using wireless headphones has been an issue for me for ages. I assumed it was because of everyones BT devices in the office but I&#39;m here by myself this morning and it was still happening.&lt;/p&gt;
&lt;p&gt;Had a google around and found &lt;a href=&quot;https://www.reddit.com/r/MacOSBeta/comments/qjgqjx/i_think_ive_found_a_fix_for_the_bluetooth/&quot;&gt;this thread&lt;/a&gt; on Reddit and it solved it. Settings &amp;gt; Sharing &amp;gt; Turn off AirPlay Reciever.&lt;/p&gt;
&lt;p&gt;I wish I&#39;d looked for a solution sooner.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/settings_airplay.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Update for Ventura: System Settings &amp;gt; General &amp;gt; AirDrop &amp;amp; Handoff. Thanks &lt;a href=&quot;https://www.trevorkay.me&quot;&gt;Trevor&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A fix for bluetooth audio cutting out on MacOS</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Thoughts on Micro.blog</title>
    <link href="https://rknight.me/blog/thoughts-on-micro-blog/"/>
    <updated>2022-05-14T00:00:00Z</updated>
    <id>https://rknight.me/thoughts-on-micro-blog/</id>
    <content type="html">&lt;p&gt;A couple of weeks ago I signed up to &lt;a href=&quot;https://micro.blog&quot;&gt;Micro.blog&lt;/a&gt; and stopped using Twitter, Instagram, and Pocket.&lt;/p&gt;
&lt;h3&gt;Twitter&lt;/h3&gt;
&lt;p&gt;Micro.blog (MB for the rest of the post) has no likes, no follower counts, no retweets, and no &lt;s&gt;post dunking&lt;/s&gt; quote tweets. If I post something, I don&#39;t know who saw it or who enjoyed it but it doesn&#39;t matter; I&#39;m posting it because I want to. Might be &lt;a href=&quot;https://toot.rknight.me/2022/05/12/stripe-have-opensourced.html&quot;&gt;something interesting&lt;/a&gt; or me &lt;a href=&quot;https://toot.rknight.me/2022/05/13/mcr-released-a.html&quot;&gt;being nostalgic for a time when I thought I was, but definitely wasn&#39;t, cool&lt;/a&gt; but none of it is being posted to try and &amp;quot;go viral&amp;quot; or get likes.&lt;/p&gt;
&lt;p&gt;The lack of follower count, or even knowing if someone follows you, means there&#39;s no guilt for unfollowing someone or wondering why someone unfollowed you. No likes means if someone really does like a post a lot, they can reply and say so. &lt;a href=&quot;https://blog.ayjay.org/a-bit-of-advice/&quot;&gt;Alan Jacobs has an excellent post&lt;/a&gt; about this.&lt;/p&gt;
&lt;p&gt;I&#39;ve looked at Twitter a few times in the past month and I was reminded just how negative it is. I&#39;m as guilty as anyone for dunking on politicians, crypto bros, and general idiots. They probably deserve it but it is &lt;em&gt;exhausting&lt;/em&gt; and it&#39;s pretty much every other tweet. I don&#39;t follow news sites or &amp;quot;brands&amp;quot; on Twitter, these are all just normal people but we&#39;re all (rightly) angry about &lt;em&gt;the things&lt;/em&gt;. I just don&#39;t think it&#39;s good for my mental health to be that annoyed about a thousand things all the time.&lt;/p&gt;
&lt;h3&gt;Instagram&lt;/h3&gt;
&lt;p&gt;I hadn&#39;t posted to Instagram for a long time. I&#39;d felt uneasy about feeding content to the beast that is Facebook for a while but I also thought perhaps I didn&#39;t have anything &lt;em&gt;worth&lt;/em&gt; posting. A few days after I signed up, MB were running the &lt;a href=&quot;https://micro.welltempered.net/2022/04/30/the-may-photoblogging.html&quot;&gt;May Photoblogging challenge&lt;/a&gt;. 30 days, 30 prompts, post a photo each day. Turns out I do have things to post and you can &lt;a href=&quot;https://toot.rknight.me/categories/may-2022-photoblogging-challenge/&quot;&gt;view my challenge photos here&lt;/a&gt;. Challenge photos are collected in this &lt;a href=&quot;http://micro.blog/discover/mbmay/grid&quot;&gt;nice grid view&lt;/a&gt; and it&#39;s been a great way to find all the cat people.&lt;/p&gt;
&lt;h3&gt;Pocket&lt;/h3&gt;
&lt;p&gt;This one is less &amp;quot;stick it to the man&amp;quot; and more &amp;quot;just use one service for a bunch of things&amp;quot;. MB has a bookmarking feature that works for exactly my needs and I &lt;a href=&quot;https://rknight.me/save-bookmark-to-micro-blog-shortcut/&quot;&gt;whipped together a shortcut&lt;/a&gt; as well as making a &lt;a href=&quot;https://micromarks.rknight.me&quot;&gt;little web app to manage my bookmarks&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Other things I like about Micro.blog&lt;/h3&gt;
&lt;p&gt;Editable posts. What a concept.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://micro.blog/discover&quot;&gt;discover timeline&lt;/a&gt; is a manually curated timeline of features posts from real people and is an excellent starting point to find users to follow. &lt;a href=&quot;https://micro.blog/jean&quot;&gt;Jean&lt;/a&gt; does an excellent job of curating posts for the discover page as well as helping new people to the service. The other way to find interesting posts are the automatic timelines based on &lt;a href=&quot;https://help.micro.blog/t/emoji-in-discover/34&quot;&gt;emoji topics&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can follow Mastodon users from MB which mean I can still get updates from &lt;a href=&quot;https://duck.haus/about&quot;&gt;the duck haus&lt;/a&gt; or any other Mastodon instance. Mastodon users can follow MB users as well. When using a custom domain with MB you can set a Mastodon-compatible username. For example mine is &lt;a href=&quot;https://micro.blog/rknightuk?remote_follow=1&quot;&gt;robb@toot.rknight.me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&#39;s &lt;a href=&quot;https://help.micro.blog/t/json-api/97&quot;&gt;an API&lt;/a&gt; which I&#39;m sure I&#39;ll be using more in the future.&lt;/p&gt;
&lt;h3&gt;Missing Pieces&lt;/h3&gt;
&lt;p&gt;As much as I&#39;ve complained about Twitter, there are people who I still want to subscribe to. Of course Twitter doesn&#39;t have RSS feeds any more but thankfully &lt;a href=&quot;https://netnewswire.com&quot;&gt;NetNewsWire&lt;/a&gt; allows me to subscribe to specific people so I&#39;m &amp;quot;following&amp;quot; a handful of Twitter accounts there instead.&lt;/p&gt;
</content>
    <summary>My thoughts on using Micro.blog for the past two weeks</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Get Safari Tabs Shortcut</title>
    <link href="https://rknight.me/blog/get-safari-tabs-shortcut/"/>
    <updated>2022-05-13T00:00:00Z</updated>
    <id>https://rknight.me/get-safari-tabs-shortcut/</id>
    <content type="html">&lt;p&gt;For &lt;a href=&quot;https://www.macstories.net/stories/introducing-automation-april/&quot;&gt;Automation April&lt;/a&gt; MacStories ran a &lt;a href=&quot;https://www.macstories.net/stories/introducing-the-2022-automation-april-shortcuts-contest-winners/&quot;&gt;contest&lt;/a&gt; where people could submit a shortcut and be in with a chance of winning an Analogue Pocket and a Stream Deck.&lt;/p&gt;
&lt;p&gt;Until the announcement of the contest I had never made a shortcut but I wanted to enter just for the fun of it (and that sweet role icon &lt;a href=&quot;http://plus.club&quot;&gt;in the members Discord&lt;/a&gt;). I decided to convert my existing &lt;a href=&quot;https://rknight.me/alfred-workflows/#085F8761-9FB4-492D-B466-D7CE943DCE60&quot;&gt;&lt;em&gt;Get Safari Tabs&lt;/em&gt; Alfred workflow&lt;/a&gt; to a shortcut.&lt;/p&gt;
&lt;p&gt;The shortcut gets all currently open tabs in Safari and converts them into one of 6 formats and then copies them to the clipboard&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Markdown list: &lt;code&gt;- [Robb Knight](https://rknight.me)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Markdown links: &lt;code&gt;[Robb Knight](https://rknight.me)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Links only: &lt;code&gt;https://rknight.me&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Titles only &lt;code&gt;Robb Knight&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Titles with links &lt;code&gt;Robb Knight https://rknight.me&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I use the workflow, and now the shortcut, fairly regularly for making &lt;a href=&quot;https://ruminatepodcast.com&quot;&gt;shownotes for Ruminate&lt;/a&gt; and for adding links to &lt;a href=&quot;https://intersect.rknight.me&quot;&gt;the Intersect&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The shortcut is MacOS only because it uses &lt;a href=&quot;https://developer.apple.com/library/archive/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/Articles/Introduction.html#//apple_r&quot;&gt;JXA&lt;/a&gt; to get the current tabs and formatting them. I&#39;m sure this could be done with shortcut actions but I already had the existing logic from the workflow and I couldn&#39;t see any advantage in converting the logic to actions.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/bfe5827f709a47909e6e81d098d5e507&quot;&gt;Download Get Safari Links Shortcut for MacOS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Update 2024-02-20: Chris has made something similar &lt;a href=&quot;https://chrismcleod.dev/blog/generate-a-markdown-list-of-open-safari-tabs-with-an-ios-shortcut/&quot;&gt;for iOS&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>My MacStories Automation April entry</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Save Bookmark to Micro.blog Shortcut</title>
    <link href="https://rknight.me/blog/save-bookmark-to-micro-blog-shortcut/"/>
    <updated>2022-04-28T00:00:00Z</updated>
    <id>https://rknight.me/save-bookmark-to-micro-blog-shortcut/</id>
    <content type="html">&lt;p&gt;I recently signed up (again) to &lt;a href=&quot;https://micro.blog&quot;&gt;Micro.blog&lt;/a&gt; in an attempt to move away from services run by &lt;a href=&quot;https://en.wikipedia.org/wiki/Elon_Musk&quot;&gt;billionare shitposters&lt;/a&gt;. I will probably write up a full post about it soon but you can hear me talk about it on &lt;a href=&quot;https://ruminatepodcast.com/episodes/144&quot;&gt;episode 144 of Ruminate&lt;/a&gt; or &lt;a href=&quot;https://toot.rknight.me&quot;&gt;view my micro blog here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the features Micro.blog offers is bookmarking of posts and links. After a &lt;a href=&quot;https://micro.blog/rknightuk/12770616&quot;&gt;conversation about using micro.blog as a read later service&lt;/a&gt; and finding the correct API I put together a shortcut to save bookmarks. You&#39;ll need to get an access token from &lt;a href=&quot;https://micro.blog/account/apps&quot;&gt;the apps settings page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.icloud.com/shortcuts/876d4c98272c4deb9f155a656a6929ec&quot;&gt;Download Bookmark on Micro.blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;MacOS shortcuts lacks support for using the sharesheet without a &lt;a href=&quot;https://apps.apple.com/us/app/sharebot-for-shortcuts/id1597340986?mt=12&quot;&gt;third-party app&lt;/a&gt; so instead you can run this shortcut whenever and it gets the current Safari page URL. The iOS version shows up in the share sheet so it can be used wherever you share links.&lt;/p&gt;
&lt;p&gt;&lt;s&gt;If there&#39;s a way to combine these so one shortcut works for both MacOS and iOS, I&#39;d love to hear it.&lt;/s&gt; Thanks to &lt;a href=&quot;https://micro.blog/pratik/12775485&quot;&gt;Pratik&lt;/a&gt; for showing me how to check the device type and make this one shortcut for both platforms.&lt;/p&gt;
</content>
    <summary>A shortcut to save bookmarks on micro.blog</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Building a PiSight</title>
    <link href="https://rknight.me/blog/building-a-pisight/"/>
    <updated>2022-02-10T00:00:00Z</updated>
    <id>https://rknight.me/building-a-pisight/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pisight.jpg&quot; alt=&quot;My finished PiSight&quot; /&gt;&lt;/p&gt;
&lt;p&gt;During the pandemic Max Braun managed to squeeze a Pi Zero with camera module &lt;a href=&quot;https://debugger.medium.com/todays-webcams-are-boring-so-i-brought-back-a-classic-291cc7c94c76&quot;&gt;into an Apple iSight camera&lt;/a&gt;. I came across the post a few weeks ago and decided to have a go myself.&lt;/p&gt;
&lt;p&gt;Despite the &lt;a href=&quot;https://www.raspberrypi.com/news/supply-chain-shortages-and-our-first-ever-price-increase/&quot;&gt;Rapsberry Pi shortage&lt;/a&gt; I was able to order a Pi Zero, the &lt;a href=&quot;https://shop.pimoroni.com/products/raspberry-pi-camera-module-v2?variant=19833929735&quot;&gt;camera module&lt;/a&gt;, the &lt;a href=&quot;https://shop.pimoroni.com/products/camera-cable-raspberry-pi-zero-edition?variant=32092803891283&quot;&gt;Pi Zero camera cable&lt;/a&gt;, and an &lt;a href=&quot;https://en.wikipedia.org/wiki/ISight&quot;&gt;iSight&lt;/a&gt;. I ordered the &lt;a href=&quot;https://github.com/maxbbraun/pisight/blob/master/PiSight.stl&quot;&gt;3D-printed internal chassis&lt;/a&gt; and &lt;a href=&quot;https://github.com/maxbbraun/pisight/issues/16&quot;&gt;this USB adaptor&lt;/a&gt; from &lt;a href=&quot;https://sgd3d.co.uk&quot;&gt;SGD3D&lt;/a&gt; which took about a week to arrive.&lt;/p&gt;
&lt;p&gt;I followed these &lt;a href=&quot;https://www.ifixit.com/Device/Apple_iSight_Webcam&quot;&gt;iFixIt teardowns&lt;/a&gt; to work out how to take the iSight apart, then looked at the &lt;a href=&quot;https://github.com/maxbbraun/pisight/issues&quot;&gt;issues on the PiSight repo&lt;/a&gt;, and &lt;a href=&quot;https://muffinresearch.co.uk/building-a-pisight/&quot;&gt;this blog post&lt;/a&gt;, to see other people putting theirs together. The main issue I had was having to trimming off the bottom two corners of the camera module to be able to fit it inside the iSight tube. I used &lt;a href=&quot;https://github.com/showmewebcam/showmewebcam&quot;&gt;&lt;code&gt;showmewebcam&lt;/code&gt;&lt;/a&gt; for the software, which boots incredibly quickly and makes it very easy to get going.&lt;/p&gt;
&lt;p&gt;Once I&#39;d wrangled it all together I used &lt;a href=&quot;https://handmirror.app&quot;&gt;Hand Mirror&lt;/a&gt; to check everything was working (the lighting is terrible in this temporary office hence why it&#39;s looks so bad):&lt;/p&gt;
&lt;center&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pisight-hand-mirror.png&quot; /&gt;&lt;/center&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.amazonaws.com/site/pisight-chassis.jpg&quot; alt=&quot;The chassis&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It may not be the best webcam in the world, but it&#39;s easily as good as the one I have in my MacBook, and I can move it around wherever I want.&lt;/p&gt;
&lt;h3&gt;Additional Links&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://debugger.medium.com/todays-webcams-are-boring-so-i-brought-back-a-classic-291cc7c94c76&quot;&gt;Today’s Webcams Are Boring, so I Brought Back a Classic | by Max Braun | Debugger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8l0kpQ_2rj4&quot;&gt;Apple FireWire iSight Teardown - YouTube&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://muffinresearch.co.uk/building-a-pisight/&quot;&gt;Building a PiSight&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/maxbbraun/pisight/tree/26c4cef49d1f5b3d396f66f86c58a1d579e686a7/monitor_stand&quot;&gt;PiSight Monitor Stand&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.thingiverse.com/thing:11761&quot;&gt;iSight Clamp for ToM by quadrivia - Thingiverse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://handmirror.app/&quot;&gt;Hand Mirror, for Mac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/peterbay/camera-control&quot;&gt;peterbay/camera-control: Simple command-line application for controlling camera settings through V4L2.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>My notes on building a PiSight</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Monzo Pot Image Generator Version Two</title>
    <link href="https://rknight.me/blog/monzo-pot-image-generator-version-2/"/>
    <updated>2021-08-29T00:00:00Z</updated>
    <id>https://rknight.me/monzo-pot-image-generator-version-2/</id>
    <content type="html">&lt;p&gt;It&#39;s been a while since I &lt;a href=&quot;https://rknight.me/monzo-pot-image-generator/&quot;&gt;released the first version&lt;/a&gt; of the &lt;a href=&quot;https://potimages.rknight.me/&quot;&gt;Monzo pot image generator&lt;/a&gt; and there&#39;s been a &lt;a href=&quot;https://community.monzo.com/t/monzo-pot-image-generator/102120&quot;&gt;lot of requests&lt;/a&gt; on the Monzo forum for various new features.&lt;/p&gt;
&lt;p&gt;So I spent some time adding and updating the site:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New about modal with credits for the new icons:
&lt;ul&gt;
&lt;li&gt;Nearly 2000 brand logos from &lt;a href=&quot;https://simpleicons.org/&quot;&gt;Simple Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Country flags from &lt;a href=&quot;https://github.com/lipis/flag-icon-css&quot;&gt;lipis/flag-icon-css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Country icons from &lt;a href=&quot;https://github.com/djaiss/mapsicon&quot;&gt;djaiss/mapsicon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Full set of emoji from &lt;a href=&quot;https://openmoji.org/library/&quot;&gt;Openmoji&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Premium backgrounds from &lt;a href=&quot;https://community.monzo.com/t/monzo-pot-image-generator/102120/178&quot;&gt;Ben in the forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Upload your own background image&lt;/li&gt;
&lt;li&gt;New coloured Monzo logo from the Monzo press kit&lt;/li&gt;
&lt;li&gt;Offline support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Try the &lt;a href=&quot;https://potimages.rknight.me/&quot;&gt;Monzo Pot Image Generator&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>Updated version with more icons and options</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The Intersect: My Personal Wiki</title>
    <link href="https://rknight.me/blog/intersect/"/>
    <updated>2021-08-23T00:00:00Z</updated>
    <id>https://rknight.me/intersect/</id>
    <content type="html">&lt;p&gt;I came across &lt;a href=&quot;https://wiki.nikitavoloboev.xyz/&quot;&gt;Nikita Volodoev&#39;s wiki&lt;/a&gt; recently when looking for other things and realised this was exactly the type of things I&#39;d been looking for to store snippets, links, and other notes about various things that don&#39;t justify a full blog post. And because I&#39;m an idiot I ended up &lt;a href=&quot;https://hellsite.rknight.me/1426307649365286921&quot;&gt;building my own solution&lt;/a&gt; with &lt;a href=&quot;https://11ty.dev&quot;&gt;Eleventy&lt;/a&gt;. The result is &lt;a href=&quot;https://intersect.rknight.me&quot;&gt;Intersect&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Aside from just rendering a bunch of markdown files it has a number of additional features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Table of contents and breadcrumbs&lt;/li&gt;
&lt;li&gt;Syntax highlight for code blocks with copy code button&lt;/li&gt;
&lt;li&gt;Full search of content and links&lt;/li&gt;
&lt;li&gt;Highlight search queries on navigation to a result&lt;/li&gt;
&lt;li&gt;Popular pages using the &lt;a href=&quot;https://usefathom.com/ref/IXCLSF&quot;&gt;Fathom API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Recently updated pages by parsing the git log&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a bunch of pages where you can read about what Intersect is and how it works on Intersect itself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://intersect.rknight.me&quot;&gt;The introduction page&lt;/a&gt; has some more details about the why&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://intersect.rknight.me/meta&quot;&gt;The meta page&lt;/a&gt; sets out what the purpose of the site is&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://intersect.rknight.me/meta/readme&quot;&gt;The readme page&lt;/a&gt; has installation instructions, and more technical information about how it was built&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/rknightuk/intersect&quot;&gt;source code is on GitHub&lt;/a&gt; but to paraphrase &lt;a href=&quot;https://github.com/andy-piccalilli/11ty-base&quot;&gt;Andy Bell&lt;/a&gt; it&#39;s not open source so much as it is free. I doubt this will meet the requirements of anyone else, it&#39;s a good base to start with, but any features I add will be because I want them.&lt;/p&gt;
&lt;p&gt;There is a companion &lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/tree/main/workflows/intersect&quot;&gt;Alfred workflow&lt;/a&gt; that also searches the content and links and can also open the page in VSCode for editing.&lt;/p&gt;
&lt;p&gt;I even went full &lt;a href=&quot;http://devsdodesign.com&quot;&gt;#devsdodesign&lt;/a&gt; and made a logo:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.us-east-1.amazonaws.com/site/intersect-logo.png&quot; alt=&quot;Intersect Logo&quot; /&gt;&lt;/p&gt;
</content>
    <summary>Intersect is a personal wiki built with Eleventy</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Calendar Events Alfred Workflow</title>
    <link href="https://rknight.me/blog/calendar-events-alfred-workflow/"/>
    <updated>2021-07-22T00:00:00Z</updated>
    <id>https://rknight.me/calendar-events-alfred-workflow/</id>
    <content type="html">&lt;p&gt;NB: This workflow has been deprecated and replaced with the &lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/raw/main/workflows/agenda&quot;&gt;Agenda Workflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;tl;dr: Calendar events workflow for Alfred. &lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/tree/main/workflows/calendar-events&quot;&gt;Download it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I released a &lt;a href=&quot;https://rknight.me/reminders-alfred-workflow/&quot;&gt;Reminders workflow&lt;/a&gt; a few days ago and while working on that I realised a lot of the code would be reusable for a version to manage calendar events. So I went at it tonight while it was too hot to sleep (it&#39;s 3am).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.us-east-1.amazonaws.com/site/calendar-events.png&quot; alt=&quot;Calendar Events workflow for Alfred&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Like the reminders one, it uses an only-for-this-use-case CLI tool which you &lt;a href=&quot;https://github.com/rknightuk/alfred-calendars-helper&quot;&gt;can view on Github here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One difference with this one is opening and creating events. I wanted the workflow to stand on it&#39;s own but I use Fantastical as my calender so it has two modes: one for default Calendar.app and one for Fantastical. By changing the &lt;code&gt;usefantastical&lt;/code&gt; workflow variable events will be opened and created in Fantastical. This is the recommended way of using it.&lt;/p&gt;
&lt;p&gt;With this workflow you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View upcoming events for the next 5 days (all or a specific calendar)&lt;/li&gt;
&lt;li&gt;Open events in Calendar.app or Fantastical&lt;/li&gt;
&lt;li&gt;Set a default calendar for creating events&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/tree/main/workflows/calendar-event&quot;&gt;Download Calendar Events for Alfred&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>An Alfred workflow to manage calendars on your Mac</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Reminders Alfred Workflow</title>
    <link href="https://rknight.me/blog/reminders-alfred-workflow/"/>
    <updated>2021-07-19T00:00:00Z</updated>
    <id>https://rknight.me/reminders-alfred-workflow/</id>
    <content type="html">&lt;p&gt;NB: This workflow has been deprecated and replaced with the &lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/raw/main/workflows/agenda&quot;&gt;Agenda Workflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;tl;dr: Reminders workflow for Alfred. &lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/tree/main/workflows/reminders&quot;&gt;Download it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are a number of workflows available for &lt;a href=&quot;https://www.alfredapp.com&quot;&gt;Alfred&lt;/a&gt; to manage Reminders on the Mac and I&#39;ve tried most of them; none of them do everything I want. Most of them have one of these problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They don&#39;t order reminders based on due date&lt;/li&gt;
&lt;li&gt;You can create reminders but can&#39;t view them&lt;/li&gt;
&lt;li&gt;They rely on a default list for creating with no option to choose&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I decided to have a go at building my own this weekend (and this evening). I tried a number of approaches including Javascript for automation (JXA) which was too slow and AppleScript which opens the app to access your reminders so is also slow. I then found &lt;a href=&quot;https://github.com/keith/reminders-cli&quot;&gt;reminders-cli&lt;/a&gt; which is a command line tool written in Swift.&lt;/p&gt;
&lt;p&gt;This tool was as close as I was able to get in terms of accessing reminders but it didn&#39;t order them by due date, and didn&#39;t allow me to view reminders from all lists, only specific ones. I cloned the repo and starting changing some stuff to do what I wanted; I&#39;ve never written Swift before, so the code is &lt;em&gt;bad&lt;/em&gt;. &lt;em&gt;Really bad&lt;/em&gt;. I also modified the date parsing script from &lt;a href=&quot;https://github.com/surrealroad/alfred-reminders&quot;&gt;alfred-reminders&lt;/a&gt;, which uses (an admittedly older version of) &lt;a href=&quot;https://github.com/wanasit/chrono&quot;&gt;Chrono&lt;/a&gt; but works for this purpose.&lt;/p&gt;
&lt;p&gt;After a bit more wrangling of various things like bash, AppleScript, and Alfred&#39;s various features like script filters and workflow variables I was able to get something I&#39;m happy with.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.us-east-1.amazonaws.com/site/reminders-for-alfred.png&quot; alt=&quot;Reminders workflow for Alfred&quot; /&gt;&lt;/p&gt;
&lt;p&gt;With this workflow you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View all upcoming reminders&lt;/li&gt;
&lt;li&gt;View upcoming reminders from a specific list&lt;/li&gt;
&lt;li&gt;Mark reminders complete&lt;/li&gt;
&lt;li&gt;Set a default list for creating reminders (or create for a specific list)&lt;/li&gt;
&lt;li&gt;Create new reminders with natural language (e.g. &amp;quot;Lunch with John tomorrow 1pm&amp;quot;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/rknightuk/alfred-workflows/tree/main/workflows/reminders&quot;&gt;Download Reminders for Alfred&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>An Alfred workflow to manage Reminders on your Mac</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Monzo Pot Image Generator</title>
    <link href="https://rknight.me/blog/monzo-pot-image-generator/"/>
    <updated>2020-07-21T00:00:00Z</updated>
    <id>https://rknight.me/monzo-pot-image-generator/</id>
    <content type="html">&lt;p&gt;While browsing &lt;a href=&quot;https://community.monzo.com/t/custom-pot-images-to-use/62748/325&quot;&gt;this thread on the Monzo forums&lt;/a&gt; I came up with an idea to generate Monzo pot images whenever I want so I created the &lt;a href=&quot;https://potimages.rknight.me/&quot;&gt;Monzo Pot Image Generator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rknightuk.s3.us-east-1.amazonaws.com/site/preview-image.png&quot; alt=&quot;Monzo Pot Image Generator&quot; /&gt;&lt;/p&gt;
&lt;p&gt;First thing was to work out how to generate and download the images. This turned out to be relatively easy with a combination of &lt;a href=&quot;https://github.com/tsayen/dom-to-image&quot;&gt;dom-to-image&lt;/a&gt; and &lt;a href=&quot;https://github.com/eligrey/FileSaver.js&quot;&gt;FileSaver&lt;/a&gt;. To generate a list of the &lt;a href=&quot;https://fontawesome.com/&quot;&gt;Font Awesome icons&lt;/a&gt; output in the search, I grabbed &lt;a href=&quot;https://github.com/FortAwesome/Font-Awesome/blob/master/metadata/icons.json&quot;&gt;the JSON config&lt;/a&gt;, did a little bit of manipulating in Sublime and used &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&#39;s global data files&lt;/a&gt; to use that data when building the site.&lt;/p&gt;
&lt;p&gt;I wanted to keep everything as simple as possible; no crazy build scripts and as few files as possible. I used &lt;a href=&quot;https://watercss.kognise.dev/&quot;&gt;Water.css&lt;/a&gt; for the base css and the rest of the css is in a &lt;code&gt;style&lt;/code&gt; tag in the &lt;code&gt;head&lt;/code&gt; (is that legal?). I also learnt that there is a &lt;code&gt;type=&amp;quot;color&amp;quot;&lt;/code&gt; input - although I might replace this at some point because it&#39;s not particularly nice on mobile Safari.&lt;/p&gt;
&lt;p&gt;You can also share you pot images with a link &lt;a href=&quot;https://potimages.rknight.me/?i=chess-queen&amp;amp;ip=fas&amp;amp;c=333333&amp;amp;bg=b7edd0&quot;&gt;like this&lt;/a&gt;. I initially used url hashes to keep the url updated all the time, but when sharing these to Twitter they get stripped out so I switched to using query strings instead.&lt;/p&gt;
</content>
    <summary>Generate images for your Monzo pots</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Game FAQs</title>
    <link href="https://rknight.me/blog/fifa-street-ps2-game-faqs/"/>
    <updated>2020-02-14T00:00:00Z</updated>
    <id>https://rknight.me/fifa-street-ps2-game-faqs/</id>
    <content type="html">&lt;p&gt;Before YouTube was the go-to place for game tutorials, &lt;a href=&quot;https://gamefaqs.com&quot;&gt;GameFAQs&lt;/a&gt; was one of the only decent places online to get in-depth guides on how to complete games or get cheat codes. GameFAQs only allowed text posts on the site so people came up with interesting ways to navigate chapters and sections in what feels like a precursor to &lt;a href=&quot;https://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Every guide would have an ASCII art heading and a table of contents with some unique key so you could use &lt;code&gt;CMD/CTRL+F&lt;/code&gt; to find the relevant section. Today I remembered my only contribution to GameFAQs was a &lt;a href=&quot;https://gamefaqs.gamespot.com/gamecube/924938-fifa-street/faqs/36247&quot;&gt;Fifa Street PS2 guide&lt;/a&gt;. I&#39;m pretty sure a lot of it was just copied from magazines and other websites but I wanted to grab a copy of it just in case it ever removed or GameFAQs shuts down. So if that link doesn&#39;t work, I&#39;ve also uploaded &lt;a href=&quot;/assets/files/fifa-street-guide.txt&quot;&gt;the original text file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I haven&#39;t used GameFAQs in a &lt;em&gt;long&lt;/em&gt; time but it&#39;s nice to know all those guides are still available.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rmlewisuk.s3.us-east-1.amazonaws.com/gta3-ascii.png&quot; alt=&quot;GTAIII ASCII Heading&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Image from &lt;a href=&quot;https://gamefaqs.gamespot.com/ps2/466217-grand-theft-auto-iii/faqs/14620&quot;&gt;this GTA III guide&lt;/a&gt; I remember using &lt;em&gt;a lot&lt;/em&gt;.&lt;/p&gt;
</content>
    <summary>Before YouTube was the go-to place for game tutorials, GameFAQs was the best place for video game guides. I wrote one for Fifa Street on the PS2</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Changing Your Name by Deed Poll</title>
    <link href="https://rknight.me/blog/changing-your-name-by-deed-poll/"/>
    <updated>2019-09-08T00:00:00Z</updated>
    <id>https://rknight.me/changing-your-name-by-deed-poll/</id>
    <content type="html">&lt;p&gt;I changed my name (and my email) a couple of weeks ago and I have a few thoughts about the process. Most of this should also apply if you&#39;ve changed your name because of marriage.&lt;/p&gt;
&lt;h3&gt;Make a List&lt;/h3&gt;
&lt;p&gt;Before you do anything else, make a list of everywhere you need to change your name, along with the process to do it (letter, email, in branch). If it&#39;s a letter or email, I used this to send to each of them:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please be advised that on {name change date} my name was legally changed from {old name} to {new name}.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;My new name should be reflected on my {credit card|account|whatever}, account number {12345}, previously held in the name of {old name}.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;I have included a copy of my Deed Poll. If you have further questions, please contact me at {phone number} or {email}.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Sincerely,&lt;br /&gt;
{New Name} (previously {Old Name})&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You&#39;ll also need to sign that letter with your old and new signature. Becuase signatures are proof of...something?&lt;/p&gt;
&lt;p&gt;I won&#39;t list everywhere I had to change my name, but here&#39;s a good list of places to start:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HMRC. You can do this online through the government gateway.&lt;/li&gt;
&lt;li&gt;Passport. Again, it can be done online, but you&#39;ll need to send your deed poll and another &amp;quot;proof&amp;quot;. I used a bank statement in my new name.&lt;/li&gt;
&lt;li&gt;Driving Licence. Requires a new application form, order online or pickup in a Post Office.&lt;/li&gt;
&lt;li&gt;Bank. Depends on the bank, check their website.&lt;/li&gt;
&lt;li&gt;Credit Cards.&lt;/li&gt;
&lt;li&gt;Insurance (house, car, phone, etc)&lt;/li&gt;
&lt;li&gt;Utilities (water, gas, electric)&lt;/li&gt;
&lt;li&gt;Mortgage/Landlord&lt;/li&gt;
&lt;li&gt;Electoral Register. You can do this online by registering to vote and it will ask if you&#39;ve changed your name.&lt;/li&gt;
&lt;li&gt;Council Tax&lt;/li&gt;
&lt;li&gt;Paypal. They require additional proof including photo ID and a bank statement.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Make Multiple Deed Polls&lt;/h3&gt;
&lt;p&gt;I used &lt;a href=&quot;https://freedeedpoll.org.uk/&quot;&gt;Free UK Deed Poll&lt;/a&gt; to make my deed poll, printed on some certificate paper I got on Amazon. This is 100% legal and any company that charges you for a deed poll is just printing a piece of paper for you. I would suggest getting at least four or five deed polls signed (you need two witnesses); I currently have three in the mail and a final one at home which won&#39;t be leaving my sight until at least one has been returned.&lt;/p&gt;
&lt;h3&gt;Do Your Passport or Driving Licence as Soon as Possible&lt;/h3&gt;
&lt;p&gt;Despite a deed poll being a legal document, there are some places that won&#39;t accept that as proof without additional documentation, namely a photo ID of some kind. Getting either your passport or driving licence done quickly will make the process a lot easier. If you don&#39;t have either of those, you&#39;ll have to argue with them like I did with my mortgage company while I was waiting for my new passport.&lt;/p&gt;
&lt;h3&gt;Try Live Chat First&lt;/h3&gt;
&lt;p&gt;A lot of companies have pages explaining how to change your name with them, which is usually something like &amp;quot;Send us a letter in the post with a copy of your deed poll&amp;quot; but if you ask them on live chat, a lot of them will do it without having to send them a physical letter like a caveman.&lt;/p&gt;
&lt;h3&gt;You Won&#39;t Get Confirmation&lt;/h3&gt;
&lt;p&gt;Of the seven places I&#39;ve sent letters to, only one of them has actually confirmed that the change has happened, I had to call the others to confirm the change.&lt;/p&gt;
&lt;h3&gt;Everyone Sucks Except Monzo&lt;/h3&gt;
&lt;p&gt;I was able to change my name on Monzo within five minutes using the in-app chat. A week later, I&#39;m still waiting for my high street bank to change even though I went in branch to make the change, which they force you to do.&lt;/p&gt;
&lt;h3&gt;If All Else Fails, Say the Magic Word&lt;/h3&gt;
&lt;p&gt;I also changed my email at the same time as my name, so I had to go through all my online accounts to change it.&lt;/p&gt;
&lt;p&gt;If you find a company who refuses to change your name or email, say the magic word: GDPR. There are multiple companies who won&#39;t change your email address at all so it almost always ended in me sending an email something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You have an obligation under GDPR to keep my personal information correct and up to date. If you&#39;re unable or unwilling to change my {name|email}, please delete my account as soon as possible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the most part, these companies would &amp;quot;suddenly&amp;quot; find a way to change it or, in a few cases, they would delete the account.&lt;/p&gt;
</content>
    <summary>I changed my name and there's some things that would have been good to know before I started</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Convert a Spotify Account From Facebook to Email Login</title>
    <link href="https://rknight.me/blog/convert-spotify-facebook-to-email-login/"/>
    <updated>2018-03-21T00:00:00Z</updated>
    <id>https://rknight.me/convert-spotify-facebook-to-email-login/</id>
    <content type="html">&lt;p&gt;This morning &lt;a href=&quot;https://hellsite.rknight.me/976392265374535680&quot;&gt;I tweeted&lt;/a&gt; that there&#39;s no way to convert a Spotify account from Facebook login to email and password login. I even spoke to Spotify support who said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As your account was created via Facebook, it can&#39;t be unlinked. Don&#39;t worry, we can free up your email address so you can create a new account. Once that&#39;s done, we&#39;ll transfer all of your tunes and student details across.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I complained about this in one the Slack groups I&#39;m in, and Nathaniel suggested I try doing a &amp;quot;forgot password&amp;quot; to set a password on the account and it worked. After that I was able to disconnect Spotify from the &lt;a href=&quot;https://facebook.com/settings?tab=applications&quot;&gt;Facebook settings page&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On the &lt;a href=&quot;https://www.spotify.com/&quot;&gt;Spotify website&lt;/a&gt;, log out&lt;/li&gt;
&lt;li&gt;Go to the login page and choose &amp;quot;forgot password&amp;quot; and use the email associated with your Facebook account&lt;/li&gt;
&lt;li&gt;Reset your password from the email link&lt;/li&gt;
&lt;li&gt;Disconnect Spotify in Facebook&lt;/li&gt;
&lt;li&gt;Log in with your new password&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The above steps that I followed have also been confirmed to work by &lt;a href=&quot;https://iwader.co.uk&quot;&gt;Wade&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>Despite what Spotify tell you, you can unlink your account from Facebook</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My Home Screen (November 2017)</title>
    <link href="https://rknight.me/blog/homescreen-november-2017/"/>
    <updated>2018-03-15T15:25:00Z</updated>
    <id>https://rknight.me/homescreen-november-2017/</id>
    <content type="html">&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://rmlewisuk.s3.amazonaws.com/homescreen-november-2017.jpg&quot;&gt;&lt;img style=&quot;float:left;padding:10px;&quot; src=&quot;https://rmlewisuk.s3.amazonaws.com/homescreen-november-2017.jpg&quot; width=&quot;250&quot; height=&quot;auto&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A lot of things have changed for me since I last &lt;a href=&quot;https://robblewis.me/homescreen-september-2015/&quot;&gt;shared my Home screen in 2015&lt;/a&gt;. Last year I switched to Android, using a Pixel XL as my phone because I had become frustrated with some of the interface changes to iOS. Just under a year later I was as irked with Android as I previously was with iOS, but for different reasons (Seriously Android? No way to choose audio output is ridiculous). I also missed my Apple Watch and I wanted to try out AirPods which, surprising no one, I love.&lt;/p&gt;
&lt;p&gt;One of the things I did like about Android is that every app you install doesn&#39;t have to be on the Home screen. I got pretty use to this so I now have my most used apps on first screen, everything else in a folder on the second, and I use spotlight to find those apps. This did have its downsides on Android though; some apps I would simply forget to check, or post to, so I&#39;ve made an effort to put those apps on the Home screen on my iPhone, namely Instagram, Reddit, and Buzzfeed.&lt;/p&gt;
&lt;p&gt;Starting with my dock, Overcast and Tweetbot were the apps I missed the most. The plethora of great podcast, and to some extent Twitter, clients on iOS isn&#39;t mirrored on Android and Pocketcasts is basically the only decent option. As much as I like Pocketcasts, Overcast works better for the way I like to listen and subscribe to podcasts. I do still have Pocketcasts and Castro installed so I can check out any new features and switch easily if I want to.&lt;/p&gt;
&lt;p&gt;Mac counterparts isn&#39;t something offered by a lot of Android apps so coming back to iOS I was happy download Fantastical and PCalc although the latter isn&#39;t as much a calculator for me as it is a game that can also do calculations.&lt;/p&gt;
&lt;p&gt;Before I used Android I was a plug-in-and-sync-from-iTunes person but I signed up for Spotify the day I got my Pixel and I&#39;ve been using it ever since. I have considered Apple Music but it doesn&#39;t integrate with my Amazon Echo so that&#39;s a no-go, at least for now.&lt;/p&gt;
&lt;p&gt;The rest of the apps are fairly self-explanatory; Amazon, eBay, and my bank&#39;s &lt;a href=&quot;https://hellsite.rknight.me/927502202914123776&quot;&gt;terrible app&lt;/a&gt; because &lt;a href=&quot;https://hellsite.rknight.me/701068051840630784&quot;&gt;I buy a lot of Lego&lt;/a&gt;, Google Inbox because email is a necessary evil, and notes because I like the simplicity of it.&lt;/p&gt;
&lt;p&gt;Spending a year on Android gave me an appreciation for the things I really like about iOS as well as the areas I hope they improve on in the future like the Home screen layout and notifications.&lt;/p&gt;
</content>
    <summary>My iPhone home screen as of November 2017</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Notes About Setting up RetroPie</title>
    <link href="https://rknight.me/blog/notes-about-setting-up-retropie/"/>
    <updated>2017-07-04T09:14:00Z</updated>
    <id>https://rknight.me/notes-about-setting-up-retropie/</id>
    <content type="html">&lt;p&gt;Setting up &lt;a href=&quot;https://retropie.org.uk/&quot;&gt;RetroPie&lt;/a&gt; on a Raspberry Pi is fairly easy but I did come up against a couple of issues that I needed to fix. This post is just a collection of quick fixes for those issues.&lt;/p&gt;
&lt;h3&gt;Remove underscored games when transferring from a Mac&lt;/h3&gt;
&lt;p&gt;When copying ROMs from a Mac, you may end up with a bunch of files that start with an underscore. To remove them all, run the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find /home/pi/RetroPie -name &amp;quot;._*&amp;quot; -exec rm -rf {} \;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;[&lt;a href=&quot;https://retropie.org.uk/forum/topic/4348/removing-_-files-from-rom/10&quot;&gt;source&lt;/a&gt;]&lt;/p&gt;
&lt;h3&gt;Finding Installed Themes&lt;/h3&gt;
&lt;p&gt;For the theme I&#39;m using, I wanted to edit the SNES background image to use the non-US SNES (read: the one true SNES). Installed themes are stored in &lt;code&gt;/etc/emulationstation/themes&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Finding decent ROMs&lt;/h3&gt;
&lt;p&gt;The best site I&#39;ve found for searching for specific ROMs is &lt;a href=&quot;http://www.completeroms.com/&quot;&gt;Complete ROMS&lt;/a&gt;. They don&#39;t have &lt;em&gt;everything&lt;/em&gt; but the site is clean and easy to find exactly what you&#39;re looking for.&lt;/p&gt;
</content>
    <summary>Some things I learnt (or want to remember) about setting up a RetroPie</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Getting Closer to the Perfect TV</title>
    <link href="https://rknight.me/blog/getting-closer-to-the-perfect-tv/"/>
    <updated>2017-05-15T00:00:00Z</updated>
    <id>https://rknight.me/getting-closer-to-the-perfect-tv/</id>
    <content type="html">&lt;p&gt;In 2015, Pieter Siekerman &lt;a href=&quot;http://technology.siekerman.nl/post/133644449664/the-perfect-tv&quot;&gt;wrote a blog post&lt;/a&gt; describing what the perfect TV should be:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For two years now I’ve closely watched various TV manufacturers trying to find their way in the changing landscape of TV platforms and I just don’t get it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In September, (and again this week), I ordered the &lt;a href=&quot;https://hisense.co.uk/electronics/tvs/m3000/43&quot;&gt;Hisense H43M3000&lt;/a&gt; despite it being a relatively unknown brand in the UK and I was pleasantly surprised at how good it was given the price of ~£300. This is the closest I&#39;ve come to the perfect TV thus far, but it still has a long way to go based on Peter&#39;s list.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;First of all and most importantly, it should not be a TV platform.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately, it is. It has built-in apps but no app store to download other apps. It&#39;s slow to load anything including switching inputs, which is infuriating. The remote is a hot mess of useless buttons including app-specific buttons like Netflix, YouTube and Wuaki which can&#39;t be changed to open a different app.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A large number of HDMI ports&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The TV has 4 HDMI ports but annoyingly only two of them support UHD/4K/HDR/whatever. I assume this is a cost-saving measure but if they removed the TV tuner or the &amp;quot;common interface&amp;quot; slot, whatever the hell that is, this would cover it. It does have a SCART socket, component, and 3 USB ports but I&#39;d prefer to replace all of those with HDMI if I could. I can &lt;a href=&quot;https://hellsite.rknight.me/863400075338371072&quot;&gt;rename the inputs though&lt;/a&gt; which is the best feature of this TV by a long shot.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The display should be great&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The display is so nice I bought another one to replace my aging HDTV from ~5 year ago. Even with non-4K content, everything looks fantastic.&lt;/p&gt;
&lt;p&gt;There are a number of other points on Peter&#39;s list which I care less about than the ones listed above and there&#39;s still a long way to go before I can buy the perfect TV. However, if you&#39;re looking for a good value 4K TV this is a pretty good option. Just buy yourself a Fire TV box to go with it so you can avoid thier &amp;quot;smart&amp;quot; software.&lt;/p&gt;
</content>
    <summary>I bought what I think is a near-perfect TV</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Enable HDR with PS4 on Hisense H43M3000</title>
    <link href="https://rknight.me/blog/hdr-hisense-tv-ps4/"/>
    <updated>2017-05-05T00:00:00Z</updated>
    <id>https://rknight.me/hdr-hisense-tv-ps4/</id>
    <content type="html">&lt;p&gt;My Hisense TV (&lt;a href=&quot;https://hisense.co.uk/electronics/tvs/m3000/43&quot;&gt;H43M3000&lt;/a&gt;) recently received an update to support HDR, which is something the PS4 supports for some games. After plugging the console in, the PS4 told me my TV doesn&#39;t support HDR but after some playing around with settings and ports I managed to get it to work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The PS4 must be using either HDMI port 3 or 4&lt;/li&gt;
&lt;li&gt;Open the TV settings and go to System then the &amp;quot;HDMI &amp;amp; CEC Function&amp;quot; section&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Adjust&amp;quot; on the HDMI 2.0 Format setting and choose &amp;quot;Enhanced Format&amp;quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once I restarted the PS4 and TV, HDR was supported (and looked beautiful in &lt;a href=&quot;http://media.rbbl.ws/game/2017/05/01/horizon-zero-dawn/&quot;&gt;Horizon Zero Dawn&lt;/a&gt;) 🎉.&lt;/p&gt;
&lt;p&gt;&lt;s&gt;&lt;em&gt;nb: I have an &lt;a href=&quot;https://hellsite.rknight.me/736500604705591297&quot;&gt;original PS4&lt;/a&gt; so I can&#39;t confirm if this TV works with 4K on the PS4 Pro.&lt;/em&gt;&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;24/01/2018 Update: I now have a PS4 Pro and can confirm it works with 4K as well.&lt;/strong&gt;&lt;/p&gt;
</content>
    <summary>Enabling PS4 HDR on Hisense H43M3000</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Jekyll Post Archive Grouped by Year</title>
    <link href="https://rknight.me/blog/jekyll-category-year-archive/"/>
    <updated>2017-01-12T00:00:00Z</updated>
    <id>https://rknight.me/jekyll-category-year-archive/</id>
    <content type="html">&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Check if the date has been output --&gt;&lt;/span&gt;&lt;br /&gt;    {% assign datePrinted = false %}&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Assign year to something we&#39;re not using --&gt;&lt;/span&gt;&lt;br /&gt;    {% assign currentYear = 1000 %}&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Get number of posts --&gt;&lt;/span&gt;&lt;br /&gt;    {% assign postCount = archivePosts | size %}&lt;br /&gt;    &lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- If no posts, say that --&gt;&lt;/span&gt;&lt;br /&gt;    {% if postCount == 0 %}&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;No posts yet&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    {% endif %}&lt;br /&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!--  Loop thrugh posts --&gt;&lt;/span&gt;&lt;br /&gt;    {% for post in archivePosts %}&lt;br /&gt;&lt;br /&gt;        {% assign postYear = post.date | date: &quot;%Y&quot; %}&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Output posts if this is a new year --&gt;&lt;/span&gt;&lt;br /&gt;        {% unless postYear == currentYear %}&lt;br /&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;{{ postYear }}&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        {% endunless %}&lt;br /&gt;&lt;br /&gt;        {% assign currentYear = postYear %}&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- Output post --&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;            {{ post.date | date: &quot;%d/%m&quot; }} - &lt;br /&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;a&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{{ post.url }}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;                {{ post.title }}&lt;br /&gt;            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;br /&gt;    {% endfor %}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
    <summary>Code Snippet for creating a post archive grouped by year in Jekyll</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Thoughts on OnePlus 3 and Switching to Android</title>
    <link href="https://rknight.me/blog/oneplus-3-and-switching-to-android/"/>
    <updated>2016-10-11T00:00:00Z</updated>
    <id>https://rknight.me/oneplus-3-and-switching-to-android/</id>
    <content type="html">&lt;p&gt;&lt;em&gt;If you want to hear more about this, or just prefer listening over reading (hi Myke), I spoke about this with John on episode 30 of our podcast, &lt;a href=&quot;http://ruminatepodcast.com/31&quot;&gt;Ruminate&lt;/a&gt;. Find it in &lt;a href=&quot;https://overcast.fm/itunes1033235350/ruminate-podcast&quot;&gt;Overcast&lt;/a&gt;, &lt;a href=&quot;http://pca.st/ruminate&quot;&gt;Pocketcasts&lt;/a&gt;, or &lt;a href=&quot;https://itunes.apple.com/gb/podcast/ruminate-podcast/id1033235350&quot;&gt;iTunes&lt;/a&gt;, or any other podcast app you use.&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I wrote about &lt;a href=&quot;http://robblewis.me/replacing-apps-on-android&quot;&gt;replacing all my apps on Android&lt;/a&gt; just under a week ago, but I wanted to lay out some of my thoughts about the &lt;a href=&quot;https://oneplus.net/uk/3&quot;&gt;OnePlus 3&lt;/a&gt; and Android in general.&lt;/p&gt;
&lt;p&gt;Firstly, I&#39;ve had a few people ask &lt;em&gt;why&lt;/em&gt; I switched to Android. There wasn&#39;t a single reason but a plethora of little things that started to bug me about iOS. First off, as I &lt;a href=&quot;http://www.ruminatepodcast.com/30&quot;&gt;discussed here&lt;/a&gt;, I&#39;m no longer using iTunes because of how buggy it is when downloading music, as well as it constantly messing up my album artwork. Without iTunes, the only thing locking me into iOS was iMessage and I realised I could live without it. After the &amp;quot;upgrade&amp;quot; to iOS10 a lot of things bugged me about it. In no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pressing notifications would sometimes not open the related app, they would just disappear&lt;/li&gt;
&lt;li&gt;The feature where it would show Overcast on the lock screen when I plugged my headphones in no longer worked&lt;/li&gt;
&lt;li&gt;Because iOS10 splits control center into two panels, whenever I opened it to use something it was inevitably on the wrong panel&lt;/li&gt;
&lt;li&gt;No way to clear all notifications from the lock screen without 3D touch (without swiping down notification center which you can only do from the widget lock screen)&lt;/li&gt;
&lt;li&gt;Widgets can&#39;t be placed wherever I want&lt;/li&gt;
&lt;li&gt;Actions on notifications (reply, archive, etc) take twice as many presses to get to as before without 3D touch&lt;/li&gt;
&lt;li&gt;Even with &lt;a href=&quot;http://www.howtogeek.com/262837/how-to-unlock-your-ios-10-device-with-a-single-click-like-in-ios-9/&quot;&gt;rest to unlock&lt;/a&gt; enabled, my iPhone still wouldn&#39;t always unlock properly, or at all&lt;/li&gt;
&lt;li&gt;Fucking iMessage stickers and apps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the above made me hate using my phone and on top of all that the way I use my phone has changed significantly in the past year so I decided the best thing for me to do was to switch to Android.&lt;/p&gt;
&lt;h3&gt;OnePlus 3&lt;/h3&gt;
&lt;p&gt;I won&#39;t be going in depth into the phone but &lt;a href=&quot;https://www.youtube.com/watch?v=ycIpOZY03OM&quot;&gt;MKBHD reviewed it here&lt;/a&gt;. The OnePlus is similar in size to the iPhone 7 plus and after a few days of using it my iPhone 6 felt ridiculously small; turns out Myke was right.&lt;/p&gt;
&lt;p&gt;The OnePlus build quality is not quite as nice as an iPhone, which I expected, but it is still a really nice device. The thing I love the most about it is the fingerprint unlock. Not only has it never failed to read my fingerprint but it&#39;s also &lt;em&gt;really&lt;/em&gt; fast, as you can see in &lt;a href=&quot;https://www.youtube.com/watch?v=fOIfTNfdZUk&quot;&gt;this video&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dash is OnePlus&#39;s quick charging feature that uses their &lt;a href=&quot;https://oneplus.net/uk/3/dashcharge&quot;&gt;dash charger and cable&lt;/a&gt;. I&#39;m able to charge my phone from ~15% to 70% in about 30 minutes, and another 15 to reach the full 100%. Because of this I&#39;ve started charging my phone in the evening before I go to bed and the battery lasts the entirety of the next day well into the late evening before I need to charge again. It&#39;s worth noting that dash charging only works with both the USB plug &lt;em&gt;and&lt;/em&gt; the dash cable, so it won&#39;t work with third-party USB cables.&lt;/p&gt;
&lt;p&gt;OnePlus 3, like the previous models, has an alert slider on the side to switch between silent, priority notifications, and all notifications. This is really useful and not something that appears on a lot of Android phones (although the modes exist as a software feature). By default priority includes alarms, music, messages, and phone calls but any app can be treated as priority in the global notification settings. Coming from an iPhone, it&#39;s nice to have a physical switch and as someone who had a lot of &lt;a href=&quot;https://en.wikipedia.org/wiki/Nokia_3310&quot;&gt;old Nokia phones&lt;/a&gt; I love having a modern equivalent of profiles. I use silent for when I&#39;m sleeping, priority for when I&#39;m at work, and all for any other time.&lt;/p&gt;
&lt;p&gt;The OnePlus runs &lt;a href=&quot;https://en.wikipedia.org/wiki/OxygenOS&quot;&gt;OxygenOS&lt;/a&gt; which is a slightly modified version of stock Android, currently on 6.0 Marshmallow. Although it&#39;s frustrating to not have the latest version of Android, I&#39;m pretty happy with it and OnePlus have confirmed they are working on an Android N update which should be out in the next few months.&lt;/p&gt;
&lt;p&gt;The camera is no iPhone competitor but the photos it takes &lt;a href=&quot;http://rmlewisuk.s3.amazonaws.com/one-plus-sample-cat.jpg&quot;&gt;are pretty good&lt;/a&gt;. I don&#39;t take a lot of photos with my phone so this isn&#39;t massively important to me, but your mileage may vary.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/one-plus-sample-cat-preview.jpg&quot; alt=&quot;One Plus cat sample image&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Lets be honest, it&#39;s a slab of glass with some buttons next to it. It&#39;s not the world&#39;s greatest device but it&#39;s nowhere near the worst and for £330, you can&#39;t go wrong.&lt;/p&gt;
&lt;h3&gt;Android&lt;/h3&gt;
&lt;p&gt;Android is much as you&#39;d expect; it&#39;s a mobile operating system that has apps, widgets, notifications, just like iOS. There are, however, some significant differences. Some of them I like, some not so much.&lt;/p&gt;
&lt;p&gt;Being able to install an app from the Google Play store from my Mac (and choose which device to install to) is so natural, and works so well, that I&#39;m amazed Apple hasn&#39;t implemented this. Opening iTunes seems archaic in comparison. Once I&#39;d downloaded a few apps, I was impressed with Google&#39;s ability to suggest apps tailored to my interests, something which Apple have been trying to do for years on the App Store with little success (remember &lt;a href=&quot;http://appleinsider.com/articles/12/09/03/apple_turns_on_app_store_genius_recommendations_for_developers&quot;&gt;Genius for Apps&lt;/a&gt;?).&lt;/p&gt;
&lt;p&gt;The home screen(s) is where Android differs significantly; I can put apps wherever I want, and have widgets all over the place. This is the biggest improvement using my phone day-to-day because if I only want four apps on the home screen, they don&#39;t have to be right at the top of the screen. The left-most home screen is Google Now which shows weather, news, and a host of other &amp;quot;cards&amp;quot; based on emails and apps I use (for example, it now shows me my eBay saved searches). It&#39;s supposed to show me delivery information based on my emails, but this &lt;a href=&quot;http://www.droid-life.com/2015/07/06/gmail-google-now-package-tracking-card-is-showing-up-or-some-google-apps-users/&quot;&gt;might be disabled for Google Apps accounts&lt;/a&gt; so I don&#39;t get the benefit of this. I currently have two home screen; one with my most used apps and the &lt;a href=&quot;https://pocketcasts.com&quot;&gt;Pocketcasts&lt;/a&gt; widget, and one with some lesser used apps and the &lt;a href=&quot;https://spotify.com&quot;&gt;Spotify&lt;/a&gt; widget. Apps that aren&#39;t on either home screen can be accessed through search or from the app drawer.&lt;/p&gt;
&lt;p&gt;Setting default apps is great (I swapped out the default SMS app for &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.textra&amp;amp;hl=en_GB&quot;&gt;Textra&lt;/a&gt;) but the best part about setting defaults is opening specific type of links and files in specific apps. For example, all Twitter links open in Fenix and all Reddit links open in Relay. This is &lt;em&gt;so&lt;/em&gt; much better than ending up on the mobile Twitter site when I have a perfectly good Twitter client installed. Talking of opening links, &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.linkbubble.playstore&amp;amp;hl=en_GB&quot;&gt;Link Bubble&lt;/a&gt; is fantastic. When I click a link in Twitter, for example, it shows a floating bubble on my screen which will expand once the page has loaded. Being able to scroll through Twitter, open a bunch of links, and then review them all at once is amazing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/default-links-and-link-bubble.png&quot; alt=&quot;Default links and Link Bubble&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One of the things I thought I&#39;d miss most is sending messages from my Mac through the Messages app. &lt;a href=&quot;https://www.pushbullet.com/&quot;&gt;Push Bullet&lt;/a&gt; fixes this by allowing me to mirror all notifications to my Mac, send messages, send files between devices, and interact with the notifications just like I can on the phone. It also has a &lt;a href=&quot;https://www.pushbullet.com/pro&quot;&gt;bunch of other really useful features&lt;/a&gt;. I was concerned that apps like this might massively affect battery life, but this hasn&#39;t been the case.&lt;/p&gt;
&lt;p&gt;Something I wasn&#39;t able to work out was how to choose where to output audio when I&#39;m connected to a Bluetooth device. On iOS, the &amp;quot;AirPlay&amp;quot; menu serves this function. I looked around for a solution to this but came up short so if anyone knows of an app that might fix this, let me know. Speaking of Bluetooth, unlike iOS, there is no way to see the battery life of Bluetooth devices like headphones. Although not a huge problem, it&#39;s frustrating that Android lacks this feature.&lt;/p&gt;
&lt;p&gt;On iOS both the banking apps I used, HSBC and Lloyds, allowed me to use TouchID to login. On Android, this isn&#39;t the case, despite Android having support for such a system (PayPal use it). This, I assume, is because not all Android phones have fingerprint sensors so there&#39;s a smaller market for it. Again, not something I can&#39;t deal with, but a pain none the less.&lt;/p&gt;
&lt;p&gt;I&#39;d be remiss if I didn&#39;t mention the clusterfuck that is Amazon&#39;s presence on Android. I wanted to download the Amazon Video app but the Play Store said it wasn&#39;t compatible with my device, which seemed odd. When I asked &lt;a href=&quot;https://danharper.me&quot;&gt;Dan&lt;/a&gt;, he informed me I should download it through the normal Amazon app. Except my Amazon app didn&#39;t have the option he showed me because I downloaded the Amazon app from the Play Store and not the &lt;a href=&quot;https://www.amazon.co.uk/Amazon-com-Amazon-Underground/dp/B004GJDQT8&quot;&gt;Amazon Underground&lt;/a&gt; app which is a combination of the standard shopping app, plus an app store. To download the Underground app, I had to turn off the security setting to only allow apps from trusted sources. Then, and only then, was I able to download the Amazon Video app from inside &lt;em&gt;that&lt;/em&gt; app. What.&lt;/p&gt;
&lt;p&gt;I&#39;m pretty happy with using Android. I don&#39;t do Real Work™ on my phone and mostly use it for Twitter, phone calls, and buying stuff on Amazon when I&#39;m not at my Mac. Almost any problem or tweak I want to make I can through apps or widgets; Android definitely feels like it&#39;s geared more towards power users and people who want to tinker with settings or &amp;quot;fix&amp;quot; things but that&#39;s perfect for me.&lt;/p&gt;
&lt;p&gt;Finally, because the Apple Watch doesn&#39;t work with Android, I&#39;m getting rid of it. As I &lt;a href=&quot;https://hellsite.rknight.me/783674253807845376&quot;&gt;said on Twitter&lt;/a&gt; the only thing I miss is not being able to quickly see the time so I&#39;m currently eyeing up &lt;a href=&quot;http://www.nixon.com/uk/en/sentry-leather-sw/A105SW.html?dwvar_A105SW_color=2244&amp;amp;dwvar_A105SW_size=00#gclid=Cj0KEQjw1ee_BRD3hK6x993YzeoBEiQA5RH_BHLZjplqhtoBrlGuj7TgwFVJGVScjX9UVaU9d1tOVwgaAmee8P8HAQ&amp;amp;start=1&quot;&gt;one of these&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>My thoughts after just under two weeks with the OnePlus 3</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Replacing Apps on Android</title>
    <link href="https://rknight.me/blog/replacing-apps-on-android/"/>
    <updated>2016-10-06T00:00:00Z</updated>
    <id>https://rknight.me/replacing-apps-on-android/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/home-screen-tiles.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you follow me on Twitter, you probably already know I&#39;ve ditched my iPhone in favour of a &lt;a href=&quot;https://oneplus.net/uk/3&quot;&gt;OnePlus 3&lt;/a&gt;. The biggest hurdle to switching is the apps I used regularly (and some not-so-regularly). After &lt;a href=&quot;http://rmlewisuk.s3.amazonaws.com/apps.md&quot;&gt;making a list of apps I had installed&lt;/a&gt; on my iPhone, I was able to filter it down to just two lists: ones with no equivalent, and ones I needed to find an Android alternative for. The three with no equivalent were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apple Store&lt;/li&gt;
&lt;li&gt;Blink&lt;/li&gt;
&lt;li&gt;Plot&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of these will make a massive difference to my life, but I will definitely miss &lt;a href=&quot;http://squibner.com/blink/&quot;&gt;Blink&lt;/a&gt; and &lt;a href=&quot;http://plotapp.io/&quot;&gt;Plot&lt;/a&gt;. The following apps are ones I need replacements for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Apple Notes&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://geo.itunes.apple.com/gb/app/clear-tasks-reminders-to-do/id493136154?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=twitter&quot;&gt;Clear&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://junecloud.com/support/deliveries-ios/&quot;&gt;Deliveries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dueapp.com/&quot;&gt;Due&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://flexibits.com/fantastical&quot;&gt;Fantastical&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.itvshowsapp.com/&quot;&gt;iTV Shows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://itunes.apple.com/gb/app/narwhal-for-reddit/id845422455?mt=8&quot;&gt;Narwhal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://overcast.fm&quot;&gt;Overcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tapbots.com/tweetbot/&quot;&gt;Tweetbot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I haven&#39;t been able to find anything that is as easy for creating lists as Clear but &lt;a href=&quot;https://keep.google.com&quot;&gt;Google Keep&lt;/a&gt;&#39;s lists feature does the job reasonably well and also doubles as a good replacement for Apple&#39;s notes app.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/google-inbox-inline-delivery.jpg&quot; alt=&quot;Google Inbox&#39; inline delivery information&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I switched to &lt;a href=&quot;https://inbox.google.com&quot;&gt;Google Inbox&lt;/a&gt; prior to buying the OnePlus and it manages to show delivery tracking inline with the email so I decided I didn&#39;t need Deliveries anymore. &lt;a href=&quot;https://danharper.me&quot;&gt;Dan&lt;/a&gt; also told me Google Now should tell me about my deliveries based on my email, but I haven&#39;t seen that working yet. Google Now also has a reminders feature, which has mostly replaced Due.&lt;/p&gt;
&lt;p&gt;The stock &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.google.android.calendar&amp;amp;hl=en_GB&quot;&gt;Google calendar&lt;/a&gt; app and widget replaced Fantastical for what I needed with no problems.&lt;/p&gt;
&lt;p&gt;Tweetbot is a solid app and I knew finding a decent alternative would be hard given Twitter&#39;s disdain for third party developers. &lt;a href=&quot;https://play.google.com/store/apps/details?id=it.mvilla.android.fenix&quot;&gt;Fenix for Twitter&lt;/a&gt; has most of the features I want from a Twitter app, and the design is fantastic.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=fema.serietv2&quot;&gt;TV Series&lt;/a&gt;, as of right now, seems like a pretty good app although I&#39;ll need a few more weeks to know if it works as well as iTV Shows which I was using on iOS. Overcast and Narwhal are both fantastic apps, but also reasonably easy to find quality Android equivalents. I replaced them with &lt;a href=&quot;https://play.pocketcasts.com/web/podcasts/index&quot;&gt;Pocketcasts&lt;/a&gt; and &lt;a href=&quot;https://play.google.com/store/apps/details?id=free.reddit.news&amp;amp;hl=en_GB&quot;&gt;Relay&lt;/a&gt; respectively.&lt;/p&gt;
&lt;p&gt;Overall, I&#39;m really pleased so many of the apps I used have Android and iOS versions, because it made switching &lt;em&gt;much&lt;/em&gt; easier. And, despite what some in the Apple community have you believe, the Android-only apps that I&#39;ve tried are really great quality and on par with their iOS equivalents. And someone should show Apple how great installing apps from the Google Play site is, because it&#39;s a damn sight easier than opening iTunes.&lt;/p&gt;
</content>
    <summary>The first step to switching to Android: replacing all my apps</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Amazon Echo Initial Thoughts</title>
    <link href="https://rknight.me/blog/amazon-echo-initial-thoughts/"/>
    <updated>2016-09-29T00:00:00Z</updated>
    <id>https://rknight.me/amazon-echo-initial-thoughts/</id>
    <content type="html">&lt;p&gt;I have no self control so I bought an &lt;a href=&quot;https://www.amazon.co.uk/Amazon-SK705DI-Echo-Black/dp/B01GAGVIE4/ref=sr_1_1?sr=8-1&amp;amp;ie=UTF8&amp;amp;keywords=echo&amp;amp;qid=1475139825&quot;&gt;Echo&lt;/a&gt; while Amazon were offering £50 off for Prime members last week. Here&#39;s a brain dump of my initial thoughts on the device.&lt;/p&gt;
&lt;h3&gt;Setup&lt;/h3&gt;
&lt;p&gt;Setup is pretty easy using the &lt;a href=&quot;https://geo.itunes.apple.com/us/app/amazon-alexa/id944011620?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=twitter&quot;&gt;Alexa app&lt;/a&gt;. The Echo creates it&#39;s own wifi network which you need to connect to so you can choose your home wifi network. Once that&#39;s done, you can connect services and products like Spotify and Hue lights from within the app, as well as add additional &amp;quot;skills&amp;quot; (Skills are what Amazon call apps for the Echo).&lt;/p&gt;
&lt;h3&gt;Spotify&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: As &lt;a href=&quot;https://www.reddit.com/r/amazonecho/comments/551frl/my_initial_thoughts_on_the_amazon_echo_uk/d88129p?context=3&quot;&gt;/u/jennorocks pointed out&lt;/a&gt;, if you say the word &amp;quot;playlist&amp;quot; when asking for a playlist, it works pretty well.&lt;/p&gt;
&lt;p&gt;I linked my Spotify account in the Alexa app and once setup, I was able to do a two things with it: either tell Alexa to play music on Spotify (playlist, artist, album, genre) or start playing through &lt;a href=&quot;https://www.spotify.com/us/connect/&quot;&gt;Spotify Connect&lt;/a&gt; which sees the Echo as a device from within the Spotify app. Getting Alexa to play one of my saved playlists was difficult as it seems to just search Spotify and play the first search result. For example, I have a playlist called &amp;quot;90s Hits&amp;quot; but it kept playing a similarly named playlist. I don&#39;t know if there&#39;s some trick to force it play my playlists, but I haven&#39;t found it yet.&lt;/p&gt;
&lt;h3&gt;Bluetooth&lt;/h3&gt;
&lt;p&gt;The Echo also functions as a bluetooth speaker. Saying &amp;quot;Alexa, pair my device&amp;quot; will turn on the Echo&#39;s discovery mode which I could then select from my phone&#39;s bluetooth settings. The Echo can then control my phone playback by asking Alexa to play or pause. If my phone is disconnected from the Echo (e.g. if I leave the house), when I come back I can say &amp;quot;Alexa, connect to my phone&amp;quot; and the Echo will reconnect.&lt;/p&gt;
&lt;h3&gt;Everything else&lt;/h3&gt;
&lt;p&gt;Alexa understood every command I gave her &lt;a href=&quot;https://hellsite.rknight.me/781140637089423360&quot;&gt;including when we played around with it in the office&lt;/a&gt; and you can see a list of commands you&#39;ve asked in the Alexa app, which has Google Now-style cards with extra information for some things like traffic, timers, or shopping lists.&lt;/p&gt;
&lt;p&gt;I was looking forward to using &lt;a href=&quot;https://ifttt.com&quot;&gt;IFTTT&lt;/a&gt; to automate some tasks such as moving my Alexa shopping list items to &lt;a href=&quot;https://todoist.com&quot;&gt;Todoist&lt;/a&gt; but IFTTT doesn&#39;t currently support Echo in the UK which is disappointing, but IFTTT say they&#39;re working on it. Hopefully this will be fixed soon.&lt;/p&gt;
&lt;p&gt;The Alexa app is pretty slow and janky (it&#39;s a web app in a wrapper) but it&#39;s only used for setup of the device, and adding new skills. You can access the &amp;quot;app&amp;quot; from &lt;a href=&quot;http://alexa.amazon.com&quot;&gt;alexa.amazon.com&lt;/a&gt; as well if you prefer to setup from a browser.&lt;/p&gt;
&lt;p&gt;I don&#39;t currently have any smart home devices so I wasn&#39;t able to try these features out, but given how well everything else works I&#39;m sure this will work equally well. The Echo does feel like somewhat of a novelty right now, but it works as a Spotify device, bluetooth speaker, and for timers while I&#39;m cooking so I&#39;m pretty happy with it.&lt;/p&gt;
</content>
    <summary>My initial thoughts on the Amazon Echo</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Saving Money on Lego in the UK</title>
    <link href="https://rknight.me/blog/saving-money-on-lego-in-the-uk/"/>
    <updated>2016-03-31T00:00:00Z</updated>
    <id>https://rknight.me/saving-money-on-lego-in-the-uk/</id>
    <content type="html">&lt;p&gt;Although there always seems to be some great Lego bargains to be had in the US from the likes of Walmart and Target, the UK doesn&#39;t really have equivalent stores that do reductions like those stores do. But there are a number of ways to save significant money on Lego in the UK.&lt;/p&gt;
&lt;h3&gt;Lego VIP Points&lt;/h3&gt;
&lt;p&gt;Lego&#39;s &lt;a href=&quot;http://shop.lego.com/en-GB/VIP&quot;&gt;VIP points&lt;/a&gt; is a points system where for every £1 you spend (either online or in an official Lego store) you get 1 point. When you have 100 points, you get £5 off a purchase. Usually twice a year (around March and September), Lego run a double points promotion, so for every pound, you get 2 points; these promotions are a good time (if you have the willpower to wait) to order larger, Lego-exclusive sets or place a large order. So depending on how and when you order, you can get 5%-10% back in money off of other purchases. Being a VIP member also allows you early-access to exclusive sets, normally a few weeks early.&lt;/p&gt;
&lt;p&gt;Although VIP is an always-on promotion, I personally buy from Lego for two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A double VIP points promotion is running&lt;/li&gt;
&lt;li&gt;When a free gift with a purchase is being offered — if the free gift (normally a polybag) is difficult, or not available, elsewhere they tend to sell for between £10-£15 on eBay. Personally, I would rather buy extra Lego with that money and get the polybag free, rather than spending the money on the polybag on it&#39;s own.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delivery times when buying online can be anywhere from a few days to nearly two weeks.&lt;/li&gt;
&lt;li&gt;Discounts and sales are few and far between so saving money on a specific set can be difficult&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://shop.lego.com/en-GB/VIP/registration/index.jsp?joinow=true&quot;&gt;Sign up to become a VIP member here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Amazon, CamelCamelCamel and Brickset&lt;/h3&gt;
&lt;p&gt;A significant portion of the Lego I buy comes from Amazon for one reason: discounts. Lego sets sold by Amazon &lt;em&gt;always&lt;/em&gt; become discounted by at least 10%; with non-licensed themes like City or Friends, the discounts can go as high as 30%.&lt;/p&gt;
&lt;p&gt;To guarantee I save money on Lego bought from Amazon, I do two things: add all the sets I want to a wish list (so I can manually check the prices every week) and install the &lt;a href=&quot;https://chrome.google.com/webstore/detail/the-camelizer/ghnomdcacenbmilgjigehppbamfndblo?hl=en&quot;&gt;CamelCamelCamel Chrome extension&lt;/a&gt;. &lt;a href=&quot;http://uk.camelcamelcamel.com/&quot;&gt;CamelCamelCamel&lt;/a&gt; (herein referred to as CCC) is a site that tracks prices on Amazon and can alert you when a product reaches a certain price.&lt;/p&gt;
&lt;p&gt;To setup a price watch on Amazon, go to the product page and click the CCC button in the Chrome toolbar. This will show a price history graph for the product, and below that you can set a price that you want to be alerted at. CCC will send you an email when the product is available at that price.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://studshq.s3.amazonaws.com/camelcamelcamel.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you use Brickset&#39;s wanted sets functionality (&lt;a href=&quot;/posts/manage-your-lego-collection-with-brickset&quot;&gt;read our guide to Brickset here&lt;/a&gt;), visit their &lt;a href=&quot;http://brickset.com/buy/amazon&quot;&gt;Amazon shopper page&lt;/a&gt;, check the &amp;quot;Sets on my wanted list only&amp;quot; checkbox and Brickset will show you the current Amazon price for sets from your wanted list.&lt;/p&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Amazon doesn&#39;t generally sell the Lego-exclusive sets (although sometimes third-parties sell them but they&#39;re usually above retail price)&lt;/li&gt;
&lt;li&gt;If you don&#39;t subscribe to Amazon Prime, you have to pay postage for orders under £20.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Hot UK Deals and Retailer Promotions&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.hotukdeals.com/&quot;&gt;Hot UK Deals&lt;/a&gt; app allows you to setup notifications based on keywords. By setting &amp;quot;Lego&amp;quot; as one of your keywords, any time a deal is posted containing the word Lego, you&#39;ll get a notifications.&lt;/p&gt;
&lt;p&gt;A lot of the UK supermarkets sell Lego, so when they get reduced, someone always posts it pretty quickly to Hot UK Deals. Something to look out for here is that some of the deals will be store specific so may not be applicable to you. However, when a retailer is doing 3 for 2 on Lego (like Tesco did recently), this can be a great time to save a significant amount of money on sets you want.&lt;/p&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Notifications can be hit or miss; there are a lot of deals on the Lego video games so those will show up as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;http://studshq.s3.amazonaws.com/hot-uk-deals.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Flubit&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://flubit.com&quot;&gt;Flubit&lt;/a&gt; is a site that tries to get you a better price than Amazon are currently offering. You give them a link to a product on Amazon, and they come back with a better offer. Read their &lt;a href=&quot;https://flubit.com/about#!/how-it-works&quot;&gt;How it Works&lt;/a&gt; page to find out more. I&#39;ve only used Flubit once, but I saved 20% on a set that was full-price on Amazon.&lt;/p&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your order could come from any retailer so delivery might not be very quick.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;eBay: Sets with no minifigures&lt;/h3&gt;
&lt;p&gt;If a set you want it out of your price range, you&#39;re not interested in the minifigures, or you particularly like a specific vehicle from a set, eBay can be a great place to pick these up. Lots of people buy sets, take out the minifgures, and then sell the sets on their without them. For example, I picked up &lt;a href=&quot;https://www.reddit.com/r/lego/comments/38wvv6/i_wasnt_planning_on_getting_any_jurassic_world/&quot;&gt;all these Jurassic World sets&lt;/a&gt; with no figures/dinosaurs for £35. Even used for spares, this was a great price. Set up eBay saved searches for what you&#39;re looking for, be patient, and you can get some great deals.&lt;/p&gt;
&lt;h3&gt;Individual Minifigures&lt;/h3&gt;
&lt;p&gt;There are three places I buy individual minifigures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.theminifigurestore.co.uk?affiliates=18&quot;&gt;The Minifigure Store&lt;/a&gt;: Prices are competitive with Bricklink and they run money off promotions through their Twitter account on a regular basis.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bricklink.com&quot;&gt;Bricklink&lt;/a&gt;: Bricklink is best place to pick up spare pieces as well as individual minifigures. If you&#39;re buying just one minifigure, the price with postage can be the same as the Minifigure store/eBay, but buying a few at a time can have some good savings. Read our &lt;a href=&quot;http://guidetobricklink.com&quot;&gt;Guide to Bricklink&lt;/a&gt; to find out about buying from Bricklink.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ebay.co.uk&quot;&gt;eBay&lt;/a&gt;: Prices are slightly higher than Bricklink, but most of the times postage is free and just-released minifigures are generally available within a few days.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Disadvantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For smaller sets, it can be more economical to just buy the complete set, even if you only want the minifigures&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Collectible Series Minifigures&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://brickset.com/sets/theme-Collectable-Minifigures&quot;&gt;Lego&#39;s collectible minifigures&lt;/a&gt; are hugely popular but have one large disadvantage: they come in blind bags so unless you can get really good at feeling for a specific one (I&#39;m terrible at it), you can end up with a lot of duplicates.&lt;/p&gt;
&lt;p&gt;If you want individual minifigures from a series, see the advice above. But if, like me, you like to collect the whole series, I&#39;ve found that by watching auctions on eBay, I can pick up a whole series for around £45 (I never pay more than £48), which works out at just under £3 a minifigure. The collectible minifigures are usually priced at £2.50 so this might not seem like a money-saving tip, but if you end up with more than two duplicates when trying to buy the blind bags, then this will save you money.&lt;/p&gt;
&lt;h3&gt;Miscellaneous&lt;/h3&gt;
&lt;p&gt;If there is a specific set you&#39;re looking for that is recently retired, or isn&#39;t discounted in the places listed above, these are the retailers I tend to look at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.debenhams.com/&quot;&gt;Debenhams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.smythstoys.com/&quot;&gt;Smyths&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.toysrus.com/&quot;&gt;Toys R Us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.johnlewis.com/&quot;&gt;John Lewis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ocado.com/&quot;&gt;Ocado&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;ve had some luck checking Tesco&#39;s reduced section (assuming your local Tesco sells Lego) where some store-specific reductions can happen on smaller Lego sets and Sainsbury&#39;s tend to reduce all their Lego once every 3 months or so as well.&lt;/p&gt;
</content>
    <summary>The UK lacks some of the stores the US have that are known for having good Lego discounts. This article outlines the methods I use to save as much money as possible when buying Lego.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Convert LXF to Bricklink XML</title>
    <link href="https://rknight.me/blog/convert-lxf-to-bricklink-xml/"/>
    <updated>2016-03-22T00:00:00Z</updated>
    <id>https://rknight.me/convert-lxf-to-bricklink-xml/</id>
    <content type="html">&lt;p&gt;When you&#39;ve created a model in Lego Digital Designer, you likely want get those parts into a Bricklink wanted list so you can order them. Unfortunately, LDD doesn&#39;t have an option to export to the required &lt;a href=&quot;http://www.bricklink.com/help.asp?helpID=207&quot;&gt;Bricklink XML format&lt;/a&gt;. Thankfully, &lt;a href=&quot;http://rebrickable.com&quot;&gt;Rebrickable&lt;/a&gt; has the ability to convert an LDD model to Bricklink XML. You&#39;ll need a Rebrickable account to do this, so if you haven&#39;t got one yet, &lt;a href=&quot;http://rebrickable.com/signup&quot;&gt;register for one&lt;/a&gt;, and sign in.&lt;/p&gt;
&lt;p&gt;Once you&#39;re signed in, choose &amp;quot;My Private MOCs&amp;quot; from the account dropdown menu and click &amp;quot;Add New Private MOC&amp;quot;, give it a name, and then press &amp;quot;Save Details&amp;quot;. Below this you will see a number of import options, but for the purposes of this article, we&#39;ll be focusing only on the LXF import. Click &amp;quot; Import from MPD/LDR/LXF file&amp;quot;, choose your LXF file from your computer, and press &amp;quot;import&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://studshq.s3.amazonaws.com/rebrickable-import.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Rebrickable will then show all the parts from the model and indicate if any colours you&#39;ve used don&#39;t exist. To fix any errornous colours, click on the part and choose a valid colour from the dropdown, and hit &amp;quot;Save&amp;quot;. This is also a good time to change the colour of any parts that Rebrickable marks as &amp;quot;rare&amp;quot; — you may want to switch to a more common colour to make it easier to buy.&lt;/p&gt;
&lt;p&gt;Once you&#39;re happy with your part list, click &amp;quot;Add to your Bricklink Wanted List&amp;quot;. A window will popup allowing you to login to Bricklink. You can choose to add them to an existing list, or create a new one from this window. Once you click &amp;quot;Add parts&amp;quot;, a message will confirm that the parts have been added, and there will be a button to view your wanted list.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://studshq.s3.amazonaws.com/rebrickable-add-to-list.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Update: When this post was written, I didn&#39;t realise Rebrickable had a feature to automatically add parts to a Bricklink wanted list.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;s&gt;Once you&#39;re happy with your part list, click &amp;quot;Export to Bricklink (XML)&amp;quot; and your parts list will be downloaded in the correct format to import into Bricklink.&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;If you want to upload the parts list to a specific wanted list on Bricklink, you will need to edit the XML file in a text editor (I recommend &lt;a href=&quot;https://www.sublimetext.com/&quot;&gt;Sublime Text&lt;/a&gt;). You&#39;ll need to add &lt;code&gt;&amp;lt;WANTEDLISTID&amp;gt;12345&amp;lt;/WANTEDLISTID&amp;gt;&lt;/code&gt; to every part in the XML file, where &lt;code&gt;12345&lt;/code&gt; refers to your Bricklink wanted list ID.&lt;/p&gt;
&lt;p&gt;Once all that is done, you can &lt;a href=&quot;http://www.bricklink.com/wantedXML.asp&quot;&gt;upload it to Bricklink&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>How to use Rebrickable to convert an LXF file to Bricklink XML format to upload to a wanted list.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Third Party Apple Watch Bands Review</title>
    <link href="https://rknight.me/blog/third-party-apple-watch-bands/"/>
    <updated>2015-11-16T00:00:00Z</updated>
    <id>https://rknight.me/third-party-apple-watch-bands/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/apple-watch-bands.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When I first saw the &lt;a href=&quot;http://www.apple.com/pr/library/2015/09/09Apple-and-Herm-s-Unveil-the-Apple-Watch-Herm-s-Collection.html&quot;&gt;Hermès Cuff for Apple Watch&lt;/a&gt; I thought it looked like a great watch band but also knew that there was no way I was going to pay upwards of a thousand pounds for one. So I kept an eye on eBay, looking for third party manufacturers making similar bands. These became available for purchase about a month after the announcement so I decided to order one. The seller also had some other copies of Apple&#39;s bands and I ordered a blue sport band, a black Milanese loop, as well as a pair of black adaptors to better match my space grey sport watch.&lt;/p&gt;
&lt;h3&gt;Leather Cuff (£20)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ebay.co.uk/itm/301765700770?_trksid=p2057872.m2749.l2649&amp;amp;var=600584661853&amp;amp;ssPageName=STRK%3AMEBIDX%3AIT&quot;&gt;eBay link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I haven&#39;t seen the Hermès band in real life so I can only compare against photos but this band is more or less identical in design to the Hermès version. But as you might imagine, it feels cheap. The leather is pretty thin, not particularly soft, and it&#39;s generally uncomfortable to wear. The buckle feels like a toy from a Christmas cracker. There are some third party version that are around the £100 mark that would likely not have these issues but something I did notice whilst wearing the band, is that because of the way the band is designed my Apple Watch sits significantly higher on my wrist then when I using a sport band. I found this to be annoying and it&#39;s possible that the Hermès version has the same problem.&lt;/p&gt;
&lt;h3&gt;Black Milanese (£20)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ebay.co.uk/itm/301743856877?_trksid=p2057872.m2749.l2649&amp;amp;var=600570788016&amp;amp;ssPageName=STRK%3AMEBIDX%3AIT&quot;&gt;eBay link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Apple only makes the Milanese loop milanese loop in one colour, so for someone like me with the space grey watch, my only option for a milanese loop is third party. The band I ordered is comfortable, but it &lt;em&gt;does&lt;/em&gt; feel like it costs. There are some more expensive options available but I can&#39;t speak for how these compare to this one. The magnet is strong, but the materials used for the band itself just aren&#39;t that great and can get uncomfortable with continued use.&lt;/p&gt;
&lt;h3&gt;Blue Sport Band (£5)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://www.ebay.co.uk/itm/301743860511?_trksid=p2057872.m2749.l2649&amp;amp;var=600570790558&amp;amp;ssPageName=STRK%3AMEBIDX%3AIT&quot;&gt;eBay link&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After trying the leather cuff and seeing how cheap it felt, I was surprised to find that the sport band from the same seller felt great. The design is identical in every way to the official version and feels more or less the same when wearing it. The only noticeable difference between this one and the Apple version is that Apple&#39;s feels a little bit thicker and sturdier. The band doesn&#39;t fit quite as snugly is the slots as it&#39;s official counterpart, but it&#39;s still feels sturdy. It&#39;s just as comfy as Apple&#39;s and at £5, it&#39;s a bargain.&lt;/p&gt;
&lt;p&gt;These bands are fine if you want something that&#39;s not a sport band and aren&#39;t willing to spend out the money for the offical onces but overall, you get what you pay for. I think, as usual, &lt;a href=&quot;http://www.relay.fm/upgrade/56&quot;&gt;Myke was right&lt;/a&gt;. I&#39;m going to stick to sport bands for the forseeable future. They&#39;re much more comfortable to wear for an extended period and that&#39;s more important to me than anything else.&lt;/p&gt;
</content>
    <summary>A review of some third-party replicas of Apple's watch bands</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Game Controller Double Standards</title>
    <link href="https://rknight.me/blog/game-controller-double-standards/"/>
    <updated>2015-11-11T00:00:00Z</updated>
    <id>https://rknight.me/game-controller-double-standards/</id>
    <content type="html">&lt;p&gt;The new Apple TV supports game controllers which is great. What&#39;s not so great is the fact that developers can&#39;t require them. By not allowing developers to require a game controller, what Apple have done is limited the platform and the games produced for it. I bought a &lt;a href=&quot;http://www.apple.com/uk/shop/product/HJ162ZM/A/steelseries-nimbus-wireless-gaming-controller&quot;&gt;Nimbus controller&lt;/a&gt; so I could play games like &lt;a href=&quot;https://itunes.apple.com/nz/app/rayman-adventures./id973020044?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=twitter&quot;&gt;Rayman Adventures&lt;/a&gt; and &lt;a href=&quot;https://itunes.apple.com/gb/app/asphalt-8-airborne/id610391947?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=twitter&quot;&gt;Asphalt 8&lt;/a&gt; but I only ever use 1 or 2 buttons on the controller in any given game. It&#39;s unreasonable to expect developers to have one set of controls for the Siri remote and another for a controller, without changing the game significantly to support this.&lt;/p&gt;
&lt;p&gt;Guitar Hero, however, is allowed to require a controller but not a standard MFi controller; Guitar Hero requires a purpose-built controller that presumably won&#39;t be able to be used for other games on Apple TV (except more Guitar Hero games). This kind of double standard is frustrating for both developers and owners of the Apple TV and I hope Apple decide to reverse their decision on not requiring game controllers soon.&lt;/p&gt;
</content>
    <summary>The new Apple TV supports game controllers which is great. What's not so great is the fact that developers can't require them.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Tips for Apple TV App Developers</title>
    <link href="https://rknight.me/blog/tips-for-apple-tv-app-developers/"/>
    <updated>2015-11-09T00:00:00Z</updated>
    <id>https://rknight.me/tips-for-apple-tv-app-developers/</id>
    <content type="html">&lt;p&gt;Since the Apple TV got released I have been running &lt;a href=&quot;http://atvapps.net&quot;&gt;Apple TV Apps&lt;/a&gt;, a blog and Twitter account showcasing the best Apple TV apps available. With discoverability being sub-par compared to the iOS app store, the site has been moderately successful and I&#39;ve been contacted by a number of developers with iTunes links to their apps asking me to feature them, but there&#39;s a problem. Those links don&#39;t go anywhere; no web previews, no way to view these apps in iTunes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/connecting-to-itunes.png&quot; alt=&quot;Connecting to iTunes&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Graham Spencer summed up what is needed from developers really well:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Apple TV developers, &lt;em&gt;please&lt;/em&gt; make sure you have a landing page with screenshots, info, price and press kit!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The page doesn&#39;t have to be the most beautiful website in the world but the information needs to be available if you expect your app to be featured anywhere. There are a number of options to get a simple website up and running with very little effort.&lt;/p&gt;
&lt;h3&gt;Free options&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.com/&quot;&gt;Wordpress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://tumblr.com&quot;&gt;Tumblr&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although Wordpress and Tumblr are both blogging platforms, they can be used as landing pages with a little bit of tweaking in the settings.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; - If you know some HTML and CSS, you can get a GitHub pages site up in a matter of minutes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Paid options&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://squarespace.com/coverpage&quot;&gt;Squarespace&lt;/a&gt; - Their cover page starts at just $5 a month and is perfect for an app landing page.&lt;/li&gt;
&lt;li&gt;Roll your own - If you&#39;re comfortable with setting everything up yourself, you can build and host your own website. &lt;a href=&quot;https://hover.com/scHIv4WR&quot;&gt;Hover&lt;/a&gt; is a great option for domains and &lt;a href=&quot;https://www.digitalocean.com/?refcode=8e1d8283bd20&quot;&gt;Digital Ocean&lt;/a&gt; offer one-click installs for loads of web applications like Wordpress and &lt;a href=&quot;https://ghost.org/&quot;&gt;Ghost&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Checklist&lt;/h3&gt;
&lt;p&gt;At a minimum, you should have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A few screenshots of the various parts of your apps (ideally the same ones featured in the store)&lt;/li&gt;
&lt;li&gt;A description of your app (again, the same description as you have in the app store is ideal)&lt;/li&gt;
&lt;li&gt;The price — this is a more difficult one because of pricing in different countries, but put the price in at least one currency.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some other things that will help market your app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A video of your app. This is useful for helping people decide whether they want to but your app or not.&lt;/li&gt;
&lt;li&gt;A press kit. This is normally a zip file which includes all the the above information (screenshots, description, video) as well as your app icon and any other marketing materials you might have.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For an example that fits all of these criteria, check out the &lt;a href=&quot;http://almostimpossible.co/&quot;&gt;landing page for Almost Impossible!&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/almost-impossible.png&quot; alt=&quot;Almost Impossible Landing Page&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Until Apple allows web previews for Apple TV apps, your goal should be to replicate all of the information you have in the app store. If you at least some of the above, your app is much more likely to be featured and also it will help customers decide if they want to buy your app.&lt;/p&gt;
</content>
    <summary>Some tips for marketing your Apple TV app successfully.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The Best Apple TV Apps</title>
    <link href="https://rknight.me/blog/the-best-apple-tv-apps/"/>
    <updated>2015-10-28T00:00:00Z</updated>
    <id>https://rknight.me/the-best-apple-tv-apps/</id>
    <content type="html">&lt;p&gt;I&#39;ve started a new blog to highlight some the best and most interesting Apple TV apps available. If you&#39;re interested you can &lt;a href=&quot;http://twitter.com/_atvapps&quot;&gt;follow @_atvapps on Twitter&lt;/a&gt; or check out the blog at &lt;a href=&quot;http://atvapps.net&quot;&gt;http://atvapps.net&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>I've started a new blog to highlight some the best and most interesting Apple TV apps available.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>My Home Screen (September 2015)</title>
    <link href="https://rknight.me/blog/homescreen-september-2015/"/>
    <updated>2015-09-11T00:00:00Z</updated>
    <id>https://rknight.me/homescreen-september-2015/</id>
    <content type="html">&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://rmlewisuk.s3.amazonaws.com/homescreen-september-2015.jpg&quot;&gt;&lt;img style=&quot;float:left;padding:10px;&quot; src=&quot;http://rmlewisuk.s3.amazonaws.com/homescreen-september-2015.jpg&quot; width=&quot;250&quot; height=&quot;auto&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I like to try and keep all of my apps on one page, hence the large number of folders. In the fight between quick access to apps and tidiness, tidiness always wins. Having said that, I do still like to keep my most used apps one tap away. The empty bottom row is used primarly for apps that I&#39;m trying out which, at the moment, happens to be &lt;a href=&quot;https://itunes.apple.com/gb/app/bf-news/id981609476?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;BuzzFeed News&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because I only have one screen of apps, my dock is less important than if I had multiple pages. I have always kept phone and Safari in those spots and as I&#39;ve added more messaging apps (&lt;a href=&quot;https://itunes.apple.com/us/app/facebook/id284882215?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Facebook&lt;/a&gt;, &lt;a href=&quot;https://itunes.apple.com/us/app/slack-team-communication/id618783545?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Slack&lt;/a&gt;, &lt;a href=&quot;https://itunes.apple.com/us/app/snapchat/id447188370?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Snapchat&lt;/a&gt;) the Messages app has been replaced by a folder to contain them all. Similarly, because I switch between listening to podcasts in &lt;a href=&quot;https://itunes.apple.com/us/app/overcast-podcast-player/id888422857?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Overcast&lt;/a&gt; and music, all media-related apps go into the media folder in the dock.&lt;/p&gt;
&lt;p&gt;The app I use the most is definitely &lt;a href=&quot;https://itunes.apple.com/us/app/tweetbot-3-for-twitter.-elegant/id722294701?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Tweetbot&lt;/a&gt;; I spend a lot of time on Twitter so I need to be able to get to it quickly. I also regulary catch on a number of subreddits and &lt;a href=&quot;https://itunes.apple.com/us/app/narwhal-for-reddit/id845422455?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Narwhal&lt;/a&gt; is easily the best Reddit client I&#39;ve found as the official one is far too confusing. &lt;a href=&quot;https://itunes.apple.com/us/app/clear-tasks-reminders-to-do/id493136154?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Clear&lt;/a&gt; and &lt;a href=&quot;https://itunes.apple.com/us/app/fantastical-2-for-iphone-calendar/id718043190?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Fantastical&lt;/a&gt; are the best apps in their respective categories and I wouldn&#39;t even considering removing them from the home screen. Although I don&#39;t use it as much as Tweetbot or Narwhal, &lt;a href=&quot;https://itunes.apple.com/us/app/plot-discover-track-movies/id922985808?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Plot&lt;/a&gt; is a fantastic app for keeping track of movies I want to watch and ones that I have watched.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://simplecast.fm&quot;&gt;Simplecast&lt;/a&gt; is a saved web site and not a native application, but I like to check up on the download numbers for &lt;a href=&quot;http://ruminatepodcast.com&quot;&gt;my podcast&lt;/a&gt; so that earns a spot on my home screen. Some of the other apps that are hidden away that I use regularly include &lt;a href=&quot;https://itunes.apple.com/us/app/due-reminders-countdown-timers/id390017969?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Due&lt;/a&gt;, a simple but really powerful reminders app, &lt;a href=&quot;https://itunes.apple.com/us/app/blink-better-affiliate-links/id946766863?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Blink&lt;/a&gt; for generating iTunes affiliate links and &lt;a href=&quot;https://itunes.apple.com/us/app/deliveries-a-package-tracker/id290986013?mt=8&amp;amp;at=1001l3gY&amp;amp;ct=blog&quot;&gt;Deliveries&lt;/a&gt; for tracking parcels.&lt;/p&gt;
&lt;p&gt;The background is a Star-Lord wallpaper (that I also use &lt;a href=&quot;https://hellsite.rknight.me/635851605364051968&quot;&gt;on my desktop&lt;/a&gt;) and you can &lt;a href=&quot;http://justinmaller.com/project/helmetica/&quot;&gt;download it here&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>My iPhone home screen as of September 2015</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>New Podcast: Ruminate</title>
    <link href="https://rknight.me/blog/ruminate-podcast/"/>
    <updated>2015-08-24T00:00:00Z</updated>
    <id>https://rknight.me/ruminate-podcast/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://johnvoorhees.co/&quot;&gt;John Voorhees&lt;/a&gt; and I decided to have a go at creating out own podcast. The current description of the show is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A podcast about the opportunities and challenges that technology presents us with every day&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This might change in the future (podcasts are harder than they seem) but for now we&#39;ll be talking about how technology helps solve problems, as well as some non-tech related topics like terrible food, and why you would save a pair of shoes for 10 years.&lt;/p&gt;
&lt;p&gt;~You can subscribe and listen to the first episode at &lt;a href=&quot;http://ruminatepodcast.com/1&quot;&gt;http://ruminatepodcast.com/1&lt;/a&gt; and follow us &lt;s&gt;on Twitter&lt;/s&gt; on &lt;a href=&quot;https://social.lol/@ruminate&quot;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>A new podcast by John Voorhees and myself</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Manage Your LEGO Collection with Brickset</title>
    <link href="https://rknight.me/blog/manage-your-lego-collection-with-brickset/"/>
    <updated>2015-04-16T00:00:00Z</updated>
    <id>https://rknight.me/manage-your-lego-collection-with-brickset/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://brickset.com/&quot;&gt;Brickset&lt;/a&gt;, as well as being a great source for LEGO news and reviews, is a also an excellent service for keeping a list of all the sets and minifigures that you own. Brickset also has some more advanced features for marking sets that you own without minifigures and custom flags to make managing your collection even easier. Once you&#39;ve set up your collection, you can also share it publicly if you desire. For example, &lt;a href=&quot;http://brickset.com/sets/ownedby-rmlewisuk&quot;&gt;here is my collection&lt;/a&gt;. If you haven&#39;t already, &lt;a href=&quot;http://brickset.com/signup&quot;&gt;signup for a Brickset account&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Sets&lt;/h2&gt;
&lt;p&gt;There are a number of different ways you can search for sets to add them to your collection: by set number, by set name or by tag. To add a set to your collection, type the set name or number into the search box and once you&#39;ve found the set you want to add, simply check the &amp;quot;I own&amp;quot; checkbox and it will be added to your collection. A large number of sets on Brickset are also tagged to make searching for a set easier; if you type &lt;code&gt;Emmet&lt;/code&gt; into the search box you will see &lt;code&gt;Emmet Brickowski [Tag]&lt;/code&gt; as one of the suggestions. Selecting this option will show you &lt;a href=&quot;http://brickset.com/sets/tag-Emmet-Brickowski&quot;&gt;all sets that contain an Emmet minifigure&lt;/a&gt;. You can then view a list of all the sets you by selecting &lt;code&gt;Sets you own&lt;/code&gt; from the &lt;code&gt;My sets&lt;/code&gt; menu. You can also set up a wanted list of sets by checking the &lt;code&gt;I want&lt;/code&gt; checkbox: your wanted list can be found by selecting &lt;code&gt;Sets you want&lt;/code&gt; from the &lt;code&gt;My sets&lt;/code&gt; menu.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://studshq.s3.amazonaws.com/brickset-search.png&quot;&gt;&lt;img src=&quot;http://studshq.s3.amazonaws.com/brickset-search.png&quot; alt=&quot;brickset-search.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once you&#39;ve added a set, you will also be able to view a list of all the minifigures you own by going to &lt;a href=&quot;http://brickset.com/minifigs/mycollection-owned&quot;&gt;brickset.com/minifigs/mycollection-owned&lt;/a&gt;. Brickset will automatically work out which minifigures you have based on the sets you own. However, if you&#39;re like me, you may on occasion buy a set without the minifigures and Brickset has a feature to cope with this: flags.&lt;/p&gt;
&lt;h3&gt;Custom Flags and No Minifigures&lt;/h3&gt;
&lt;p&gt;Flags are a way for you to add extra metadata to the sets you own. To set up flags, go to &lt;a href=&quot;http://brickset.com/mycollection&quot;&gt;brickset.com/mycollection&lt;/a&gt; and select &lt;code&gt;Set up flags&lt;/code&gt;. Brickset allows you up to four custom flags: I have a &lt;code&gt;Bricklinked&lt;/code&gt; flag for noting when I bought the parts of a set from &lt;a href=&quot;https://www.bricklink.com/&quot;&gt;Bricklink&lt;/a&gt;, a &lt;code&gt;To build&lt;/code&gt; flag to note when I haven&#39;t yet opened a set and a &lt;code&gt;Maybe&lt;/code&gt; flag to use in conjunction with my wanted list. The blue flag has an extra checkbox to make the flag indicate that you don&#39;t own the minifigures for a set. By using this flag, Brickset will not show that you own the minifigures from any set with this flag applied.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://studshq.s3.amazonaws.com/brickset-flags.png&quot;&gt;&lt;img src=&quot;http://studshq.s3.amazonaws.com/brickset-flags.png&quot; alt=&quot;brickset-flags.png&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Loose Minifigures&lt;/h2&gt;
&lt;p&gt;If you have purchased a minifigure individually, there are two ways you can add this to your minifigures collection. The first is to find the set the minifigure comes from, select the &lt;code&gt;minifigures&lt;/code&gt; tab from the set page, and check the &lt;code&gt;I own&lt;/code&gt; checkbox. These will be added to your minifigure collection. The second method is to search by the name of the minifigure: simply change the search dropdown to &lt;code&gt;minifigs&lt;/code&gt;. Once you have found the minifigure you want to add to your collection, simple check the  &lt;code&gt;I own&lt;/code&gt; checkbox.&lt;/p&gt;
&lt;h2&gt;Custom lists&lt;/h2&gt;
&lt;p&gt;Once you&#39;ve set up your collection, you can filter by theme, year and sort it by various different methods (e.g. number of pieces). This is great for sets that are directly linked together by something official like a theme, but if you want to create a custom list  of sets, or BrickLists as Brickset calls them, you can. For example, I&#39;ve made &lt;a href=&quot;http://brickset.com/sets/list-12524&quot;&gt;a list of the sets given away with the Daily Mail last year&lt;/a&gt; for my own reference. To create a new BrickList, select &lt;code&gt;BrickLists&lt;/code&gt; from &lt;code&gt;My Menu&lt;/code&gt; and then select &lt;code&gt; Create new BrickList&lt;/code&gt;. Give your list a title and description and then you can start adding sets to it. You can choose to make it public or keep it private.&lt;/p&gt;
&lt;h2&gt;Find out if you own a specific part&lt;/h2&gt;
&lt;p&gt;As an additional bonus of having catalogued your collection, if you are looking for a specific part, Brickset will tell you which sets that you own contain that part you are looking for. Change the search dropdown to &lt;code&gt;part&lt;/code&gt;, find the part you want to find, choose a colour and then select &lt;code&gt;View sets in your collection that contain this part&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Collection Summary&lt;/h2&gt;
&lt;p&gt;Now you&#39;ve added all your sets and minifigures, you can view your collection summary by selecting &lt;code&gt;Collection summary&lt;/code&gt; from the &lt;code&gt;My Sets&lt;/code&gt; menu. This summary will show you, by theme, the total cost of the sets you own, the total numbers of sets in a theme and how many of them you own as well as a number of other data points. Fair warning: if you don&#39;t want to know how much you&#39;ve spent on LEGO, avoid this page.&lt;/p&gt;
</content>
    <summary>Brickset is a great service for cataloging your LEGO collection. This guide will show you how to use all the main features to keep an up-to-date list of the sets and minifigures you own.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Simple Git Deploy</title>
    <link href="https://rknight.me/blog/simple-git-deploy/"/>
    <updated>2015-03-29T00:00:00Z</updated>
    <id>https://rknight.me/simple-git-deploy/</id>
    <content type="html">&lt;p&gt;This is a simple way to deploy to a remote server, more for my reference than anything else.&lt;/p&gt;
&lt;p&gt;Create a new folder on the server and initialise a bare git repository in it.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; /root/repos/project-name&lt;br /&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; /root/repos/project-name&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; init &lt;span class=&quot;token parameter variable&quot;&gt;--bare&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a post-receive hook (&lt;code&gt;nano /hooks/post-receive&lt;/code&gt;) with this as the contents:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;REPO&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/root/repos/project-name&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;TMP_GIT_CLONE&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/tmp/project-name&lt;br /&gt;&lt;span class=&quot;token assign-left variable&quot;&gt;PUBLIC_DIR&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;/var/www/project-name&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone &lt;span class=&quot;token variable&quot;&gt;$REPO&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_GIT_CLONE&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-rp&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_GIT_CLONE&lt;/span&gt;/* &lt;span class=&quot;token variable&quot;&gt;$PUBLIC_DIR&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$TMP_GIT_CLONE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure to create the public directory if it doesn&#39;t already exist. Then add the remote to your local repo.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; live ssh@server:/root/repos/project-name&lt;/code&gt;&lt;/pre&gt;
</content>
    <summary>A simple method to git push to deploy.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Remove Laravel Homestead Environment Variables</title>
    <link href="https://rknight.me/blog/remove-homestead-environment-variables/"/>
    <updated>2015-03-27T00:00:00Z</updated>
    <id>https://rknight.me/remove-homestead-environment-variables/</id>
    <content type="html">&lt;p&gt;When you add environment variables to Laravel homestead, they get added so you can access them within your applications. The problem is, if you delete a varaible from your &lt;code&gt;homestead.yaml&lt;/code&gt; file, it doesn&#39;t get deleted within Homestead. If you need to remove them, you can delete them from &lt;code&gt;php-fpm.conf&lt;/code&gt; located at &lt;code&gt;/etc/php5/fpm/php-fpm.conf&lt;/code&gt;.&lt;/p&gt;
</content>
    <summary>How to delete envirionment variables from Laravel Homestead.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Stig Quote Generator</title>
    <link href="https://rknight.me/blog/stig-quote-generator/"/>
    <updated>2015-03-26T00:00:00Z</updated>
    <id>https://rknight.me/stig-quote-generator/</id>
    <content type="html">&lt;p&gt;This morning, I was watching Top Gear and decided it would be fun to create the &lt;a href=&quot;http://code.robblewis.me/stig-quotes/&quot;&gt;Stig quote generator&lt;/a&gt;. I grabbed all the &amp;quot;some say&amp;quot; quotes from the &lt;a href=&quot;http://en.wikiquote.org/wiki/Top_Gear&quot;&gt;Top Gear Wikiquote&lt;/a&gt; page and split them into two parts (the &amp;quot;some say&amp;quot; part and the &amp;quot;and that&amp;quot; parts). The generator then grabs two of them at random, one of each type, and joins them together. Example:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some say that his heart is in upside down, and that if he felt like it he could fire Alan Sugar.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/rmlewisuk/stig-quotes&quot;&gt;code is on GitHub&lt;/a&gt; if that&#39;s your thing.&lt;/p&gt;
</content>
    <summary>This morning, I was watching Top Gear and decided it would be fun to create the Stig quote generator.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>UltraViolet: Everything is Not Awesome</title>
    <link href="https://rknight.me/blog/ultraviolet/"/>
    <updated>2015-02-20T00:00:00Z</updated>
    <id>https://rknight.me/ultraviolet/</id>
    <content type="html">&lt;p&gt;Joe Steel &lt;a href=&quot;http://joe-steel.com/2015-02-20-Discs-not-Included.html&quot;&gt;wrote about digital content&lt;/a&gt; following an interview with a Kevin Tsujihara, CEO of Warner Bros. Entertainment:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Incredibly, he highlights that they’re still trying to push hard on UltraViolet. Consumers have roundly rejected this as any kind of solution. Disney, Google, and Apple won’t participate — but sure, let’s prop this sucker up, Weekend at Bernie’s style! It is a farce of a system that has wronged many that dare to use it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Joe and Dan also spoke about how bad UltraViolet is on &lt;a href=&quot;http://defocused.co/defocused/ep-36-youre-a-soldier-arry.html&quot;&gt;this week&#39;s Defocused&lt;/a&gt; so I thought I would take the oppurtunity to get an UltraViolet copy of The Lego Movie that came with the blu ray I bought. The UltraViolet slip in the blu ray suggests to &amp;quot;instantly stream or download&amp;quot; it takes &amp;quot;3 easy steps&amp;quot;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;http://flixter.com/getuv&quot;&gt;http://flixter.com/getuv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enter the code&lt;/li&gt;
&lt;li&gt;Follow the instructions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Step one and two went smoothly. The page at stage two noted that the UltraViolet download is for the &amp;quot;cinema version&amp;quot; only although it wasn&#39;t clear if the blu ray version was different. I was informed I would have to create &lt;em&gt;two&lt;/em&gt; accounts, Flixter and UltraViolet. These are for &amp;quot;&lt;em&gt;storing your film and TV collection in the cloud&lt;/em&gt;&amp;quot; and to &amp;quot;&lt;em&gt;stream and download your UltraViolet Digital Collection to your favourite compatible screens&lt;/em&gt;&amp;quot; respectively.&lt;/p&gt;
&lt;p&gt;Signing up for a Flixter account requires a name, email addrees and date of birth; this data can be used for the UltraViolet account as well, which is convenient. Alternatively, you can login with Facebook which asks for access to your profile, friends list and email address, or Google Plus which requests access to a list of all the people in your circles. To finalise the account(s) creation, the terms and conditions that you must agree to state (emphasis mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I accept UltraViolet&#39;s Terms of Use and Privacy Policy; agree to allow Flixster to link to my UltraViolet account and allow me to manage it through Flixster; and &lt;strong&gt;request that Flixster and Warner Bros. send me offers&lt;/strong&gt; and make product recommendations and use my UltraViolet account information for such purposes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On submission an error told me &amp;quot;&lt;em&gt;The UV username is not valid.&lt;/em&gt;&amp;quot;. I subsequently received an email asking me to confirm my Flixter account. Ignoring the error, I confirmed the account and was prompted to link my UltraViolet account, which I&#39;m pretty sure didn&#39;t exist. It didn&#39;t.&amp;quot;&lt;em&gt;Your connection to UltraViolet needs to be reset. Please click here to resolve this issue.&lt;/em&gt;&amp;quot; Flixter told me. The same UltraViolet linking page was presented with no way to sign up for a new account so I Googled for the &lt;a href=&quot;https://www.uvvu.com/signup&quot;&gt;sign up page&lt;/a&gt; and filled in the form. Success. Back to Flixter to link my brand new UltraViolet account, which worked this time and then redirected back to Flixter where I can finally view my collection. Of no movies. Nothing there. The code I originally entered hadn&#39;t worked so I selected &amp;quot;redeem&amp;quot; from the main menu.&lt;/p&gt;
&lt;p&gt;Redemption of a code on Flixter requires searching for the movie in their database rather than just entering the code directly. Then back to the UltraViolet site to enter the code again. After a few minutes of &amp;quot;updating my collection&amp;quot; I finally had the Lego Movie available to watch in my collection.&lt;/p&gt;
&lt;p&gt;This whole process took me about 40 minutes for &amp;quot;3 easy steps&amp;quot;. Everything is not awesome, Mr. Tsujihara. Not even close.&lt;/p&gt;
</content>
    <summary>I tried to redeem an UltraViolet download code. It didn't go well.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Fix Gmail SMTP Offline Error in Yosemite Mail</title>
    <link href="https://rknight.me/blog/fix-gmail-offline-os-x-yosemite-mail/"/>
    <updated>2014-10-17T00:00:00Z</updated>
    <id>https://rknight.me/fix-gmail-offline-os-x-yosemite-mail/</id>
    <content type="html">&lt;p&gt;Yosemite Mail will sometimes show Gmail outgoing mail as being offline when you first setup a Gmail account. To fix this open up Mail and do the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open preferences and go to Accounts.&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Edit SMTP Server List&amp;quot; from the &amp;quot;Outgoing Mail Server Dropdown&amp;quot;.&lt;/li&gt;
&lt;li&gt;Select &amp;quot;Advanced&amp;quot; and put your account password in the password input.&lt;/li&gt;
&lt;li&gt;Voila, all fixed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For some reason, Mail doesn&#39;t always save the password here on setup, so these are steps required to fix it.&lt;/p&gt;
</content>
    <summary>How to fix Gmail SMTP showing as offline in Yosemite mail.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Apple Privacy Statement</title>
    <link href="https://rknight.me/blog/apple-privacy-statement/"/>
    <updated>2014-09-18T00:00:00Z</updated>
    <id>https://rknight.me/apple-privacy-statement/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.apple.com/privacy/government-information-requests/&quot;&gt;Apple:&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;On devices running iOS 8, your personal data such as photos, messages (including attachments), email, contacts, call history, iTunes content, notes, and reminders is placed under the protection of your passcode. Unlike our competitors, Apple cannot bypass your passcode and therefore cannot access this data. So it&#39;s not technically feasible for us to respond to government warrants for the extraction of this data from devices in their possession running iOS 8.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is excellent news.&lt;/p&gt;
</content>
    <summary>Apple issued a statement on privacy and government information requests.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Relay FM</title>
    <link href="https://rknight.me/blog/relay-fm/"/>
    <updated>2014-08-18T00:00:00Z</updated>
    <id>https://rknight.me/relay-fm/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://relay.fm&quot;&gt;Myke and Stephen&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Relay FM is our new home on the Internet, and where you can find all of our podcasts. The shows you have known and loved for years are being rebooted as part of the new network. Everything we have done so far in our podcasting careers has led us here, and we&#39;re pouring all of our love, knowledge and attention into this thing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&#39;ve already listened to the &lt;a href=&quot;http://relay.fm/analogue/1&quot;&gt;first episode of Analog(ue)&lt;/a&gt; and &lt;a href=&quot;http://relay.fm/inquisitive/1&quot;&gt;Inquisitive&lt;/a&gt; and, as with everything Myke produces, they are fantastic. I wish him, Stephen and all the other hosts the best of luck.&lt;/p&gt;
</content>
    <summary>Myke Hurley and Stephen Hackett have launched their new podcast network, Relay FM</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>An Ode to Bionic</title>
    <link href="https://rknight.me/blog/bionic/"/>
    <updated>2014-07-09T00:00:00Z</updated>
    <id>https://rknight.me/bionic/</id>
    <content type="html">&lt;div style=&quot;text-align:center&quot;&gt;
&lt;p&gt;Things Are Happening,&lt;br /&gt;
Is This The End?,&lt;br /&gt;
It&#39;s What Panda&#39;s Must Feel Like,&lt;br /&gt;
All The Time.&lt;/p&gt;
&lt;p&gt;Stop Belling Yourself,&lt;br /&gt;
What&#39;s The Point,&lt;br /&gt;
Do You Remember Rogif Moore?,&lt;br /&gt;
Too Sad.&lt;/p&gt;
&lt;p&gt;World&#39;s Latest Podcast,&lt;br /&gt;
Our Non-Specific Internet Phone Calls​,&lt;br /&gt;
To Our Child Bionique,&lt;br /&gt;
The Magnificent Meese​.&lt;/p&gt;
&lt;p&gt;You, I and Our Love Child,&lt;br /&gt;
I Put A Bell On The End,&lt;br /&gt;
Not Even a Full Ding,&lt;br /&gt;
I&#39;ve Got To Get It All In.&lt;/p&gt;
&lt;p&gt;I Want To Sell You Clothes,&lt;br /&gt;
Potential, That&#39;s What It&#39;s Loaded With​,&lt;br /&gt;
It&#39;s A Team Effort, I&#39;d Like to Say,&lt;br /&gt;
Tinkerbell Button.&lt;/p&gt;
&lt;p&gt;This Show Isn&#39;t About Ecosystems,&lt;br /&gt;
One Star,&lt;br /&gt;
It&#39;s Probably Swearing​,&lt;br /&gt;
Fuck You, Everyone.&lt;/p&gt;
&lt;p&gt;They Come In Sets of Two,&lt;br /&gt;
Did It Hard and Fast,&lt;br /&gt;
World&#39;s Greatest Finale,&lt;br /&gt;
&lt;a href=&quot;http://vlcnr.rknight.me&quot;&gt;VLCNR forever&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;</content>
    <summary>An ode to Bionic. A poem made up of show titles.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>How to Install iOS8 Beta Without a Developer Account</title>
    <link href="https://rknight.me/blog/how-to-install-ios8-without-a-developer-account/"/>
    <updated>2014-06-03T00:00:00Z</updated>
    <id>https://rknight.me/how-to-install-ios8-without-a-developer-account/</id>
    <content type="html">&lt;p&gt;No no no no no no no no no no no no no no no no no no no no no no no no no no no no no no no no no no.&lt;/p&gt;
&lt;p&gt;If you&#39;re not a developer, this is not for you. If you do install it, don&#39;t go reviewing apps in the App Store because they don&#39;t work. Don&#39;t complain when shit breaks. Don&#39;t moan when the beta expires. Don&#39;t be surprised if your phone becomes unusable.&lt;/p&gt;
&lt;p&gt;Just don&#39;t.&lt;/p&gt;
</content>
    <summary>How to install iOS8 beta without a developer account.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Thoughts on Google Chromecast</title>
    <link href="https://rknight.me/blog/thoughts-on-chromecast/"/>
    <updated>2014-03-21T00:00:00Z</updated>
    <id>https://rknight.me/thoughts-on-chromecast/</id>
    <content type="html">&lt;p&gt;The Chromecast got released in the UK on Wednesday and I bought one, in the hopes it will be better than the plethora of other streaming devices I have (Apple TV, Google TV, Xbox 360, PS3). As a side note, the Google TV, specifically &lt;a href=&quot;https://www.sony.co.uk/support/en/product/NSZ-GS7&quot;&gt;this model&lt;/a&gt; is the worst peice of equipment I&#39;ve ever owned.&lt;/p&gt;
&lt;h3&gt;Setup&lt;/h3&gt;
&lt;p&gt;The Chromecast is really easy to setup; plug in the dongle into an HDMI port, plug in the power cable (either USB or mains) and turn your TV on. Then go to &lt;a href=&quot;http://chromecast.com/setup&quot;&gt;chromecast.com/setup&lt;/a&gt; and follow the instructions. I set it up on my Mac so I can&#39;t vouch for the Windows setup, but I think it&#39;d be pretty similar. Download and run the companion Mac app, setup your preferred wifi network, let any Chromecast updates run and you&#39;re good to go. None of the setup is done on the Chromecast itself, so there&#39;s no bullshit of trying to put in your wifi password with an on screen keyboard.&lt;/p&gt;
&lt;h3&gt;Apps&lt;/h3&gt;
&lt;p&gt;Google lists a number of apps &lt;a href=&quot;http://chromecast.com/apps&quot;&gt;on the Chromecast site&lt;/a&gt; that have support for the Chromecast but the ones I am most interested in were BBC iPlayer, Netflix, Plex and YouTube.&lt;br /&gt;
If you&#39;ve ever used AirPlay on an iOS device, using Chromecast is just as simple. In any supported app, select the &amp;quot;cast button&amp;quot;, choose your Chromecast from the list and the video will start playing through your TV.&lt;/p&gt;
&lt;p&gt;YouTube, Netflix and BBC iPlayer were fairly straight forward and worked without a hitch. Plex required me to update the server on my Mac to the latest version (I hadn&#39;t updated it for over a year). You can also use the Chromecast within Chrome on the desktop by installing the &lt;a href=&quot;https://chrome.google.com/webstore/detail/google-cast/boadgeojelhgndaghljhdicfkmllpafd&quot;&gt;Chromecast extension&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One of the biggest advantages of Chromecast over AirPlay to an Apple TV is the ability to leave the app your streaming from and do other things. When AirPlaying video, the app your streaming from has to be open the whole time, whereas the Chromecast loads the stream to the device itself, allowing you to check Twitter, Facebook or whatever else you want to do.&lt;/p&gt;
&lt;p&gt;If you use any of the apps listed on the Chromecast site on a regular basis, for £30 you really can&#39;t go wrong.&lt;/p&gt;
</content>
    <summary>The Google Chromecast has been released in the UK, so I had to buy one and try it out.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>New York</title>
    <link href="https://rknight.me/blog/new-york/"/>
    <updated>2014-01-05T00:00:00Z</updated>
    <id>https://rknight.me/new-york/</id>
    <content type="html">&lt;p&gt;I visited my friend over Christmas who is currently working in New York. I had an amazing time and I thought I would recommend some places I visited for anyone who is planning on visiting in the future, as well as to keep a record of what I got up to.&lt;/p&gt;
&lt;h3&gt;Restaurants&lt;/h3&gt;
&lt;p&gt;We ate at quite a few restaurants and these three are the ones I would recommend to anyone:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://roguenyc.com&quot;&gt;Rogue&lt;/a&gt; - Rogue is a sports bar but the food is absolutely fantastic. As long as you can put up with all the sports (I counted seven simultaneous games on one occasion) being shown on their 14+ televisions, it&#39;s well worth a visit.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rubytuesday.com/&quot;&gt;Ruby Tuesday, Times Square&lt;/a&gt; - Ruby Tuesday is exactly what you&#39;d expect from an American restaurant; huge portions, lots of meat and amazing buffalo chicken.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bellanapoli.com/&quot;&gt;Bella Napoli, 7th Avenue&lt;/a&gt; - An excellent Italian restaurant, great service and reasonably priced.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Attractions&lt;/h3&gt;
&lt;p&gt;Ignoring the obvious, well-known attractions such as Times Square and the Empire State Building, &lt;a href=&quot;http://thehighline.org&quot;&gt;the High Line&lt;/a&gt; was a personal highlight. The High Line is &lt;em&gt;&amp;quot;a public park built on an historic freight rail line elevated above the streets on Manhattan’s West Side&amp;quot;&lt;/em&gt; and definitely makes a nice change of pace from barging past people on the streets. We took a ride on the &lt;a href=&quot;http://www.circlelinedowntown.com/&quot;&gt;Circleline Downtown Cruise&lt;/a&gt; which gives great views of the Statue of Liberty, the Manhattan skyline as well as Ellis Island and Governor&#39;s Island. We also did a helicoptor tour which gave spectacular views, but it is a little on the pricy side (~£100 p/person for 15 minutes). And I turned into a little kid when I visited the &lt;a href=&quot;http://www.nintendoworldstore.com/&quot;&gt;Nintendo Store&lt;/a&gt; at the Rockefeller Center.&lt;/p&gt;
&lt;h3&gt;Photos&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://edpoole.me&quot;&gt;Ed&lt;/a&gt; was kind enough to lend me his Canon 650D to take photos which was an interesting experience. Apparently, a good camera &lt;em&gt;doesn&#39;t&lt;/em&gt; make you a good photographer. I got used to it after a couple of days and managed to get a few nice photos which I have &lt;a href=&quot;https://rmlewisuk.exposure.so/new-york-2013&quot;&gt;posted on Exposure&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>I visited New York for Christmas and New Year. Here are a few recommendations for place to visit, eat and drink</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Create a Table in Markdown with No Headers</title>
    <link href="https://rknight.me/blog/create-a-blank-no-header-markdown-table/"/>
    <updated>2013-11-12T00:00:00Z</updated>
    <id>https://rknight.me/create-a-blank-no-header-markdown-table/</id>
    <content type="html">&lt;p&gt;Whilst creating a document which requires me to put some data (which isn&#39;t in the slightest way tabular data) into a table, I wanted to create the table with no headers. However the way markdown works mean it requires you to set a header for it to create a table in the first place. By using the HTML non-breaking space entity it can be done:&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;&lt;span class=&quot;token table&quot;&gt;&lt;span class=&quot;token table-header-row&quot;&gt;&lt;span class=&quot;token table-header important&quot;&gt;&lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;nbsp;&quot;&gt;&amp;amp;nbsp;&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token table-header important&quot;&gt; &lt;span class=&quot;token entity named-entity&quot; title=&quot;&amp;nbsp;&quot;&gt;&amp;amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token table-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;------&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;-----&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;token table-data-rows&quot;&gt;&lt;span class=&quot;token table-data&quot;&gt;Stuff  &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token table-data&quot;&gt; More things&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Simple.&lt;/p&gt;
</content>
    <summary>Markdown doesn't allow you to create tables without a header by default. This little hack allows you to do that.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Parents: Take Some Fucking Responsibility</title>
    <link href="https://rknight.me/blog/parents-take-some-responsibility/"/>
    <updated>2013-10-01T00:00:00Z</updated>
    <id>https://rknight.me/parents-take-some-responsibility/</id>
    <content type="html">&lt;p&gt;The &lt;a href=&quot;http://www.telegraph.co.uk/technology/apple/10346236/Twins-rack-up-1000-iPad-bill-buying-virtual-pets.html&quot;&gt;Telegraph reported this morning&lt;/a&gt; that two six-year-olds racked up a £1000 bill through in app purchases because they knew their parents iTunes password. And of course the parents are placing the blame entirely on the developers of apps that include in-app purchases.&lt;/p&gt;
&lt;h3&gt;Parental controls&lt;/h3&gt;
&lt;p&gt;iOS has built in parental controls that allow for restrictions on downloading apps and when a password is required (either every 15 minutes, or always) among other settings. The problem is, there is no mention of these controls in the initial setup process, presumably to keep setup as simple as possible.&lt;/p&gt;
&lt;p&gt;Parents may not be aware these settings exist and therefore just assume they can&#39;t restrict access to purchases or other features of the operating system. For reference, restrictions are in settings:&lt;/p&gt;
&lt;p&gt;settings&amp;gt;general&amp;gt;restrictions&lt;/p&gt;
&lt;h3&gt;The Blame Game&lt;/h3&gt;
&lt;p&gt;The parents of the twins claim they knew the password for the account:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;...his children knew the password after using the iPad for schoolwork and games.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;quot;Using the iPad for schoolwork&amp;quot;? In what way would that involve needing the password for the iTunes account? So because they couldn&#39;t be bothered to check what their children were purchasing, they just gave them the password. Perhaps give them the pin number to your credit card so they can go and do their own shopping? They&#39;re six years old.&lt;/p&gt;
&lt;p&gt;This is not the first time this has happened. Back in March an eight-year-old &lt;a href=&quot;http://www.belfasttelegraph.co.uk/breakingnews/offbeat/boy-racks-up-a-1000-ipad-bill-29128775.html&quot;&gt;spent £980 on The Simpsons: Tapped Out&lt;/a&gt;. The parents responded by saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I appreciate children are their target audience but it is not right and there needs to be specific controls in place to stop this from happening.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Specific controls? Perhaps like the ones in settings?&lt;/p&gt;
&lt;p&gt;In both cases, Apple refunded the money to the parents as a gesture of good will. Jim Darymple nails it in this peice entitled &amp;quot;&lt;a href=&quot;http://www.loopinsight.com/2013/03/05/its-not-apples-job-to-be-a-parent-to-your-kids/&quot;&gt;It&#39;s not Apple&#39;s Job to be a parent to your kids&lt;/a&gt;&amp;quot;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The simple fact is, as parents, it’s up to us to monitor what our kids do with technology or any toy. If you choose not to use the included controls because they are a hassle, then that’s your choice. You made that decision.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Parents: take some fucking responsibility, stop blaming everyone else and use some common sense instead of letting your kids do whatever the hell they want.&lt;/p&gt;
</content>
    <summary>The Telegraph reported this morning that two six-year-olds racked up a £1000 bill through in app purchases because they knew their parents iTunes password. And of course the parents are placing the blame entirely on the developers of apps that include in-app purchases.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Pub Hack #1</title>
    <link href="https://rknight.me/blog/pub-hack-1/"/>
    <updated>2013-09-18T00:00:00Z</updated>
    <id>https://rknight.me/pub-hack-1/</id>
    <content type="html">&lt;p&gt;The first &lt;a href=&quot;http://pubhack.co.uk&quot;&gt;Pub Hack&lt;/a&gt; took place yesterday. Jo and Lillian did an excellent job of organising everything including food, t-shirts, trophies as well as all the other behind-the-scenes stuff that needed doing.&lt;/p&gt;
&lt;p&gt;The theme was &amp;quot;post-apocolypse&amp;quot; so pretty much everyone, including our team, took that to mean zombies. We wasted the first hour on an idea that we found had already been done and then got to work on &amp;quot;&lt;a href=&quot;http://blownover.meteor.com&quot;&gt;Has It Blown Over Yet?&lt;/a&gt;&amp;quot;. Blown Over takes inspiration from &lt;a href=&quot;http://uksnowmap.com&quot;&gt;UK Snow Map&lt;/a&gt;, and Shaun of the Dead, and allows people to report a zombie attack on Twitter (using the hashtag #pompeyzombie) or on the website. And of course it will show you pubs close to your location to wait for this to all blow over.&lt;/p&gt;
&lt;p&gt;We only had 10 hours to build it so the Twitter integration is a little bit buggy and the map pins just keep building up forever. But overall I&#39;m really happy with what we built.&lt;/p&gt;
&lt;p&gt;There were some excellent entries including &amp;quot;Apocalhipster&amp;quot; which used an iPhone accelarometer and web sockets to control a zombie-shooting hipster, &amp;quot;Last Man Standing&amp;quot; which used the battery level API to allow people to set off alarms on the laptops of those plugged into power and a first-person game set in the &lt;a href=&quot;http://brewhouseandkitchen.com/&quot;&gt;Brewhouse &amp;amp; Kitchen&lt;/a&gt;, where Pub Hack took place. There was also a similiar entry to ours tracking disasters across the world on a map and a directory of &amp;quot;forts&amp;quot; (read: pubs) in which to stay safe from the apocolypse.&lt;/p&gt;
&lt;p&gt;Our team won &amp;quot;Most Likely to Commercially Suceed&amp;quot; which was awesome, Apocalhipster won &amp;quot;Best Design&amp;quot; and the 3D game won overall. It was a really great day and I can&#39;t wait for the next one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;https://vimeo.com/75569166&quot;&gt;Pub Hack on Vimeo&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>The first Pub Hack took place yesterday and the theme was post-apocalypse.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Thoughts on the iPhone 5S and 5C</title>
    <link href="https://rknight.me/blog/thoughts-on-the-iphone-5s-and-5c/"/>
    <updated>2013-09-11T00:00:00Z</updated>
    <id>https://rknight.me/thoughts-on-the-iphone-5s-and-5c/</id>
    <content type="html">&lt;p&gt;So Apple had their iPhone event. &lt;a href=&quot;http://www.apple.com/iphone-5s/&quot;&gt;iPhone 5S&lt;/a&gt;. &lt;a href=&quot;http://www.apple.com/iphone-5c/&quot;&gt;iPhone 5C&lt;/a&gt;. Nothing particularly surprising but interesting nonetheless.&lt;/p&gt;
&lt;h2&gt;iPhone 5S&lt;/h2&gt;
&lt;p&gt;The same solid design of the iPhone 5 with an improved camera, A7 chip and fingerprint scanner system called Touch ID. Touch ID is the feature I&#39;m most excited about. Not because I find inputting a pin code &amp;quot;cumbersome&amp;quot;, as Phil Schiller said, but because I don&#39;t have to enter my password for iTunes purchases. And &lt;a href=&quot;http://www.loopinsight.com/2013/09/10/hands-on-with-the-iphone-5c-and-iphone-5s/&quot;&gt;according to Jim Darymple&lt;/a&gt;, it works well:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I went through the process of adding my fingerprint to the 5S and then unlocking the phone using the fingerprint. It’s pretty seamless to do, just following the onscreen instructions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The 5S comes in three colours, including the now-infamous &amp;quot;gold&amp;quot;. From what I&#39;ve seen of it, this isn&#39;t some flashy over-the-top monstrosity but a more subtle gold finish. I still won&#39;t be buying a gold one though.&lt;/p&gt;
&lt;p&gt;The camera has a lot of improvements including video recording at 120fps, a new burst mode for capturing action shots and a dual LED flash to &amp;quot;light your subject perfectly&amp;quot;.&lt;/p&gt;
&lt;h2&gt;iPhone 5C&lt;/h2&gt;
&lt;p&gt;The 5C is more or less an iPhone 5, with a slightly bigger battery and plastic back. It comes in five colours and you can get a &lt;a href=&quot;http://store.apple.com/uk/product/MF035/iphone-5c-case-blue&quot;&gt;hideous case&lt;/a&gt; for it, if you so choose.&lt;/p&gt;
&lt;p&gt;The interesting part about this model is it&#39;s not &amp;quot;cheap&amp;quot; per se. Yes, it £80 cheaper than the 5S but that&#39;s still not what I would call cheap. But it&#39;s cheap enough that it&#39;ll likely be free on most contracts in the UK.&lt;/p&gt;
&lt;p&gt;Taking a quick look around some carriers websites today, I can&#39;t seem to find a mention of the 5S, but the 5C is on all the home pages. It seems to me that this is the phone they&#39;re going to be trying to sell over the 5S for obvious reasons.&lt;/p&gt;
&lt;h2&gt;iWork, iMovie and iPhoto&lt;/h2&gt;
&lt;p&gt;From now on, when you buy a new iPhone or iPad, you&#39;re going to get the complete iOS iWork suite, as well as iMovie and iPhoto, for free. This is a great move by Apple and I wouldn&#39;t be surprised if the same deal was announced for iWork for Mac when Mavericks is released.&lt;/p&gt;
&lt;h2&gt;Release dates&lt;/h2&gt;
&lt;p&gt;Pre orders for the 5C and 5S &lt;a href=&quot;http://store.apple.com/uk&quot;&gt;open on Friday&lt;/a&gt;. iOS7 will be released the the public on 18th September, two days before the new iPhones.&lt;/p&gt;
&lt;p&gt;You can &lt;a href=&quot;http://www.apple.com/apple-events/september-2013/&quot;&gt;watch the announcement here&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>Apple announced two new iPhones: The 5C and the 5S will be released on the 20th of September</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>JustDelete.me: One Million Page Views</title>
    <link href="https://rknight.me/blog/just-delete-me-one-million-page-views/"/>
    <updated>2013-08-29T07:04:00Z</updated>
    <id>https://rknight.me/just-delete-me-one-million-page-views/</id>
    <content type="html">&lt;p&gt;When I wrote &lt;a href=&quot;/24-hours-of-just-delete-me/&quot;&gt;this post&lt;/a&gt; about &lt;a href=&quot;http://justdelete.me&quot;&gt;justdelete.me&lt;/a&gt; I assumed that would pretty much be the best I could hope for in terms of traffic. 3000 visitors in 24 hours was an amazing response to get.The last few days? We’ve been doing that in half an hour.&lt;/p&gt;
&lt;h2&gt;News coverage&lt;/h2&gt;
&lt;p&gt;The coverage in the news has been insane. We were picked up by &lt;a href=&quot;http://minimalmac.com/post/58698882020/robb-lewis-just-delete-me&quot;&gt;Minimal Mac&lt;/a&gt; on Monday and the traffic stayed pretty steady for the next couple of days. Then we were &lt;a href=&quot;http://www.wired.com/gadgetlab/2013-08-just-delete-me/&quot;&gt;featured in WIRED&lt;/a&gt; which skyrocketed traffic. From there, many of the other tech blogs picked up the story and we ended up at number one on Hacker News, trending on GitHub, number one on &lt;a href=&quot;https://pinboard.in/popular/&quot;&gt;Pinboard popular&lt;/a&gt; and Christina Warren was interviewed about the site on &lt;a href=&quot;http://www.foxbusiness.com/on-air/varney-co/index.html&quot;&gt;Varney and Co on Fox Business&lt;/a&gt;. Other sites that picked it up include &lt;a href=&quot;http://techcrunch.com/2013-08-23/justdelete-me-wants-to-help-you-pull-the-plug-on-all-those-pesky-online-accounts/&quot;&gt;TechCrunch&lt;/a&gt;, &lt;a href=&quot;http://mashable.com/2013-08-24/justdelete-me/?utm_cid=mash-com-fb-main-link&quot;&gt;Mashable&lt;/a&gt; and &lt;a href=&quot;http://gigaom.com/2013-08-23/painlessly-erase-your-internet-life-with-justdelete-me/&quot;&gt;Gigaom&lt;/a&gt;. I was also interviewed for &lt;a href=&quot;http://thetechtailor.com/justdeleteme&quot;&gt;The Tech Tailor podcast&lt;/a&gt;. All of the links I have found about the site are &lt;a href=&quot;https://pinboard.in/search/u:rmlewisuk?query=justdeleteme&quot;&gt;on Pinboard&lt;/a&gt; tagged as justdeleteme.&lt;/p&gt;
&lt;h2&gt;Hosting&lt;/h2&gt;
&lt;p&gt;I’ve got a little confession to make. I’ve never had more than 10 visitors on my site at the same time (except that one time Panic linked to me and the site died immediately). My hosting was costing me $1.50 a month. The server held up until around Thursday night when CPU usage was at 100%. &lt;a href=&quot;http://edpoole.me&quot;&gt;Ed&lt;/a&gt;, &lt;a href=&quot;http://mikerogers.io&quot;&gt;Mike&lt;/a&gt; and myself all jumped on a Skype call to work out what to do. Stupidly, I hadn’t even made the site static (thinking that hardly anyone would be interested) so we immediately converted it to static. We then cloned the site to &lt;a href=&quot;http://mdtm.pl/17Wu4ia&quot;&gt;MediaTemple&lt;/a&gt;, changed the name servers and waited. It took about 2 days for it to fully transfer over but the majority of traffic was going to MT which has held up really well. Since we moved the site, we’ve used over 80gb of bandwidth even though the site is only around 200kb.&lt;/p&gt;
&lt;h2&gt;Contributors and Future plans&lt;/h2&gt;
&lt;p&gt;We’re going to continue adding services from pull requests (We’ve done 130 from 61 different contributors so far) and I will open email submission again soon. We now have over 180 services listed (the current count is shown in the console on page load if you’re interested) which I’m sure will expand in the coming weeks. In terms of making some money to cover hosting and analytics costs we’re going to see how the traffic is in a week or two when the frenzy has died down and make a decision then.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://tosdr.org&quot;&gt;Terms of Service; Didn’t Read&lt;/a&gt; are looking at integrating our data with theirs to keep as much information up to date as possible. The &lt;a href=&quot;https://chrome.google.com/webstore/detail/justdeleteme/hfpofkfbabpbbmchmiekfnlcgaedbgcf&quot;&gt;JustDelete.me Chrome Extension&lt;/a&gt; is receiving some great feedback and Mike is currently considering creating versions for Firefox and Safari.&lt;/p&gt;
&lt;h2&gt;Statistics&lt;/h2&gt;
&lt;p&gt;We have been tracking visitor numbers with &lt;a href=&quot;https://www.gosquared.com/r/NjE0MzM4&quot;&gt;GoSquared&lt;/a&gt;. GoSquared are a real-time analytics company and they have been awesome in terms of supporting us and helping with upgrades. I can’t recommended, and thank, them enough. The top sources of traffic for the last 10 days are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.spiegel.de/netzwelt/web/online-account-webseite-mit-anleitungen-um-profil-zu-loeschen-a-918850.html&quot;&gt;Spiegel.de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mashable.com/2013-08-24/justdelete-me/?utm_cid=mash-com-fb-main-link&quot;&gt;Mashable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;wired.com/gadgetlab/2013-08-just-delete-me/&quot;&gt;Wired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tumblr (&lt;a href=&quot;http://tumblr.thefjp.org/post/59394819304/delete-yourself-from-web-services-with-justdelete-me&quot;&gt;likely this post&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://techcrunch.com/2013-08-23/justdelete-me-wants-to-help-you-pull-the-plug-on-all-those-pesky-online-accounts/&quot;&gt;TechCrunch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We’ve had visitors from at least 150 countries with United States, Germany and Italy making up the top three. Here’s a chart showing the last 10 day’s visitors, uniques and page views:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/just-delete-me-one-million-page-views-chart.png&quot; alt=&quot;chart_1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Some other random snippets of information about the site:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Over 13k likes on Facebook.&lt;/li&gt;
&lt;li&gt;The most used browser was Chrome.&lt;/li&gt;
&lt;li&gt;There have been over 6500 tweets about the site.&lt;/li&gt;
&lt;li&gt;The most used operating system was Windows 7.&lt;/li&gt;
&lt;li&gt;Half a million pages views were served on Monday and Tuesday alone.&lt;/li&gt;
&lt;li&gt;The average time spent on the site is around four minutes.&lt;/li&gt;
&lt;li&gt;The most used monitor size was 1366 x 768.&lt;/li&gt;
&lt;li&gt;Someone made a copy of the site trying to cash in on the press attention. As soon as we created an official Twitter account, he stopped getting mentioned. BOOM.&lt;/li&gt;
&lt;li&gt;The highest amount of people on the site at one time was 1842, on Tuesday.&lt;/li&gt;
&lt;li&gt;The Twitter account has more followers than me and Ed combined.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <summary>Just Delete Me was launched just 10 days ago and has already had over one million page views.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>24 Hours of Just Delete Me</title>
    <link href="https://rknight.me/blog/24-hours-of-just-delete-me/"/>
    <updated>2013-08-20T12:49:00Z</updated>
    <id>https://rknight.me/24-hours-of-just-delete-me/</id>
    <content type="html">&lt;p&gt;“&lt;em&gt;I’m sure I’ll get a couple of hundred visitors&lt;/em&gt;”. That’s what I was thinking yesterday when I launched &lt;a href=&quot;http://justdelete.me&quot;&gt;justdelete.me&lt;/a&gt;. I wasn’t completely wrong.&lt;/p&gt;
&lt;p&gt;The response to &lt;a href=&quot;http://justdelete.me&quot;&gt;justdelete.me&lt;/a&gt; has been incredible. In just 24 hours it was linked to by &lt;a href=&quot;http://minimalmac.com/post/58698882020/robb-lewis-just-delete-me&quot;&gt;Minimal Mac&lt;/a&gt; (swoon!), tweeted and retweeted by hundreds of people and had over 3000 visitors.&lt;/p&gt;
&lt;p&gt;Since launch five additional services have been added: Reddit, Lovefilm, MySpace, Amazon and Klout. To add Klout, I had to sign up for it to immediately delete my account. I saw things. Crazy, strange things. How’s that for dedication?&lt;/p&gt;
&lt;p&gt;Other stats of note:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visitors from over 70 different countries&lt;/li&gt;
&lt;li&gt;Around 30% of people were using Chrome&lt;/li&gt;
&lt;li&gt;Someone from &lt;a href=&quot;http://d.pr/i/I8JN&quot;&gt;Apple visited&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The top three operating systems were OS X 10.8, iOS 6.1 and Windows 7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also Ed, who designed the site, isn’t getting anywhere near enough credit for the project so &lt;a href=&quot;http://edpoole.me/portfolio&quot;&gt;go visit his portfolio&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>“I’m sure I’ll get a couple of hundred visitors”. That’s what I was thinking yesterday when I launched justdelete.me. I wasn’t completely wrong.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Just Delete Me</title>
    <link href="https://rknight.me/blog/just-delete-me/"/>
    <updated>2013-08-19T07:00:00Z</updated>
    <id>https://rknight.me/just-delete-me/</id>
    <content type="html">&lt;p&gt;After seeing a few tweets about how difficult it can be to delete your Skype account and then hearing that Netflix flat-out &lt;em&gt;won’t&lt;/em&gt; delete your details I decided to build &lt;a href=&quot;http://justdelete.me&quot;&gt;JustDelete.me&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://JustDelete.Me&quot;&gt;JustDelete.Me&lt;/a&gt; is a directory of urls to delete your account from web services. (Yes, I am aware how terrible that description is. If you’ve got a better one, &lt;a href=&quot;/contact&quot;&gt;let me know&lt;/a&gt;). Services are marked either easy, medium or hard depending on how difficult it is to delete that account. Those marked as hard have additional information on how to completely remove your account, such as Skype which requires you to contact customer services to do so.&lt;/p&gt;
&lt;p&gt;A lot of inspiration for the site came from Steve Streza’s &lt;a href=&quot;http://devcenter.me&quot;&gt;DevCenter.me&lt;/a&gt; and the search functionality is modified from the repository. I thought about just forking the repo and modifying it but the sites are different enough to warrant the time to build it myself. Also, where would have been the fun in that? &lt;a href=&quot;http://edpoole.me&quot;&gt;Ed Poole&lt;/a&gt; did a great on job on taking the initial concept and making it look a hell of a lot nicer than what I &amp;quot;designed&amp;quot;.&lt;/p&gt;
&lt;p&gt;At present there are 16 services listed. If you want to add a new service, &lt;a href=&quot;/contact&quot;&gt;drop me an email&lt;/a&gt; and let me know. Alternatively, &lt;a href=&quot;https://github.com/rmlewisuk/justdelete.me&quot;&gt;fork the repo&lt;/a&gt; on GitHub, add the site to the json file and submit a pull request.&lt;/p&gt;
&lt;p&gt;Update: &lt;a href=&quot;/24-hours-of-just-delete-me/&quot;&gt;24 Hours of Just Delete Me&lt;/a&gt;&lt;/p&gt;
</content>
    <summary>After seeing a few tweets about how difficult it can be to delete your Skype account and then hearing that Netflix flat-out won’t delete your details I decided to build JustDelete.me.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>How PF Meet Helped Me Get a Placement</title>
    <link href="https://rknight.me/blog/how-pf-meet-helped-me-get-a-placement/"/>
    <updated>2013-08-16T15:03:00Z</updated>
    <id>https://rknight.me/how-pf-meet-helped-me-get-a-placement/</id>
    <content type="html">&lt;p&gt;I &lt;a href=&quot;http://www.pfmeet.co.uk/how-pf-meet-helped-me-get-a-placement&quot;&gt;wrote a post over on the PF Meet blog&lt;/a&gt; about how the event helped me get an industrial placement. Worth a read if you&#39;re going to be applying for placements or wondering about the benefits of events like PF Meet.&lt;/p&gt;
</content>
    <summary>Portsmouth Freelancer's Meet is a monthly meetup and I was able to get a placement through the people I met there</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Lego Back to The Future Set Review</title>
    <link href="https://rknight.me/blog/lego-back-to-the-future-set-review/"/>
    <updated>2013-08-12T09:00:00Z</updated>
    <id>https://rknight.me/lego-back-to-the-future-set-review/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/lego-back-to-the-future-set-review.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;love&lt;/em&gt; Back to The Future. I even have a &lt;a href=&quot;http://instagram.com/p/HZnNqHMrQx/&quot;&gt;DeLorean tattoo&lt;/a&gt;. Back in December of last year, &lt;a href=&quot;http://blog.lego.cuusoo.com/2012-12-20/results-of-the-summer-lego-review/&quot;&gt;Lego announced that &lt;/a&gt; that they were going to be making a Back to The Future themed set. On Saturday my Back to The Future Lego set arrived and I opened it like a kid on Christmas morning.&lt;/p&gt;
&lt;p&gt;The set has 401 pieces, plus the usual random selection of spares, and a &lt;em&gt;huge&lt;/em&gt; instruction manual. A majority of the manual is to construct the DeLorean from the first film with the last few pages showing the modifications needed to make the other two versions. You get both the “OUTATIME” licence plate as well as the barcode one from the future.&lt;/p&gt;
&lt;p&gt;The flux capacitor custom brick is great and the time circuit states the destination time, rather than 1955, as 1958 which is the year the first Lego brick was introduced. The gull-wing doors are particularly fun to use, despite not having actual windows in them. They can be a little fragile and tend to fall off if I try and move the set whilst holding them.&lt;/p&gt;
&lt;p&gt;The Marty and Doc minifigures have double-sided faces (happy and shocked) and Doc has a double sided body; one side is his lab coat and one is a radiation suit. The figures are slightly too big to fit comfortably into the car, making it somewhat frustrating to close the doors. Although the finished product doesn’t look &lt;em&gt;exactly&lt;/em&gt; like the films, it’s pretty close considering it’s made of Lego and if you’re a fan of Back to The Future, you’re going to want this set. I got mine from &lt;a href=&quot;http://shop.lego.com/en-GB/The-DeLorean-time-machine-21103&quot;&gt;the Lego online store&lt;/a&gt; but it’s available pretty much anywhere Lego sets are sold.&lt;/p&gt;
</content>
    <summary>My review of the fourth Lego Cuusoo set, Back to The Future.</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Instapaper Beta</title>
    <link href="https://rknight.me/blog/instapaper-beta/"/>
    <updated>2013-08-10T00:00:00Z</updated>
    <id>https://rknight.me/instapaper-beta/</id>
    <content type="html">&lt;p&gt;Instapaper, having been &lt;a href=&quot;http://www.marco.org/2013-04-25/instapaper-next-generation&quot;&gt;sold to Betaworks&lt;/a&gt; in April, has a &lt;a href=&quot;http://beta.instapaper.com&quot;&gt;shiny new beta&lt;/a&gt; for the web interface which is long overdue. Not that the site wasn’t usable, but it was starting to feel very dated when compared to the likes of &lt;a href=&quot;http://getpocket.com&quot;&gt;Pocket&lt;/a&gt;. Despite this I had stuck with Instapaper as it had the one thing Pocket still doesn’t have: a way for me to pay them for the service, but that’s a topic for another day.&lt;/p&gt;
&lt;p&gt;The new interface is a complete overhaul of the old site and looks great. There are a number of things that could do with improvement (too much whitespace, not great on smaller screens) but it’s still in beta so I’m sure things will get better before the public release.&lt;/p&gt;
&lt;p&gt;It’s nice, for once, to see something be sold and not just left to fade into internet history. Although it was fairly certain this wouldn’t happen based on what Marco Arment said in this announcement of the sale:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We’ve structured the deal with Instapaper’s health and longevity as the top priority, with incentives to keep it going well into the future.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On top of the web beta, &lt;a href=&quot;http://blog.instapaper.com/post/57817543037&quot;&gt;Betaworks said in a blog post&lt;/a&gt; that there will be “&lt;em&gt;..new versions of the Instapaper iOS and Android apps&lt;/em&gt;”. This is an exciting time for Instapaper users and the future looks great for the service.&lt;/p&gt;
</content>
    <summary>Instapaper has a new beta version of the website</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Automatically Rename TV Shows with Hazel and TVNamer</title>
    <link href="https://rknight.me/blog/automatically-rename-tv-shows-with-hazel-and-tvnamer/"/>
    <updated>2013-08-08T00:00:00Z</updated>
    <id>https://rknight.me/automatically-rename-tv-shows-with-hazel-and-tvnamer/</id>
    <content type="html">&lt;p&gt;I download a lot of TV shows (all legal of course) and have been renaming the files using &lt;a href=&quot;https://github.com/tvrenamer/tvrenamer&quot;&gt;TVRenamer&lt;/a&gt;. After using TVRenamer manually for months I got fed up with having to do it, or the much more likely scenario happened where I would just leave them to build up in my downloads folder. I recently started using &lt;a href=&quot;http://www.noodlesoft.com/hazel.php&quot;&gt;Hazel&lt;/a&gt; to automatically rename and organise my photos. This works well because Hazel simply changes the filename to the date they were taken. TV shows are a little more complex than that as they have season and episode numbers as well as titles. Enter &lt;a href=&quot;https://github.com/dbr/tvnamer&quot;&gt;TVNamer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;TVNamer is a command line utility that takes a TV episode with an ugly filename (show.name.3x20.720[HD].avi) and changes it to something much more readable (ShowName S03E20 - Episode Title.avi). To install TVNamer follow the simple instructions in the &lt;a href=&quot;https://github.com/dbr/tvnamer/blob/master/readme.md&quot;&gt;readme&lt;/a&gt;, it only takes a couple of minutes. Once it’s installed to can use it by simple typing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tvnamer filename
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TVNamer will then parse the file, look for episode information and, if it finds more than one result, will prompt you to choose the correct one and confirm the rename. When I tested this the correct result was always the first one which makes using Hazel to automate the process much easier.&lt;/p&gt;
&lt;p&gt;If you’re not familiar with Hazel, it’s a preference pane for Mac that monitors folders and matches files based on rules much like iTunes smart playlists. You can then set actions to perform when your rules are matched such as move files, rename them or run shell scripts.&lt;/p&gt;
&lt;p&gt;To setup automatic renaming, open Hazel, select the folder where your TV shows download to, then add a new rule. Obviously rules will entirely depend on the type of files you choose to download but personally I set Hazel to find any files that have the extension &lt;em&gt;mkv&lt;/em&gt;, &lt;em&gt;avi&lt;/em&gt; or &lt;em&gt;mp4&lt;/em&gt;. Then choose to run a shell script on the matched files and choose &lt;em&gt;“embedded script”&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/automatically-rename-tv-shows-with-hazel-and-tvnamer-sshot.png&quot; alt=&quot;Hazel Screenshot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Select edit script and paste in the following:&lt;/p&gt;
&lt;p&gt;/usr/local/bin/tvnamer --batch &amp;quot;$1&amp;quot;&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;–batch&lt;/em&gt; option tells TVNamer to automatically choose the first result and rename it and the &lt;em&gt;$1&lt;/em&gt; refers to the matched file Hazel found. To test your rule is working select the cog dropdown in the main Hazel screen and select &lt;em&gt;&amp;quot;Run rules now&amp;quot;&lt;/em&gt;. Any files that match your Hazel rule should be renamed.&lt;/p&gt;
&lt;p&gt;Initially I found that Hazel can sometimes have issues with running TVNamer if you’re matching files within subdirectories of your downloads folder. To remedy this I have Hazel move matched files to another folder and rename them from there. Refer to &lt;a href=&quot;http://mac.tutsplus.com/tutorials/app-training/9-hazel-rules-to-increase-your-productivity/&quot;&gt;this Tuts+ guide&lt;/a&gt; to find out how to use Hazel to move files automatically.&lt;/p&gt;
</content>
    <summary>How I'm using Hazel and TVNamer to save a ton of time renaming files</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Hold Alt When Resizing to Center Windows on OS X</title>
    <link href="https://rknight.me/blog/hold-alt-when-resizing-to-center-windows-on-os-x/"/>
    <updated>2013-03-20T00:00:00Z</updated>
    <id>https://rknight.me/hold-alt-when-resizing-to-center-windows-on-os-x/</id>
    <content type="html">&lt;p&gt;Spotted this tip on Twitter (I can&#39;t remember/find who tweeted it, sorry!) and it blew my mind. When resizing a window in OS X, hold down alt. The window will stay centered on the screen. Amazing.&lt;/p&gt;
</content>
    <summary>A quick tip for resizing windows on OS X</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>70Decibels and 5by5</title>
    <link href="https://rknight.me/blog/70decibels-and-5by5/"/>
    <updated>2013-03-14T10:11:46Z</updated>
    <id>https://rknight.me/70decibels-and-5by5/</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.70decibels.com/blog/2013/3/13/were-moving-to-5by5.html&quot;&gt;70Decibels is merging with 5by5&lt;/a&gt; which is great news for everyone involved, including listeners. Myke has worked incredibly hard to get 70Decibels to where it is today, starting with The Bro Show and expanding to the packed list of shows now:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;70Decibels is nearly 18 months old. It&#39;s amazing what has happened in that time and we all know that we owe it all to you, the listeners. Without you tuning in every week, getting involved, asking questions, promoting us and letting us know when we fall short, we wouldn&#39;t be here. I just want to thank you all from the bottom of my heart for everything you&#39;ve done to get us to this point. All of us at the network cannot wait to share what comes next. Thank you all so much.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&#39;m not only a fan of 70Decibels and 5by5 but also, I&#39;m glad to say, Myke&#39;s friend. I couldn&#39;t be happier for him and this merger is one step closer to him going full time as a podcaster extraordinaire. Myke and Dan announced and talked at length about the merger, as well as podcasting in general on &lt;a href=&quot;http://www.70decibels.com/cmdspace/2013/3/13/033-a-big-announcement-with-dan-benjamin.html&quot;&gt;CMD+Space 033&lt;/a&gt;.&lt;/p&gt;
</content>
    <summary>70Decibels is merging with 5by5</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>Google Reader and Alternatives</title>
    <link href="https://rknight.me/blog/google-reader-and-alternatives/"/>
    <updated>2013-03-14T10:11:45Z</updated>
    <id>https://rknight.me/google-reader-and-alternatives/</id>
    <content type="html">&lt;p&gt;Google have announced that they&#39;re shutting down Google Reader come July 1st:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We launched Google Reader in 2005 in an effort to make it easy for people to discover and keep tabs on their favorite websites. While the product has a loyal following, over the years usage has declined. So, on July 1, 2013, we will retire Google Reader. Users and developers interested in RSS alternatives can export their data, including their subscriptions, with Google Takeout over the course of the next four months&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They call it usage decline but it&#39;s more likely that most users are simply using it as a sync engine to access their feeds through apps like &lt;a href=&quot;http://reederapp.com/&quot;&gt;Reeder&lt;/a&gt;. Whatever the reasons, this leaves many of us at a dead end in terms of reading RSS. You can of course export your data and Dave Caolo has &lt;a href=&quot;http://52tiger.net/daily-tip-export-your-feeds-from-google-reader/&quot;&gt;outlined the process on 52Tiger&lt;/a&gt;. Other have mentioned using services like &lt;a href=&quot;http://flipboard.com/&quot;&gt;Flipboard&lt;/a&gt; or &lt;a href=&quot;https://www.pulse.me/&quot;&gt;Pulse&lt;/a&gt; but I&#39;ve always found these apps to be a little bloated and they don&#39;t really fit with how I like to consume news. The only viable alternative as of right now is &lt;a href=&quot;http://www.feedafever.com/&quot;&gt;Fever&lt;/a&gt;. Fever is a self-hosted aggregator and is supported on iOS by the aforementioned Reeder as well as &lt;a href=&quot;https://itunes.apple.com/ca/app/sunstroke/id488564806?mt=8&quot;&gt;Sunstroke&lt;/a&gt;. Of course, being self-hosted means you&#39;re going to have to have somewhere to install it and at least some knowledge of server-side tech. &lt;a href=&quot;http://www.macstories.net/tutorials/how-anyone-can-install-fever-in-ten-minutes/&quot;&gt;MacStories&lt;/a&gt; have got a great tutorial to get you started. There is hope, however, in the form of &lt;a href=&quot;http://feedwrangler.net/&quot;&gt;Feed Wrangler&lt;/a&gt; a project by &lt;a href=&quot;https://alpha.app.net/davidsmith&quot;&gt;David Smith&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This project is already well along in development, with a working web interface and native apps. I was expecting to launch early this summer but Google has announced that they are closing down Reader July 1. That accelerates my plans and I am now working to get ready for public consumption as soon as possible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Between Fever, Feed Wrangler as well as projects that haven&#39;t been announced yet June might not be so bad for RSS after all.&lt;/p&gt;
</content>
    <summary>Google Reader is shutting down so I had a look for some alternatives</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>DIY Game Controller Rack</title>
    <link href="https://rknight.me/blog/diy-game-controller-rack/"/>
    <updated>2013-03-11T10:00:00Z</updated>
    <id>https://rknight.me/diy-game-controller-rack/</id>
    <content type="html">&lt;p&gt;Two Playstation 2, two GameCube, four N64, two Xbox, four Wii, two Guitar Hero. You get the idea, I have lots of controllers. So does &lt;a href=&quot;http://mattgemmell.com/2013/03-02-playing-nintendo-games-on-a-mac/&quot;&gt;Matt Gemmell&lt;/a&gt;. And I&#39;m sure, so do a lot of other people. My solution for organising them is a fairly simple one, but I haven&#39;t seen it documented elsewhere on the web. So here it is.&lt;/p&gt;
&lt;p&gt;I had an old DVD rack not being used for anything so I figured using that would be a good start (and avoid any cost to me). I purchased some blank DVD cases and popped them in every forth slot. This gave me enough spaces to house all of my controllers as well as a couple of spaces for Wii Nunchucks. I also left a larger space at the bottom for those damn Wii wheels and a mug which holds all of my controller extension cables, extra memory cards for the PS2 and GameCube.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/diy-game-controller-rack-whole.png&quot; alt=&quot;Whole game controller rack&quot; /&gt; For the Guitar Hero controllers, I put some screws in each side of the rack (measuring the width before, of course) and wrapped them in Cellotape although electrical tape, which I didn&#39;t have, would have been better. The Guitars slot nicely into these and hang out the way. I also stuck one screw in the front of the rack for the Wii Zapper.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://rmlewisuk.s3.amazonaws.com/diy-game-controller-rack-guitar.png&quot; alt=&quot;guiter hero controller holder&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And that&#39;s all there is to it.&lt;/p&gt;
</content>
    <summary>A quick and dirty solution to storing all my game controllers</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>I am a Tool</title>
    <link href="https://rknight.me/blog/i-am-a-tool/"/>
    <updated>2013-03-05T17:46:00Z</updated>
    <id>https://rknight.me/i-am-a-tool/</id>
    <content type="html">&lt;p&gt;As many of you noticed, moments ago my timeline (and yours) was filled with tweets from every single blog post I&#39;ve ever written. I apologise, I am a tool. Pro tip: Import posts &lt;em&gt;before&lt;/em&gt; setting up Wordpress to Twitter.&lt;/p&gt;
</content>
    <summary>I fucked up and posted hundreds of blog posts to Twitter all at once</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
  
  <entry>
    <title>The Difference Between Fact and Trivia</title>
    <link href="https://rknight.me/blog/the-difference-between-fact-and-trivia/"/>
    <updated>2013-02-27T13:11:00Z</updated>
    <id>https://rknight.me/the-difference-between-fact-and-trivia/</id>
    <content type="html">&lt;p&gt;This morning I took a practice exam for one of the web units I’m studying. Most of the questions were fairly easy but one of them in particular annoyed me. The question was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“PageRank is so named because it was created by Larry Page, not because it ranks pages”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I incorrectly marked this as &lt;em&gt;false&lt;/em&gt;. When I asked how much trivia we would be asked in the exam, my lecturer told me (quite agressively) that the question is not trivia but a fact that is useful to know. I argued the counterpoint, saying a fact is something useful to developing my understanding of a specific topic or technology, in this case, PageRank. She disagreed.&lt;/p&gt;
&lt;p&gt;Here is a quote from an archived version of a &lt;a href=&quot;http://web.archive.org/web/20090424093934/http://www.google.com/press/funfacts.html&quot;&gt;Google Fun Facts Page&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The basis of Google’s search technology is called PageRank™, and assigns an “importance” value to each page on the web and gives it a rank to determine how useful it is. However, that’s not why it’s called PageRank. It’s actually named after Google co-founder Larry Page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The first part of that statement is the fact. The last sentence is trivia. It holds no bearing on my understanding of PageRank. Should we really be tested on trivial facts about Google, or any other company for that matter? In my opinion, no.&lt;/p&gt;
&lt;p&gt;Rant over.&lt;/p&gt;
</content>
    <summary>A weird and annoying conversation I had at university today</summary>
    <author>
      <name>Robb Knight</name>
    </author>
  </entry>
</feed>
