<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="/feed.xsl" type="text/xsl" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en" xml:base="https://chrisburnell.com">
	<title>Chris Burnell · Articles</title>
	<subtitle>All of my articles.</subtitle>
	<id>https://chrisburnell.com/articles/</id>
	<link href="https://chrisburnell.com/articles.xml" rel="self" />
	<link href="https://chrisburnell.com/articles/" rel="alternate" />
	<author>
		<name>Chris Burnell</name>
		<uri>https://chrisburnell.com/</uri>
		<email>me@chrisburnell.com</email>
	</author>
	<logo>https://chrisburnell.com/images/raven.svg</logo>
	<image>https://chrisburnell.com/images/avatar@4x.jpeg</image>
	<updated>2026-05-09T12:49:02+00:00</updated>
	<generator>Eleventy v3.1.0</generator>
	<entry>
		<id>https://chrisburnell.com/article/fresh-pixels/</id>
		<link href="https://chrisburnell.com/article/fresh-pixels/" />
		<title>Fresh pixels</title>
		<published>2026-05-09T09:49:02-03:00</published>
		<publishedFriendly>9 May 2026</publishedFriendly>
		<updated>2026-05-09T09:49:02-03:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Status updates and enforcing the crispiest-possible 88x31 badges across the web</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Status updates and enforcing the crispiest-possible 88x31 badges across the web&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Yesterday afternoon, I spent some time creating a new &lt;a href=&quot;/88x31/&quot;&gt;88x31 badge&lt;/a&gt; for my website footer.&lt;/p&gt;
&lt;p&gt;In case you missed &lt;a href=&quot;/article/new-year-new-server-2/&quot;&gt;my last post&lt;/a&gt;, I’m in the midst of migrating servers, and one of the things I migrated was &lt;a href=&quot;https://status.chrisburnell.com&quot;&gt;my status page&lt;/a&gt;, which pings each of my websites once per minute and reports whether the request was successful, and if so, how long the request took. Each website is represented on the front end by a graph of response times across the last hour as well as 60 red or green-coloured &lt;em&gt;bloops&lt;/em&gt;, which represent the successes of the last hour’s pings.&lt;/p&gt;
&lt;p&gt;So the idea was to create a dynamic 88x31 badge that relayed information from my status page by displaying some number of the most recent &lt;em&gt;bloops&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I set out achieving this by first creating the 88x31 image with some blank areas that I could fill in later with green or red, depending on the status of each &lt;em&gt;bloop&lt;/em&gt;, and the next step was to create a short PHP script to consume this image, fill in the colours of the &lt;em&gt;bloops&lt;/em&gt;, and spit out the result.&lt;/p&gt;
&lt;p&gt;Fortunately, generating images with PHP is one of the first things I ever learned how to do outside of HTML and CSS early on in my web development journey, nearly 20 years ago, so this was a familiar task!&lt;/p&gt;
&lt;p&gt;And the result (blown up for clarity):&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;https://chrisburnell.com/images/uptime.gif&quot; alt=&quot;Server uptime badge&quot; width=&quot;352&quot; height=&quot;124&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;
&lt;/figure&gt;
&lt;details&gt;
    &lt;summary&gt;Backend code, if you’re interested&lt;/summary&gt;
&lt;p&gt;Here’s what the JSON file of minute-by-minute data looks like:&lt;/p&gt;
&lt;pre data-language=&quot;json&quot; data-language-friendly=&quot;JSON&quot; data-filename=&quot;uptime.json&quot;&gt;&lt;code&gt;&lt;span&gt;[&lt;/span&gt;
	&lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1778260261&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.406&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;200&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;http_version&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&quot;2&quot;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
	&lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1778260321&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.446&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;200&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;http_version&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&quot;2&quot;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
	&lt;span&gt;{&lt;/span&gt;
		&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;1778260381&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;0.807&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;200&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
		&lt;span&gt;&quot;http_version&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&quot;2&quot;&lt;/span&gt;
	&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here’s the gist of the PHP that generates the dynamic image:&lt;/p&gt;
&lt;pre data-language=&quot;php&quot; data-language-friendly=&quot;PHP&quot; data-filename=&quot;uptime.php&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;?php&lt;/span&gt;
&lt;p&gt;&lt;span&gt;$image&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;imagecreatefromgif&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;uptime.gif&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$green&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;imagecolorallocate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;102&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;204&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;51&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$red&lt;/span&gt;   &lt;span&gt;=&lt;/span&gt; &lt;span&gt;imagecolorallocate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;153&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;51&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$cacheFile&lt;/span&gt;  &lt;span&gt;=&lt;/span&gt; &lt;span&gt;&quot;cache.json&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$uptimeFile&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;&quot;uptime.json&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$numBloops&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;9&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;file_exists&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;||&lt;/span&gt; &lt;span&gt;filemtime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;time&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&lt;/span&gt; &lt;span&gt;60&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$uptimeData&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;json_decode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;file_get_contents&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$uptimeFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;usort&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$uptimeData&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;fn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;$b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$b&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&lt;/span&gt; &lt;span&gt;$a&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$recent&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;array_slice&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$uptimeData&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;$numBloops&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$cache&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$recent&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br&gt;
&lt;span&gt;&quot;bloops&quot;&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;array_map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;br&gt;
&lt;span&gt;fn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$item&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$item&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;0&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;$item&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;gt;=&lt;/span&gt; &lt;span&gt;200&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span&gt;$item&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;response&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;299&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$recent&lt;/span&gt;&lt;br&gt;
&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br&gt;
&lt;span&gt;]&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;file_put_contents&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;json_encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cache&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$cache&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;json_decode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;file_get_contents&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cacheFile&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;$bloops&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;array_reverse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$cache&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;&quot;bloops&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;foreach&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;$bloops&lt;/span&gt; &lt;span&gt;as&lt;/span&gt; &lt;span&gt;$i&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;$ok&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;$color&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;$ok&lt;/span&gt; &lt;span&gt;?&lt;/span&gt; &lt;span&gt;$green&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; &lt;span&gt;$red&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;imagefilledrectangle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;4&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;$color&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Content-type: image/gif&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Cache-Control: public, max-age=60&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;imagegif&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;$image&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And while we’re at it, here’s how I’m serving my PHP file as if it’s a GIF in &lt;em&gt;nginx&lt;/em&gt;:&lt;/p&gt;
&lt;pre data-language=&quot;nginx&quot; data-language-friendly=&quot;nginx&quot; data-filename=&quot;/etc/nginx/sites-available/example.com&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;location&lt;/span&gt; = /images/uptime.gif&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
    &lt;span&gt;&lt;span&gt;include&lt;/span&gt; fastcgi_params&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;&lt;span&gt;fastcgi_param&lt;/span&gt; SCRIPT_FILENAME /absolute/path/to/uptime.php&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
    &lt;span&gt;&lt;span&gt;fastcgi_pass&lt;/span&gt; unix:/run/php/php8.4-fpm.sock&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;In building this new 88x31, I was struck with another idea.&lt;/p&gt;
&lt;p&gt;Because I so fiercely believe that (most) 88x31 badges look best on the web when they have &lt;code&gt;image-rendering: pixelated;&lt;/code&gt; applied to them, why not enforce my belief across (almost) the entire web?&lt;/p&gt;
&lt;p id=&quot;using-css&quot;&gt;Using CSS&lt;/p&gt;
&lt;p&gt;I use the &lt;a href=&quot;https://add0n.com/stylus.html&quot;&gt;Stylus&lt;/a&gt; extension in my browser (&lt;a href=&quot;https://github.com/openstyles/stylus#releases&quot;&gt;get it here&lt;/a&gt;) to apply my own CSS to websites and pages. My custom styles are mostly to fix bugs, improve shaky layouts, or to add little quality-of-life stuff, and this seems like an ideal place for me to throw a small chunk of CSS and have my browser apply it across every page that I visit.&lt;/p&gt;
&lt;p&gt;The CSS I came up with is pretty minimal, and although it relies on the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes being present, many websites that I visit that &lt;em&gt;do&lt;/em&gt; have 88x31 badges at least have the attributes present, if not the desired CSS property applied as well:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:where(img[width=&quot;88&quot;][height=&quot;31&quot;])&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;image-rendering&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; pixelated&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here’s how it looks in &lt;em&gt;Stylus&lt;/em&gt;. Note that I’m applying this CSS to &lt;q&gt;Everything&lt;/q&gt;, which means &lt;em&gt;every&lt;/em&gt; webpage that you visit:&lt;/p&gt;
&lt;figure&gt;
    &lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;/images/built/stylus-pixelate-88x31s-500.avif 500w, /images/built/stylus-pixelate-88x31s-800.avif 800w&quot; sizes=&quot;100vw&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;/images/built/stylus-pixelate-88x31s-500.webp 500w, /images/built/stylus-pixelate-88x31s-800.webp 800w&quot; sizes=&quot;100vw&quot;&gt;&lt;img alt=&quot;Stylus UI when adding styles for all websites to pixelate 88x31 badges&quot; title=&quot;Stylus UI when adding styles for all websites to pixelate 88x31 badges&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;/images/built/stylus-pixelate-88x31s-500.png&quot; width=&quot;800&quot; height=&quot;128&quot; srcset=&quot;/images/built/stylus-pixelate-88x31s-500.png 500w, /images/built/stylus-pixelate-88x31s-800.png 800w&quot; sizes=&quot;100vw&quot;&gt;&lt;/picture&gt;
&lt;/figure&gt;
&lt;p id=&quot;using-js&quot;&gt;Using JavaScript&lt;/p&gt;
&lt;p&gt;Alternatively, if you want to achieve this for &lt;em&gt;all&lt;/em&gt; 88x31 images, whether they have the correct attributes or not, there’s the &lt;a href=&quot;https://www.tampermonkey.net/&quot;&gt;Tampermonkey&lt;/a&gt; extension (&lt;a href=&quot;https://www.tampermonkey.net/#download&quot;&gt;get it here&lt;/a&gt;) that works much like Stylus but with JavaScript instead of CSS. Here’s my script that checks the width and height of images &lt;em&gt;whether their attributes are set or not&lt;/em&gt; and appropriately applies the pixelated effect to 88x31 images:&lt;/p&gt;
&lt;pre data-language=&quot;javascript&quot; data-language-friendly=&quot;JavaScript&quot;&gt;&lt;code&gt;&lt;span&gt;// ==UserScript==&lt;/span&gt;
&lt;span&gt;// @name         Pixelate 88x31s&lt;/span&gt;
&lt;span&gt;// @match        *://*/*&lt;/span&gt;
&lt;span&gt;// @run-at       document-idle&lt;/span&gt;
&lt;span&gt;// ==/UserScript==&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;document&lt;span&gt;.&lt;/span&gt;&lt;span&gt;querySelectorAll&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;img&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;img&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;const&lt;/span&gt; &lt;span&gt;pixelate&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;img&lt;span&gt;.&lt;/span&gt;naturalWidth &lt;span&gt;===&lt;/span&gt; &lt;span&gt;88&lt;/span&gt; &lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt; img&lt;span&gt;.&lt;/span&gt;naturalHeight &lt;span&gt;===&lt;/span&gt; &lt;span&gt;31&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
img&lt;span&gt;.&lt;/span&gt;style&lt;span&gt;.&lt;/span&gt;imageRendering &lt;span&gt;=&lt;/span&gt; &lt;span&gt;&quot;pixelated&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
img&lt;span&gt;.&lt;/span&gt;complete &lt;span&gt;?&lt;/span&gt; &lt;span&gt;pixelate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;:&lt;/span&gt; img&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addEventListener&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;load&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; pixelate&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now properly-attributed 88x31 images will always appear nice and sharp, everywhere on the web, including but not limited to the ones in the footer of my website (though they already have the &lt;em&gt;correct&lt;/em&gt; &lt;code&gt;image-rendering&lt;/code&gt;)!&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/fresh-pixels/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/new-year-new-server-2/</id>
		<link href="https://chrisburnell.com/article/new-year-new-server-2/" />
		<title>New Year, New Server 2: Electric Boogaloo</title>
		<published>2026-05-06T18:52:16-03:00</published>
		<publishedFriendly>6 May 2026</publishedFriendly>
		<updated>2026-05-06T18:52:16-03:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>I got to really put my recently-practised and newly-learned system administrator skills to the test again, mere months after my my last update about migrating the server that hosts my websites. Why’s that, you ask? Because the server host that I switched to has been a major disappointment.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;I got to really put my recently-practised and newly-learned system administrator skills to the test again, mere months after my my last update about migrating the server that hosts my websites. Why’s that, you ask? Because the server host that I switched to has been a major disappointment.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;To cut a long story short—&lt;em&gt;although, I never seem to be able to tell short stories&lt;/em&gt;—the server host that I switched to at the end of last year employs deceptive pricing tactics.&lt;/p&gt;
&lt;p&gt;&lt;q&gt;Advertise price &lt;code&gt;A&lt;/code&gt;, but deliver price &lt;code&gt;A × 1.5&lt;/code&gt; after 3 months&lt;/q&gt; type of stuff.&lt;/p&gt;
&lt;p&gt;And if that wasn’t bad enough, I’ve also been having &lt;em&gt;horrendous&lt;/em&gt; issues with establishing and maintaining connections to the server. I have lost track of how many times this website’s scheduled and new commit CI workflows failed to sync newly-built files to my server, seemingly at random times and intervals. Checking the logs would reveal that CI (from multiple sources) wouldn’t even be &lt;em&gt;reaching&lt;/em&gt; my server.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Just accept the connection, damn it!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Enough was enough.&lt;/p&gt;
&lt;p&gt;I got a new server. It’s actually got even better specs for the same price as I was paying, and it’s hosted in Finland instead of the US too! I went scouring through the terminal history on my scorned server and checked through all the places that I was &lt;s&gt;working&lt;/s&gt; playing in and have migrated about 95% of everything! Only a few services and bits and bobs remain to be sifted through.&lt;/p&gt;
&lt;p&gt;It was also a fun learning experience, as I decided to use &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; this time around to segment the different pieces of software I use to power my &lt;a href=&quot;/projects/#self-hosted&quot;&gt;self-hosted stuff&lt;/a&gt;. I had everything running on &lt;q&gt;bare metal&lt;/q&gt; before and felt like I had a decent grasp of how (at least) my setup worked, but jumped at the opportunity to clean things up and learn something new.&lt;/p&gt;
&lt;p&gt;Because I spent so much time learning what I was &lt;em&gt;actually&lt;/em&gt; doing last migration, this one went really smoothly. Things were in places that I expected them to be, I had put effort into organising things, and I was able to reach &lt;em&gt;real&lt;/em&gt; deep and pull out memories of the migration from four months ago. I’m pretty confident I’ll be able to pull everything that would be missed from my scorned server before it’s decommissioned at the end of this month.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cue a post from me in June lamenting tremendous data loss…&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It was great to watch the sparklines on my uptime tracker shoot downward as I migrated my different websites. Across the board I saw response times to uptime pings decrease by ~10×! So far so good!&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/new-year-new-server-2/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/unusual-rotations-2026-03/</id>
		<link href="https://chrisburnell.com/article/unusual-rotations-2026-03/" />
		<title>Unusual Rotations (March 2026): Baroque</title>
		<published>2026-03-01T22:23:11+00:00</published>
		<publishedFriendly>1 March 2026</publishedFriendly>
		<updated>2026-03-01T22:23:11+00:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Reflecting on February and looking ahead to March’s genre(s), Baroque.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Reflecting on February and looking ahead to March’s genre(s), Baroque.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;h2&gt;February: Vaporwave (in review)&lt;/h2&gt;
&lt;p&gt;Unfortunately, February was a difficult month, as my family and I went through the loss of a family member. As a result, I wasn’t in a particularly adventurous mindset, and I fell back on familiar and comforting music rather than explore and learn more about music.&lt;/p&gt;
&lt;p&gt;In a way, it’s probably a good thing that I picked &lt;em&gt;Vaporwave&lt;/em&gt; for this month because I already listen to the genre regularly, so I don’t have an overwhelming sense of having &lt;q&gt;failed&lt;/q&gt; this little challenge already at the second month of twelve.&lt;/p&gt;
&lt;p&gt;I will probably end up taking a few hours during March to go back and find new stuff to listen to throughout the year and educate myself further on the (frankly) complex history of this scene and its lineage.&lt;/p&gt;
&lt;p&gt;All that being said, &lt;a href=&quot;https://isitbandcampfriday.com/&quot;&gt;Bandcamp Friday&lt;/a&gt; took place on the 6&lt;sup&gt;th&lt;/sup&gt; of this month, so I took advantage of the event to purchase a number of fun Vaporwave albums. I haven’t had the opportunity to properly go through them all (yet), but the album &lt;a href=&quot;https://slowerpace.bandcamp.com/album/encardia-99&quot;&gt;ENCARDIA &#39;99&lt;/a&gt; by &lt;a href=&quot;https://slowerpace.bandcamp.com&quot;&gt;slowerpace &lt;span lang=&quot;ja&quot;&gt;音楽&lt;/span&gt;&lt;/a&gt; was a stand-out for me not just because it so strongly epitomises the Vaporwave sound, but also because it sounds as if someone translated the &lt;a href=&quot;https://archive.org/details/MSEncarta99&quot;&gt;Encarta 99 Encyclopedia&lt;/a&gt; directly into Vaporwave music, with amazing track titles like &lt;em&gt;LEARNING TIME&lt;/em&gt; and &lt;em&gt;FORCES OF NATURE&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Vaporwave, a short history&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;… at least, as told by me. I might get some stuff wrong, but I have no interest in having debates about it—feel free to send me corrections, if you want. I might read &#39;em.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As far as I understand, like most genres of music, the &lt;q&gt;origin&lt;/q&gt; is both difficult and contentious to pinpoint. By and large, music changes through evolution, and to gaze at the timeframe of a given genre &lt;q&gt;birth&lt;/q&gt; would show a blurry, watercolour gradient of hues and tones. Sometimes you can maybe discern a shape in the wash of colours (these are the artists/albums/tracks that &lt;em&gt;really&lt;/em&gt; pushed the needle), but more often than not, there is no pinpoint that definitively marks the &lt;em&gt;start&lt;/em&gt; of a new genre of music.&lt;/p&gt;
&lt;p&gt;When it comes to Vaporwave, there is a &lt;strong&gt;strong&lt;/strong&gt; case to be made that its origins are too murky to call a start time on, but there’s an &lt;strong&gt;equally strong&lt;/strong&gt; case to be made for pinpointing &lt;q&gt;the start of Vaporwave as we know it&lt;/q&gt;:&lt;/p&gt;
&lt;p&gt;In the late 2000s, as the Internet matured (the Internet itself, not its denizens &lt;span&gt;lol&lt;/span&gt;) towards a new decade, there were a few genres like chillwave and &lt;abbr title=&quot;hypnogogic pop&quot;&gt;h-pop&lt;/abbr&gt; that were already using retro sounds, lo-fi aesthetics, and playing on nostalgia and a wistfulness for a half-remembered past.&lt;/p&gt;
&lt;p&gt;It was out of this primordial soup that Vaporwave grew. One of the key moments in this early time was in October of 2011 when &lt;a href=&quot;https://jamesferraroarchive.bandcamp.com&quot;&gt;James Ferraro&lt;/a&gt; released his album, &lt;a href=&quot;https://jamesferraroarchive.bandcamp.com/album/far-side-virtual&quot;&gt;Far Side Virtual&lt;/a&gt;. In it, James Ferraro masterfully blends ringtones, elevator music, and the &lt;q&gt;sound&lt;/q&gt; of corporate technology and techno-optimism from the 80s, 90s, and early 2000s to evoke an uncanny dreamscape of consumerism and overwhelming nostalgia (as a kid of the 90s, at least).&lt;/p&gt;
&lt;p&gt;Unbeknownst to the world, as the genre bubbled slowly to life in underground, indie circles, the artists that were pushing the envelope in this scene were creating a &lt;em&gt;supersaturated solution&lt;/em&gt;. All the elements were there, in suspension, just waiting for the right conditions.&lt;/p&gt;
&lt;p&gt;On the 9&lt;sup&gt;th&lt;/sup&gt; of December, 2011, &lt;a href=&quot;https://vektroid.bandcamp.com&quot;&gt;Vektroid (as Macintosh Plus)&lt;/a&gt; released &lt;a href=&quot;https://vektroid.bandcamp.com/album/floral-shoppe&quot;&gt;Floral Shoppe&lt;/a&gt;, crystallising &lt;em&gt;Vaporwave&lt;/em&gt; in these underground circles, and, in a way, helped to define the &lt;span lang=&quot;fr&quot;&gt;je ne sais quoi&lt;/span&gt; that makes up what Vaporwave &lt;em&gt;is&lt;/em&gt;: 80s/90s Japanese city pop, corporate &lt;abbr title=&quot;branded instrumental music, elevator music&quot;&gt;muzak&lt;/abbr&gt;, lo-fi and chopped and screwed samples, and subtly-critical or ironic &lt;q&gt;sounds&lt;/q&gt; of late stage capitalism.&lt;/p&gt;
&lt;p&gt;This is what gives Vaporwave its interesting but slightly-eerie quality: a world that was &lt;em&gt;sold&lt;/em&gt; to us, but refracted through the uncynical, wide-eyed wonder of childhood, before we knew enough to be critical, when everything just seemed so shiny and glossy and exciting and &lt;em&gt;new&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Of course, nothing happens in a vacuum, and the Internet at large quickly caught onto this new but nostalgic genre of music. Maybe the conditions were &lt;em&gt;just right&lt;/em&gt;, because it exploded in popularity throughout 2012, and I think this probably has a lot to do with how &lt;abbr title=&quot;how easily something can be made into a meme&quot;&gt;memeable&lt;/abbr&gt; the Vaporwave aesthetic was and that the nostalgia factor of Vaporwave is targeted at the demographic of people who are more likely to make memes about things in the first place.&lt;/p&gt;
&lt;p&gt;From there, genres and sub-genres and sub-sub-genres (that some would argue are genres unto themselves, thank you very much) would grow and blossom through their own scenes and wider circles that were developing.&lt;/p&gt;
&lt;p&gt;There are far too many genres that were born from this time and from very similar origins for me to even name, and it’s been interesting to see and hear how Vaporwave has evolved and splintered in the ~14 years since &lt;em&gt;Far Side Virtual&lt;/em&gt; and &lt;em&gt;Floral Shoppe&lt;/em&gt; came out.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;March: Baroque&lt;/h2&gt;
&lt;p&gt;I spent a lot of my youth learning piano, mostly baroque and classical pieces, and have been trying to pick it back up as an adult. My parents are both big fans of these genres, and I’ve been very familiar throughout my life (as a result), so this month, again, will probably be more about the depth of my exploration rather than breadth.&lt;/p&gt;
&lt;p&gt;I’d really love to get a stronger understanding of what defines these genres (usually lumped together under the umbrella of &lt;q&gt;classical music&lt;/q&gt;), what kind of influence history had on this music, and deep dive on some of my favourite aritsts/composers of these periods.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I’m definitely going to be listening to and playing a lot of Beethoven this month!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As always, if you have any ideas, thoughts, recommendations for this month or future ones, hit me up!&lt;/p&gt;
&lt;blockquote&gt;
    &lt;p&gt;It&#39;s all right here in my noodle. The rest is just scribbling. Scribbling and bibbling, bibbling and scribbling.&lt;/p&gt;
    &lt;cite&gt;Mozart (from the movie, &lt;a href=&quot;https://app.trakt.tv/movies/amadeus-1984&quot; rel=&quot;external noopener&quot;&gt;Amadeus&lt;/a&gt;)&lt;/cite&gt;
&lt;/blockquote&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;unusual-rotations&quot;&gt;
	&lt;p&gt;This post is part of &lt;a href=&quot;/tag/unusualrotations2026/&quot;&gt;Unusual Rotations 2026&lt;/a&gt;, a year-long project to immerse myself in 12 different musical genres that aren’t in my &lt;q&gt;usual&lt;/q&gt; rotation over the course of a year, one genre of focus per month, in an effort to expand the horizons of my musical tastes, learn more about how genres have evolved and grown over time, and expose myself to a rich history of music that I might have otherwise overlooked!&lt;/p&gt;
	&lt;ol&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-01/&quot;&gt;January: Grunge&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-02/&quot;&gt;February: Vaporwave&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-03/&quot;&gt;March: Baroque&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
	&lt;p&gt;More to come…&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/unusual-rotations-2026-03/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/unusual-rotations-2026-02/</id>
		<link href="https://chrisburnell.com/article/unusual-rotations-2026-02/" />
		<title>Unusual Rotations (February 2026): Vaporwave</title>
		<published>2026-02-01T21:50:47-04:00</published>
		<publishedFriendly>1 February 2026</publishedFriendly>
		<updated>2026-02-01T21:50:47-04:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Reflecting on listening to Grunge throughout January and planning February’s genre, Vaporwave.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Reflecting on listening to Grunge throughout January and planning February’s genre, Vaporwave.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;h2&gt;January: Grunge&lt;/h2&gt;
&lt;p&gt;On the whole, I really enjoyed exploring grunge more this month! There were some classic, quintessential tracks in there that I was already pretty intimately aware of, but it was nostalgic and it always rules to listen to great music you haven’t heard before.&lt;/p&gt;
&lt;p&gt;Although I &lt;em&gt;did&lt;/em&gt; listen to a smattering of &lt;span&gt;&lt;q&gt;big music’s&lt;/q&gt;&lt;/span&gt; &lt;em&gt;Grunge&lt;/em&gt; playlists (e.g. &lt;a href=&quot;https://music.youtube.com/playlist?list=RDCLAK5uy_kQDX7ciH8Pm8h48FWNLv5suF7U6abRhU4&quot;&gt;The Grunge Era on YouTube Music&lt;/a&gt;) and sampled through some &lt;q&gt;top 50 albums of all time&lt;/q&gt; lists (e.g. &lt;a href=&quot;https://www.rollingstone.com/music/music-lists/50-greatest-grunge-albums-798851/&quot;&gt;50 Greatest Grunge Albums by Rolling Stone&lt;/a&gt;), I think I let my own personal taste really take the reins this month. Because I ended up really enjoying so much of it, it was hard to stop listening to artists and albums once I put them on! Even though I don’t think it was necessarily a mistake, I’m going to try to cast a wider net going forward and absorb &lt;em&gt;more&lt;/em&gt; music, rather than latch onto the first things that prick up my ears.&lt;/p&gt;
&lt;p&gt;I want to guess that I listened to &lt;em&gt;at least&lt;/em&gt; 100 hours of Grunge across January, and I captured &lt;a href=&quot;/music/&quot;&gt;10 albums on my Music Reviews page&lt;/a&gt; that really stood out to me. I don’t know whether it’s a testament to just how good these bands are at grunge, or just the pervasive nature of &lt;em&gt;popularity&lt;/em&gt;, but most of them are the well-known heavy-hitters of the grunge world.&lt;/p&gt;
&lt;p&gt;In no particular order, here are a few of my favourites from this month:&lt;/p&gt;
&lt;div&gt;
&lt;article&gt;									&lt;a href=&quot;/music/jar-of-flies/&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;						&lt;picture&gt;								&lt;source type=&quot;image/webp&quot; srcset=&quot;/images/built/jar-of-flies.webp&quot;&gt;				&lt;img src=&quot;/images/built/jar-of-flies.jpeg&quot; alt=&quot;Art for Jar of Flies&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;			&lt;/picture&gt;							&lt;/a&gt;							&lt;h1&gt;							&lt;a href=&quot;/music/jar-of-flies/&quot;&gt;							Jar of Flies							&lt;/a&gt;					&lt;/h1&gt;									&lt;div&gt;									&lt;a href=&quot;https://www.last.fm/music/Alice+in+Chains&quot; rel=&quot;external noopener&quot;&gt;Alice in Chains&lt;/a&gt;													&lt;small&gt;(&lt;time datetime=&quot;1994-01-25T12:00:00+00:00&quot;&gt;1994&lt;/time&gt;)&lt;/small&gt;							&lt;/div&gt;							&lt;div&gt;									&lt;data value=&quot;4.25&quot; title=&quot;4.25 out of 5&quot;&gt; &lt;/data&gt;					&lt;strong&gt;4.25/5&lt;/strong&gt;					&lt;data value=&quot;0&quot; hidden=&quot;&quot;&gt;0&lt;/data&gt;					&lt;data value=&quot;5&quot; hidden=&quot;&quot;&gt;5&lt;/data&gt;							&lt;/div&gt;							&lt;time datetime=&quot;2026-01-16T09:22:57-04:00&quot; hidden=&quot;&quot;&gt;Friday, 16 January 2026&lt;/time&gt;										&lt;data value=&quot;https://album.link/s/4FCoFSNIFhK36holxHWCnc&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;							&lt;data value=&quot;/music/&quot; hidden=&quot;&quot;&gt;music&lt;/data&gt;							&lt;data value=&quot;/music/jar-of-flies/&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;				&lt;data value=&quot;/&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;	&lt;/article&gt;&lt;article&gt;									&lt;a href=&quot;/music/in-utero/&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;						&lt;picture&gt;								&lt;source type=&quot;image/webp&quot; srcset=&quot;/images/built/in-utero.webp&quot;&gt;				&lt;img src=&quot;/images/built/in-utero.jpeg&quot; alt=&quot;Art for In Utero&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;			&lt;/picture&gt;							&lt;/a&gt;							&lt;h1&gt;							&lt;a href=&quot;/music/in-utero/&quot;&gt;							In Utero							&lt;/a&gt;					&lt;/h1&gt;									&lt;div&gt;									&lt;a href=&quot;https://www.last.fm/music/Nirvana&quot; rel=&quot;external noopener&quot;&gt;Nirvana&lt;/a&gt;													&lt;small&gt;(&lt;time datetime=&quot;1993-09-21T12:00:00+00:00&quot;&gt;1993&lt;/time&gt;)&lt;/small&gt;							&lt;/div&gt;							&lt;div&gt;									&lt;data value=&quot;4.25&quot; title=&quot;4.25 out of 5&quot;&gt; &lt;/data&gt;					&lt;strong&gt;4.25/5&lt;/strong&gt;					&lt;data value=&quot;0&quot; hidden=&quot;&quot;&gt;0&lt;/data&gt;					&lt;data value=&quot;5&quot; hidden=&quot;&quot;&gt;5&lt;/data&gt;							&lt;/div&gt;							&lt;time datetime=&quot;2026-01-16T20:40:57-04:00&quot; hidden=&quot;&quot;&gt;Friday, 16 January 2026&lt;/time&gt;										&lt;data value=&quot;https://album.link/s/7wOOA7l306K8HfBKfPoafr&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;							&lt;data value=&quot;/music/&quot; hidden=&quot;&quot;&gt;music&lt;/data&gt;							&lt;data value=&quot;/music/in-utero/&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;				&lt;data value=&quot;/&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;	&lt;/article&gt;&lt;article&gt;									&lt;a href=&quot;/music/superunknown/&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;						&lt;picture&gt;								&lt;source type=&quot;image/webp&quot; srcset=&quot;/images/built/superunknown.webp&quot;&gt;				&lt;img src=&quot;/images/built/superunknown.jpeg&quot; alt=&quot;Art for Superunknown&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;			&lt;/picture&gt;							&lt;/a&gt;							&lt;h1&gt;							&lt;a href=&quot;/music/superunknown/&quot;&gt;							Superunknown							&lt;/a&gt;					&lt;/h1&gt;									&lt;div&gt;									&lt;a href=&quot;https://www.last.fm/music/Soundgarden&quot; rel=&quot;external noopener&quot;&gt;Soundgarden&lt;/a&gt;													&lt;small&gt;(&lt;time datetime=&quot;1994-03-08T12:00:00+00:00&quot;&gt;1994&lt;/time&gt;)&lt;/small&gt;							&lt;/div&gt;							&lt;div&gt;									&lt;data value=&quot;4&quot; title=&quot;4 out of 5&quot;&gt; &lt;/data&gt;					&lt;strong&gt;4/5&lt;/strong&gt;					&lt;data value=&quot;0&quot; hidden=&quot;&quot;&gt;0&lt;/data&gt;					&lt;data value=&quot;5&quot; hidden=&quot;&quot;&gt;5&lt;/data&gt;							&lt;/div&gt;							&lt;time datetime=&quot;2026-01-19T01:25:25-04:00&quot; hidden=&quot;&quot;&gt;Monday, 19 January 2026&lt;/time&gt;										&lt;data value=&quot;https://album.link/s/4SPc25NzdqOQt2IX4JDLUv&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;							&lt;data value=&quot;/music/&quot; hidden=&quot;&quot;&gt;music&lt;/data&gt;							&lt;data value=&quot;/music/superunknown/&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;				&lt;data value=&quot;/&quot; hidden=&quot;&quot;&gt;&lt;/data&gt;	&lt;/article&gt;
&lt;/div&gt;
&lt;p&gt;I also received some much-appreciated recommendations from a handful of lovely folks: &lt;a href=&quot;https://mastodon.social/@ellikerjames&quot;&gt;James Elliker&lt;/a&gt; recommended a whole &lt;a href=&quot;https://mastodon.social/@ellikerjames/115859716847721196&quot;&gt;personalised list of top 50 albums&lt;/a&gt; which was incredibly fruitful; &lt;a href=&quot;https://knowler.dev/&quot;&gt;Nathan Knowler&lt;/a&gt; recommended &lt;a href=&quot;https://bsky.app/profile/knowler.dev/post/3mbtyovsbc22v&quot;&gt;Superheaven’s album from last year&lt;/a&gt; which helped me settle into the driver’s seat of a nomad in the grunge world; and &lt;a href=&quot;https://adactio.com&quot;&gt;Jeremy Keith&lt;/a&gt; recommended I check out &lt;a href=&quot;https://adactio.com/notes/22346&quot;&gt;Babes in Toyland&lt;/a&gt; (two very sick music videos). Thanks all!&lt;/p&gt;
&lt;p&gt;I suspect I’m going to be juggling grunge through February as well, so don’t be surprised if a few albums slip onto my Music Reviews page over the next… well, probably over the course of this year!&lt;/p&gt;
&lt;p&gt;I’m going to take a quick moment to pay myself on the back for taking on this idea or project or whatever you want to call it. It has been really fun and I encourage you to join! Reject the Gregorians and start your own exploration into new and semi-familiar genres whenever you want!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;On with February!&lt;/p&gt;
&lt;h2&gt;Vaporwave&lt;/h2&gt;
&lt;p&gt;To say that I’m new to this genre would be… a complete and utter lie! I got really into it probably around a decade ago, and I’ve been listening to it pretty steadily ever since.&lt;/p&gt;
&lt;p&gt;With that being said, my exploration of the genre has been &lt;em&gt;pretty&lt;/em&gt; limited. As with my month focusing on grunge, I’ve tended to be drawn to depth rather than breadth. I’m hoping by &lt;span&gt;cheating&lt;/span&gt; with a rather familiar genre this early on will help me get into exploring more. Pausing along the way is fine—pun ~not~ intended—but covering as much ground as I can over the course of this short month is my goal!&lt;/p&gt;
&lt;p&gt;I imagine I’ll be fleshing out my Music Review section with some old favourites that I never added for whatever reason, but I’m hoping to find myself immersed in that wonderful, euphoric feeling of discovering something new that electrifies you once again.&lt;/p&gt;
&lt;p&gt;’Til March!&lt;/p&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;unusual-rotations&quot;&gt;
	&lt;p&gt;This post is part of &lt;a href=&quot;/tag/unusualrotations2026/&quot;&gt;Unusual Rotations 2026&lt;/a&gt;, a year-long project to immerse myself in 12 different musical genres that aren’t in my &lt;q&gt;usual&lt;/q&gt; rotation over the course of a year, one genre of focus per month, in an effort to expand the horizons of my musical tastes, learn more about how genres have evolved and grown over time, and expose myself to a rich history of music that I might have otherwise overlooked!&lt;/p&gt;
	&lt;ol&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-01/&quot;&gt;January: Grunge&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-02/&quot;&gt;February: Vaporwave&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-03/&quot;&gt;March: Baroque&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
	&lt;p&gt;More to come…&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/unusual-rotations-2026-02/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/unusual-rotations-2026-01/</id>
		<link href="https://chrisburnell.com/article/unusual-rotations-2026-01/" />
		<title>Unusual Rotations (January 2026): Grunge</title>
		<published>2026-01-06T19:57:37-04:00</published>
		<publishedFriendly>6 January 2026</publishedFriendly>
		<updated>2026-01-06T19:57:37-04:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>I&#39;ve come up with a fun, new project to work on over the course of this year, and maybe you’ll join me!</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;I&#39;ve come up with a fun, new project to work on over the course of this year, and maybe you’ll join me!&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Towards the end of 2025, I came up with this idea to expand the horizons of my musical tastes.&lt;/p&gt;
&lt;p&gt;I’ve always had quite a broad taste in music, I think. When I was growing up, I would tell people, &lt;q&gt;I listen to everything except jazz and country.&lt;/q&gt; I didn’t &lt;em&gt;really&lt;/em&gt; know what I was talking about, and definitely listen to all sorts of jazz and country music these days, so is it fair to say that I listen to everything?&lt;/p&gt;
&lt;p&gt;Maybe! But I’m going to try and find out.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Over the course of 2026, I’m going to be dedicate each month to a genre of music that’s either way outside the realm of what I normally listen to or is a genre that I’ve been tiptoeing around and deserves more attention.&lt;/p&gt;
&lt;p&gt;I’ll be documenting the journey here, on my website, as something that I can reflect back on and might inspire someone else to try something new too!&lt;/p&gt;
&lt;p&gt;At the start of each new month, I’ll reflect on the previous month, maybe highlight some stand-out artists/albums/songs, touch on some historical stuff that intrigued me, and whatever else I take away from my exploration into that genre.&lt;/p&gt;
&lt;p&gt;This whole project is really a venture into the unknown. To be frank, I haven’t even thought much about &lt;em&gt;how&lt;/em&gt; I want to structure my research and listening, let alone if this project is a reasonable thing to consider doing in the first place. How much can I really learn about something as deep and as rich as an entire genre of music in just a month?&lt;/p&gt;
&lt;p&gt;The reality is: I can’t. But I don’t expect to, either. Reaching some ethereal finish line is not the point. On the contrary, the journey is the whole point! Imagine the sadness that would come with knowing you had already heard everything. To know that the feelings of sating one’s curiosity is behind me and that no surprises await would be a terrible condemnation to endure.&lt;/p&gt;
&lt;p&gt;I’m more concerned with having enough time each month to juggle spending time towards the genre of the month and continuing to listen to the previous genres I’ve explored that I’ll inevitably become obsessed with!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I know &lt;em&gt;way&lt;/em&gt; too many cool people with vast, sprawling, wildly different tastes in music, so I’m really looking forward to &lt;s&gt;hassling&lt;/s&gt; hearing from folks about their favourite genres. Educate me! What are &lt;em&gt;your&lt;/em&gt; favourite artists/albums/songs? I’ll check them out! Shoot me a message with a totally un-asked for braindump of the &lt;q&gt;lore&lt;/q&gt; of your favourite genre! Cause &lt;strong&gt;I’m askin’&lt;/strong&gt;, and I’ll read &lt;strong&gt;every single word&lt;/strong&gt; of it. What are the genre’s big hits? Hidden gems? Do &lt;em&gt;you&lt;/em&gt; make this kind of music? &lt;strong&gt;I WILL LISTEN TO IT.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And please, by all means, join me! Make your own list of 12 genres that you want to dive into or maybe the ones I’ll pick interest you already. But make sure you let me know! I’d love to go on this journey with you.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So, without further ado, &lt;em&gt;my&lt;/em&gt; genre for January 2026 is…&lt;/p&gt;
&lt;h2&gt;Grunge&lt;/h2&gt;
&lt;p&gt;Growing up in the 90s and 2000s, I’m a bit too young to have really caught the peak of the grunge wave (I think?). Regardless, my friend group in school was sort of tangentially into grunge, so this genre isn’t a particularly new sound for me.&lt;/p&gt;
&lt;p&gt;However, when I moved to Singapore in 2023, I had the opportunity to spend a lot more (in-person) time with my good friend, Raga, who’s a metalhead and huge fan of grunge. He (re-)opened my eyes to a lot of grunge that I hadn’t deliberately listened to in at least 15 years! Thinking about it now, I don’t really know why I let it fade out of rotation. I’ve been giving hip hop and drum and bass too much space! They’re getting set on the backburner for, at least, January, so I can concentrate on immersing myself in &lt;strong&gt;grunge&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Again, please do reach out if you join me on this journey &lt;strong&gt;and&lt;/strong&gt;/&lt;strong&gt;or&lt;/strong&gt; if you’re a fan of grunge yourself. Send me your recs!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Apologies to the neighbors.&lt;/em&gt;&lt;/p&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;unusual-rotations&quot;&gt;
	&lt;p&gt;This post is part of &lt;a href=&quot;/tag/unusualrotations2026/&quot;&gt;Unusual Rotations 2026&lt;/a&gt;, a year-long project to immerse myself in 12 different musical genres that aren’t in my &lt;q&gt;usual&lt;/q&gt; rotation over the course of a year, one genre of focus per month, in an effort to expand the horizons of my musical tastes, learn more about how genres have evolved and grown over time, and expose myself to a rich history of music that I might have otherwise overlooked!&lt;/p&gt;
	&lt;ol&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-01/&quot;&gt;January: Grunge&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-02/&quot;&gt;February: Vaporwave&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;/article/unusual-rotations-2026-03/&quot;&gt;March: Baroque&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
	&lt;p&gt;More to come…&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/unusual-rotations-2026-01/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/new-year-new-server/</id>
		<link href="https://chrisburnell.com/article/new-year-new-server/" />
		<title>New Year, New Server</title>
		<published>2026-01-06T15:37:40-04:00</published>
		<publishedFriendly>6 January 2026</publishedFriendly>
		<updated>2026-01-06T15:37:40-04:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Over the last two weeks, I’ve been toiling away on the ugly underside of this website: the server. It powers and hosts all the data for this and my many other websites, and I thought as we say goodbye to 2025 and welcome in 2026, I’d reminisce on the history of my website.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Over the last two weeks, I’ve been toiling away on the ugly underside of this website: the server. It powers and hosts all the data for this and my many other websites, and I thought as we say goodbye to 2025 and welcome in 2026, I’d reminisce on the history of my website.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;h2&gt;In the beginning…&lt;/h2&gt;
&lt;p&gt;When I first started publishing on my own domain on the web (under my own name, at least, I’ve been &lt;em&gt;webmastering&lt;/em&gt; since 2005), I really wanted a WordPress blog, which I thought was the &lt;strong&gt;coolest&lt;/strong&gt; thing you could possibly own in 2008. (Things have changed, to say the least!) Somehow, I managed to get one running on a shared hosting provider, and suddenly it felt like a part of &lt;em&gt;me&lt;/em&gt; was on the Internet now, or at least some kind of extension of myself.&lt;/p&gt;
&lt;p&gt;That shared hosting dashboard (&lt;em&gt;cPanel&lt;/em&gt;) kept my handful of websites going from 2008 until 2014, a &lt;strong&gt;solid&lt;/strong&gt; 6 years of service, but it didn’t come without friction.&lt;/p&gt;
&lt;p&gt;Unfortunately, the style of the dashboard that is/was common with these types of sharing hosting services feels like it was constructed to be some impossibly-capable tool-belt that extends ad infinitum, but is thrust around you in the vain hope that the little &lt;q&gt;One size fits all&lt;/q&gt; label will answer your many questions and provide some level of comfort amidst your utter confusion and horror.&lt;/p&gt;
&lt;p&gt;I’m sure this is &lt;em&gt;exactly&lt;/em&gt; what other folks expect and want of their web hosting dashboard, but this isn’t something that I can effectively learn how to use. I just end up feeling like my grasp is slipping on the surface of a very large, very well-maintained planet. No shade if this stuff is your jam!&lt;/p&gt;
&lt;p&gt;Somehow (this isn’t the last time I’ll use that word), I managed to work through this inadequate/over-adequate tooling for years and years, but my skills as a developer eventually caught up with my needs of control over the backend of my websites. I remember starting to &lt;em&gt;really&lt;/em&gt; detest having to wade through all the pre-installed &lt;strong&gt;junk&lt;/strong&gt; in my shared hosting dashboard, but not being nearly interested enough in the dashboard itself to do more than some basic modifications to the UI.&lt;/p&gt;
&lt;h2&gt;Taking the reins&lt;/h2&gt;
&lt;p&gt;By 2014, my role at work and my personal projects had already begun demanding some actual know-how with the command line, and as my familiarity with Node.js and bash grew, it became obvious that I wasn’t destined to chain myself to my shared hosting dashboard forever.&lt;/p&gt;
&lt;p&gt;So I decided do something about it.&lt;/p&gt;
&lt;p&gt;As someone who &lt;s&gt;spent&lt;/s&gt; still spends &lt;em&gt;tonnes&lt;/em&gt; of my personal time in this &lt;q&gt;space&lt;/q&gt;, I have come to realise that the moments where I really enjoy developing and learning are when the virtual space I’m in feels &lt;strong&gt;comfy and familiar&lt;/strong&gt;. &lt;q&gt;Flow state&lt;/q&gt; and all that jazz.&lt;/p&gt;
&lt;p&gt;To me, this is like the difference between following maps and following landmarks and paths your feet have tread a hundred times before. Both methods get you to the same place, but I want &lt;em&gt;my&lt;/em&gt; steps to be &lt;em&gt;my own&lt;/em&gt;, not the steps that have been determined for me by someone or something else.&lt;/p&gt;
&lt;p&gt;This probably comes from a ~decade of obsessing over the minute details of my website to the point of exhaustion, moving on to modifying and customising my Android phone to a ridiculous degree until it feels &lt;em&gt;just right&lt;/em&gt;, and looking for something else to dive into and learn about and absorb myself in and transform it into something that feels homey and familiar only to find my itch unscratched.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So it’s been nearly &lt;em&gt;twelve&lt;/em&gt; years (4,348 days, to be exact) since I first installed the &lt;abbr title=&quot;virtual private server, an isolated, virtual environment on a physical server&quot;&gt;VPS&lt;/abbr&gt; that succeeded the shared hosting that was the home for &lt;code&gt;chrisburnell.com&lt;/code&gt; et al. for so many years.&lt;/p&gt;
&lt;p&gt;This came with a &lt;em&gt;steep&lt;/em&gt; learning curve, but each step forward brought with it deep lungfuls of fresh air. I got to learn first-hand where the gaps in my knowledge and skills were from years of depending on janky web UIs to manage databases and oversee processes.&lt;/p&gt;
&lt;p&gt;I’m super fortunate and grateful to be friends with great people like &lt;a href=&quot;https://www.linkedin.com/in/hank-woods/&quot;&gt;Hank Woods&lt;/a&gt; and &lt;a href=&quot;https://uk.linkedin.com/in/callum-loh-717b66224&quot;&gt;Callum Loh&lt;/a&gt; who guided and taught me &lt;em&gt;boatloads&lt;/em&gt; throughout many of those early, hands-on hours with my new server.&lt;/p&gt;
&lt;p&gt;That’s not to say that I didn’t go off and make a shambles of everything when I wasn’t supervised: configuration files in the &lt;code&gt;tmp&lt;/code&gt; directory, SSHing directly in as root with a far-too-trivial password, binaries where configuration is supposed to go… Name a mistake and I probably made it.&lt;/p&gt;
&lt;p&gt;But, somehow (again?), I &lt;em&gt;MacGyvered&lt;/em&gt; together a mountain out of a molehill, and was finally at a level of control over my website (front and back) that felt like I could work with. There were times it outpaced me or felt like I couldn’t get it to do what I wanted, but without that veil between me and the systems I was trying to interact with, I was able to explore and learn so much, achieve new things that weren’t possible for me before (let alone conceive of), and again, make the environment that I was spending &lt;em&gt;so much time in&lt;/em&gt; feel like a &lt;em&gt;home&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Clueless&lt;/h2&gt;
&lt;p&gt;Over some quiet evenings this last December, a old, familiar feeling started to creep back into my mind:&lt;/p&gt;
&lt;p&gt;Sure, I’m not making the &lt;em&gt;total&lt;/em&gt; newbie mistakes anymore, or at least not that often. I can edit and find the stuff that makes my server run. I can handle nginx configuration, I have &lt;em&gt;enough&lt;/em&gt; of a handle on firewall rules and reverse proxies exposing services to the web, but if anything goes wrong…&lt;/p&gt;
&lt;p&gt;Yeah, I ended up creating a grotesque sibling for the shared hosting dashboard that I hated so much, but this behemoth was of my own making… &lt;em&gt;*facepalm*&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The difference with &lt;em&gt;this&lt;/em&gt; behemoth was that when things went wrong, there wasn’t a customer support chat for me to jump into and get things resolved for me. The responsibility was mine and mine alone, and I certainly threw down the gauntlet at my own feet.&lt;/p&gt;
&lt;p&gt;I must have been feeling especially self-sabotaging when I decided I wanted to add hosting my own Mastodon instance to my skillset in 2022. It’s a real testament to their documentation that &lt;em&gt;I&lt;/em&gt; was able to get things running, but I figured it out and have kept it ticking along ever since, but this is where my old VPS’s age really began to show.&lt;/p&gt;
&lt;p&gt;After over a decade of mucking around and leaving grease stains on all the server’s good furniture, the toll on the server was showing. Running 3+ database management systems, pumping the traffic of 5+ domains and dozens of subdomain projects through shoddily-configured web servers, and an &lt;q&gt;interesting&lt;/q&gt; mishmash of who-knows how many iterations of different projects in different languages written at very different stages of my career was enough, but supporting a Mastodon instance on top of that meant that the server’s memory was running like a lump of molten lava pretty much nonstop.&lt;/p&gt;
&lt;p&gt;Not good.&lt;/p&gt;
&lt;h2&gt;It’s alive!&lt;/h2&gt;
&lt;p&gt;So I began researching. Maybe I could just upgrade the server’s capabilities and things would be fine?&lt;/p&gt;
&lt;p&gt;But I couldn’t shake that feeling of how great it would feel to start fresh and take the time to actually learn what I’m doing to get things right from the start. At the very least, even if I got things wrong, my attitude this time would be to understand and learn, so I figured I would be capable of understanding &lt;em&gt;why&lt;/em&gt; it was wrong.&lt;/p&gt;
&lt;p&gt;Rather than chasing search queries about my issue for hours, looking for the silver bullet to copy and paste that will &lt;q&gt;just&lt;/q&gt; fix things, my plan was to actually read logs and man pages. After all, associating patterns of strings in bash scripts and postgres commands with certain actions is only really one step removed from associating the &lt;em&gt;phpMyAdmin&lt;/em&gt; logo with the way that I used to interact with databases.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(Again, to each their own! I’d rather have you on the web with me than not, and I don’t hold any judgement towards how you get comfy and comfortable in your web space. This article’s about me, though!)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And that solidified it for me. This was happening.&lt;/p&gt;
&lt;p&gt;I began shopping around and discovered I could get a server for a comparable, competitive price that had twice the CPUs, memory, storage, and transfer capabilities of my old server. &lt;strong&gt;Lock it in.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So that’s what I’ve been up to for the last ~2 weeks: slowly trickling stuff across from my old VPS to the new. I started with the straightforward static sites and then moved onto the more complex ones, taking things really slowly to make sure I understood every line of config I authored and looking for ways to DRY things out just enough to build a sweet library of my own reusable stuff while not making it impossible to revisit this stuff in a year’s time and have to re-learn how hundreds of moving pieces fit together. A careful and measured approach.&lt;/p&gt;
&lt;p&gt;And I’m &lt;em&gt;very&lt;/em&gt; pleased to say that my old server is just about ready to be decommissioned! Everything important (read: that I can remember exists) has been ported over and the new server looks to be in great health after a week of stability.&lt;/p&gt;
&lt;p&gt;I still need to go through things on the old server with a fine-toothed comb &lt;em&gt;once&lt;/em&gt; more. There’s so many old and unimportant one-off experiments that I’d like to keep just for the heck of it, but there’s also a lot of files that I can only assume were accidentally saved in the wrong location or moved haphazardly or for some other indecipherable reason. It’s funny, though, to think how much I probably confused myself in 2014!&lt;/p&gt;
&lt;p&gt;I was wandering around so naïvely back then, but it’s a fun and nostalgic experience to retrace the first steps I took on fresh earth twelve years ago; to see where my feet took me, what piqued my interest, what parts of the landscape I strayed from out of fear, what parts I let nature take its course out of deference, where I built lookouts and small homes to rest and read in.&lt;/p&gt;
&lt;p&gt;One day soon will be the last day I set foot in that space that I know so well, but I haven’t left the experience empty-handed.&lt;/p&gt;
&lt;p&gt;Now, I have a map. A map that has all my secret little paths, notes, warnings about &lt;q&gt;here be dragons&lt;/q&gt;, all the stuff, all the character that isn’t on the pages of the maps you can get off a shelf. It’s not a perfect map by any means—the corners are dog-earred; words, written in pen, have been scratched out; and, later on, eraser marks betray hidden mistakes in charcoal—this map is far from finished.&lt;/p&gt;
&lt;p&gt;But this map that I made is my own.&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/new-year-new-server/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/color-scheming/</id>
		<link href="https://chrisburnell.com/article/color-scheming/" />
		<title>Color Scheming</title>
		<published>2025-10-24T12:01:00-03:00</published>
		<publishedFriendly>24 October 2025</publishedFriendly>
		<updated>2025-10-24T12:01:00-03:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>It’s been about a year and a half since I changed how colour schemes (i.e., light and dark themes) work on my website, and after reviewing and refactoring things again recently, I thought I would share how everything ties together and allows for different levels of control over colour schemes.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;It’s been about a year and a half since I changed how colour schemes (i.e., light and dark themes) work on my website, and after reviewing and refactoring things again recently, I thought I would share how everything ties together and allows for different levels of control over colour schemes.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;In this article, I’ll cover &lt;em&gt;how&lt;/em&gt; to implement a colour-scheming system, gain some understanding of how to control the colour scheme in different ways, and write some CSS that leverages the strengths of the language to build a hierarchy of colour scheme controls.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: We’re going to build this hierarchy of controls out of order, but we’ll wrap everything back around to honour its order by the end.&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;&lt;abbr title=&quot;Operating System&quot;&gt;OS&lt;/abbr&gt;/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr&gt;
&lt;h2 id=&quot;build&quot;&gt;Let’s build&lt;/h2&gt;
&lt;h3 id=&quot;part-1&quot;&gt;4. &lt;abbr title=&quot;Operating System&quot;&gt;OS&lt;/abbr&gt;/Browser-level Preference&lt;/h3&gt;
&lt;ol aria-hidden=&quot;true&quot;&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;OS/Browser-level Preference&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To begin with, we should make sure to include this &lt;code&gt;meta&lt;/code&gt; tag in the &lt;code&gt;head&lt;/code&gt; of our page(s). This &lt;q&gt;indicates a suggested [colour] scheme that user agents should use for a page&lt;/q&gt; (&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/color-scheme&quot;&gt;MDN&lt;/a&gt;).&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;content&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we need to indicate in our CSS what colour schemes we want to have available, and we can apply this to the document root (&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; in &lt;em&gt;most&lt;/em&gt; cases) and the cascade will apply the appropriate colour scheme to the entire document:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:root&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This, alone, allows us to write CSS that responds dynamically to the &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; for a light or dark colour scheme. Where colours are concerned in our CSS, we can use the &lt;code&gt;light-dark()&lt;/code&gt; function to hook into which of the two colour schemes is active and provide an appropriate colour for both conditions.&lt;/p&gt;
&lt;p&gt;Also, because we’ve written &lt;code&gt;light dark&lt;/code&gt;, we have indicated that where an &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; does not exist, we should default to the first value. This means that in the absense of all preferences and overrides, the default colour scheme will be the &lt;code&gt;light&lt;/code&gt; one. If we had instead written &lt;code&gt;dark light&lt;/code&gt;, the &lt;code&gt;dark&lt;/code&gt; colour scheme would be the default.&lt;/p&gt;
&lt;h3 id=&quot;part-2&quot;&gt;1 &amp;amp; 2. Element-level &amp;amp; Page-level Overrides&lt;/h3&gt;
&lt;ol aria-hidden=&quot;true&quot;&gt;
    &lt;li&gt;Element-level Override&lt;/li&gt;
    &lt;li&gt;Page-level Override&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;OS/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Next, let’s take care of Page-level and Element-level colour scheme overrides. The way I’ve chosen to do this is by creating classes for each colour scheme that can be appled to any element and use a specific colour scheme for itself and its children:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can apply these classes to the &lt;code&gt;html&lt;/code&gt; element to force an entire page to use a specific colour scheme:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, we might want a particular section of a page to always use a specific colour scheme, so we can apply the class to a wrapper element and allow the &lt;code&gt;color-scheme&lt;/code&gt; value to cascade to its children:&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;main&lt;/span&gt; &lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	...
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;main&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;part-3&quot;&gt;3. Site-level Preference&lt;/h3&gt;
&lt;ol aria-hidden=&quot;true&quot;&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Site-level Preference&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;OS/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The last part is unfortunately the most complex, so let’s dive in and flesh out how we can allow website visitors to override their &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; &lt;em&gt;without&lt;/em&gt; stepping on top of our &lt;em&gt;Page-level/Element-level Overrides&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To start with, I’m using &lt;a href=&quot;https://darn.es/&quot;&gt;David Darnes’&lt;/a&gt; web component, &lt;a href=&quot;https://github.com/daviddarnes/storage-form/&quot;&gt;&lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt;&lt;/a&gt;, to capture the &lt;em&gt;Site-level Preference&lt;/em&gt;. This works by wrapping a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; that contains a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;. The &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; web component listens for selection changes on the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value and saves those changes to local storage.&lt;/p&gt;
&lt;pre data-language=&quot;html&quot; data-language-friendly=&quot;HTML&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;storage-form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span&gt;autocomplete&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;off&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;select&lt;/span&gt; &lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;color-scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;optgroup&lt;/span&gt; &lt;span&gt;label&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;Select a colour scheme&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
				&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span&gt;selected&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;OS Default&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
				&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;light&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Light&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
				&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;option&lt;/span&gt; &lt;span&gt;value&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;dark&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Dark&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;option&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
			&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;optgroup&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
		&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;storage-form&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From then on, whenever the web component’s JavaScript finds the same &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; (matched by &lt;code&gt;name&lt;/code&gt; attribute) on subsequent page loads or on other pages, it will modify the selected &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; in the DOM to match the local storage value.&lt;/p&gt;
&lt;p&gt;This takes care of persistence of &lt;em&gt;Site-level Preferences&lt;/em&gt;. I cannot overstate how amazingly powerful this little web component is! I use it every time I need to manage some sort of &lt;q&gt;state&lt;/q&gt; on my website.&lt;/p&gt;
&lt;p&gt;What’s great about this approach is that we can leave &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; alone from here and continue using CSS to control and manage how we respond to different colour schemes. We can build selectors that match when a particular &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; is selected (i.e., &lt;code&gt;checked&lt;/code&gt;), and using the &lt;code&gt;:has()&lt;/code&gt; selector, we can then apply a specific colour scheme based on that selection:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So when the &lt;code&gt;light&lt;/code&gt; option has been selected, we are applying the light colour scheme to the document root, and vice versa for the &lt;code&gt;dark&lt;/code&gt; option.&lt;/p&gt;
&lt;h3 id=&quot;part-4&quot;&gt;A nod to performance&lt;/h3&gt;
&lt;p&gt;Before we can put everything together, there are some problems we need to address.&lt;/p&gt;
&lt;p&gt;Firstly, we need to think about &lt;em&gt;how&lt;/em&gt; we initiate the JavaScript that defines the &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; web component because until it is loaded, the &lt;em&gt;Site-level Preference&lt;/em&gt; that exists in local storage won’t have been mirrored onto the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; on the page. At present, we’re &lt;em&gt;relying&lt;/em&gt; on the value of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; to apply a &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This gives us some options and a choice to make.&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; instantiate the web component in the &lt;code&gt;head&lt;/code&gt; of our page(s) and be sure that by the time the HTML parser reaches our &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;, the browser will know what to do with it, and the correct colour scheme will be applied; however, this will block the parsing of HTML while the entirety of the web component’s JavaScript is being processed.&lt;/p&gt;
&lt;p&gt;We might think to defer the script or run it asynchronously, but no matter how we slice it—loading the JavaScript before the HTML or vice versa—we’re going to run into an unsightly problem. The effect will be more pronounced on slower devices and/or slower connections, but there &lt;em&gt;will&lt;/em&gt; be a period of time where some portion of HTML has been parsed and rendered &lt;em&gt;before&lt;/em&gt; the locally-stored colour scheme value has been applied to the HTML. Depending on how different in brightness the light and dark colour schemes are, this can result in an intense shift from light to dark or dark to light before and after the locally-stored colour scheme value is applied.&lt;/p&gt;
&lt;p&gt;What &lt;em&gt;I’ve&lt;/em&gt; done to solve this is to defer the loading of the JavaScript that initiates the web component and instead include a small snippet of (minified) JavaScript in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; that &lt;em&gt;is technically&lt;/em&gt; parser-blocking, but will reliably run (or fail) very quickly.&lt;/p&gt;
&lt;pre data-language=&quot;javascript&quot; data-language-friendly=&quot;JavaScript&quot;&gt;&lt;code&gt;&lt;span&gt;const&lt;/span&gt; &lt;span&gt;COLOR_SCHEME&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; localStorage&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;COLOR_SCHEME&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	document&lt;span&gt;.&lt;/span&gt;documentElement&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;data-color-scheme&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;COLOR_SCHEME&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;window&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addEventListener&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;load&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
document&lt;span&gt;.&lt;/span&gt;documentElement&lt;span&gt;.&lt;/span&gt;&lt;span&gt;removeAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;data-color-scheme&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;What this does is independently check the browser’s local storage for the same value that gets set by the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; in the &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; web component. &lt;em&gt;If&lt;/em&gt; a value is found, then it sets a data attribute on the document root. When the window has finished loading, this means that the &lt;code&gt;&amp;lt;storage-form&amp;gt;&lt;/code&gt; JavaScript has completed, so the data attribute on the document root gets removed, allowing the CSS selector based on the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value (which is now in parity with local storage) to once again take control.&lt;/p&gt;
&lt;p&gt;We can apply some further CSS that will apply the correct colour scheme during this &lt;q&gt;in-between&lt;/q&gt; state when the data attribute is present on the document root:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;[data-color-scheme=&quot;light&quot;]&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;span&gt;[data-color-scheme=&quot;dark&quot;]&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;part-5&quot;&gt;Review and Refactor&lt;/h3&gt;
&lt;p&gt;Let’s put all of our CSS together. We’ll combine our initial &lt;code&gt;:root&lt;/code&gt; declaration alongside two other declarations, one for each of two groups, selectors that should apply the light colour scheme and selectors that should apply the dark colour scheme.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span&gt;Warning!&lt;/span&gt; The CSS below is not the full solution! Keep reading below to learn about what we need to do to fix its problems.&lt;/em&gt;&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:root&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked),&lt;br&gt;
[data-color-scheme=&quot;light&quot;],&lt;br&gt;
.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked),&lt;br&gt;
[data-color-scheme=&quot;dark&quot;],&lt;br&gt;
.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, while this CSS does target the different parts of the DOM that we need, there are a few last considerations to make before this will preserve the order of preferences and overrides that we want. We’re going to use two important features of CSS to help us tailor things to do that.&lt;/p&gt;
&lt;p&gt;First of all, we can amend our first declaration with the &lt;code&gt;:where()&lt;/code&gt; selector. This selector &lt;em&gt;nullifies&lt;/em&gt; the specifity of all selectors inside it, so when our &lt;code&gt;:root&lt;/code&gt; selector becomes &lt;code&gt;:where(:root)&lt;/code&gt;, it has a specificity of &lt;code&gt;(0,0,0)&lt;/code&gt;. This makes it very easy to &lt;em&gt;out-specify&lt;/em&gt; later on.&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;:root&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:where(:root)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
&lt;/span&gt;	color-scheme: light dark;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we’ll consider the three methods of control (&lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value, data attribute, class) and which should be more specific.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value selector and data attribute selector can be treated as one—that is to say that their specificity in this hierarchy should be identical, as they both &lt;em&gt;actually&lt;/em&gt; represent the same thing, the value of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Based on the hierarchy that we want, the specificity of the class-based controls should be higher than the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value and data attribute controls.&lt;/p&gt;
&lt;p&gt;Let’s consider the specificity of the three selectors in each group:&lt;/p&gt;
&lt;table&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;th&gt;&lt;code&gt;:root:has([name=color-scheme] [value=light]:checked)&lt;/code&gt;&lt;/th&gt;
            &lt;td&gt;(0,4,0)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;&lt;code&gt;[data-color-scheme=light]&lt;/code&gt;&lt;/th&gt;
            &lt;td&gt;(0,1,0)&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;th&gt;&lt;code&gt;.light&lt;/code&gt;&lt;/th&gt;
            &lt;td&gt;(0,1,0)&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Given that their specificities don’t align with what we want, we can leverage a second important feature of CSS, source order.&lt;/p&gt;
&lt;p&gt;Let’s use the &lt;code&gt;:where()&lt;/code&gt; selector again to nullify the specificity of the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value selector and data attribute selector:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;-&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;light&quot;&lt;/span&gt;]&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;.light {
	color-scheme: light;
}
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;-&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[name=&lt;span&gt;&quot;color-scheme&quot;&lt;/span&gt;] [value=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;:&lt;/span&gt;checked&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;[data-color-scheme=&lt;span&gt;&quot;dark&quot;&lt;/span&gt;]&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
&lt;/span&gt;.dark {
	color-scheme: dark;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But why do this? Won’t they have the same specificity as the &lt;code&gt;:where(:root)&lt;/code&gt; declaration?&lt;/p&gt;
&lt;p&gt;They &lt;strong&gt;do&lt;/strong&gt; have the same specificity &lt;code&gt;(0,0,0)&lt;/code&gt;, but, &lt;strong&gt;critically&lt;/strong&gt;, they come &lt;em&gt;after&lt;/em&gt; the &lt;code&gt;:where(:root)&lt;/code&gt; declaration in source order. This means that our new &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; value and data attribute selectors take precedence over &lt;code&gt;:where(:root)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I’ve inlined the specificity of each selector to demonstrate this below:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;/**
 * (0,0,0) — 1st in source order
 */&lt;/span&gt;
&lt;span&gt;:where(:root)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;p&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/p&gt;
&lt;/code&gt;&lt;ul&gt;&lt;code&gt;
&lt;li&gt;Order of selector specificities below:&lt;/li&gt;
&lt;li&gt;(0,0,0) – 2nd in source order&lt;/li&gt;
&lt;li&gt;(0,0,0) – 2nd in source order&lt;/li&gt;
&lt;/code&gt;&lt;li&gt;&lt;code&gt;(0,1,0)&lt;br&gt;
*/&lt;br&gt;
&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;light&quot;]),&lt;br&gt;
.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;dark&quot;]),&lt;br&gt;
.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/pre&gt;

&lt;hr&gt;
&lt;h2 id=&quot;part-6&quot;&gt;Fin.&lt;/h2&gt;
&lt;p&gt;At this point, the build is complete! For the most part, the code involved in this solution &lt;em&gt;rarely&lt;/em&gt; needs amending or changing, so I tend to put it wherever you might find things like resets in my CSS.&lt;/p&gt;
&lt;p&gt;We can make powerful use of the &lt;code&gt;light-dark()&lt;/code&gt; function to toggle between colour values depending on the active colour scheme, e.g.:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;main&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;background-color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;light-dark&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;#e1e1e1&lt;span&gt;,&lt;/span&gt; #1e1e1e&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
	&lt;span&gt;color&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;light-dark&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;#1e1e1e&lt;span&gt;,&lt;/span&gt; #e1e1e1&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Furthermore, because we’ve set up a hierarchy for the controls that we’ve made available to us, we’ve instructed our styles to hook into visitors’ &lt;em&gt;OS/Browser-level Preference&lt;/em&gt;. If they’d rather not let their OS/Browser dictate their preference, they can use the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; to choose a &lt;em&gt;Site-level Preference&lt;/em&gt; that will persist across tabs, windows, and even sessions, thanks to the power of local storage.&lt;/p&gt;
&lt;p&gt;We’ve also thought about user experience and poor-performance situations by introducing a light sprinkling of JavaScript. Despite incurring a small performance impact itself, this gives us the tremendous benefit of applying a chosen colour scheme to the page as &lt;em&gt;early&lt;/em&gt; as possible to prevent the &lt;em&gt;wrong&lt;/em&gt; colour scheme from being shown &lt;em&gt;before&lt;/em&gt; the heftier parts of this solution have had a chance to make their impact.&lt;/p&gt;
&lt;p&gt;On top of that, we, as website authors, can override the user’s &lt;em&gt;Site-level Preference&lt;/em&gt; to be able to say that certain pages or parts of pages should &lt;em&gt;always&lt;/em&gt; be rendered with a specific colour scheme.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Full CSS Solution&lt;/summary&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;:where(:root)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;
	&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light dark&lt;span&gt;;&lt;/span&gt;
&lt;span&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;light&quot;]),&lt;br&gt;
.light&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;dark&quot;]),&lt;br&gt;
.dark&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;br&gt;
&lt;/details&gt;&lt;p&gt;&lt;/p&gt;
&lt;h4&gt;Bonus!&lt;/h4&gt;
&lt;p&gt;Although it isn’t stable across browsers yet, the &lt;a href=&quot;/feature-watch/#css-if&quot;&gt;&lt;code&gt;if()&lt;/code&gt; selector&lt;/a&gt; will allow us to toggle non-colour property values based on the resolved colour scheme. This is great for things like changing a &lt;code&gt;background-image&lt;/code&gt; based on the colour scheme. That would look something like this:&lt;/p&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;&lt;span&gt;background-image&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;if&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;light&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/light.png&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt; &lt;span&gt;else&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; &lt;span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/dark.png&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;part-7&quot;&gt;Fin. Part 2:&amp;nbsp;Electric Boogaloo&lt;/h2&gt;
&lt;p&gt;We can actually take this one step further without &lt;em&gt;much&lt;/em&gt; extra CSS, and this gives us the ability to set a Page-level or Element-level colour scheme that is more of a &lt;em&gt;suggestion&lt;/em&gt; than a &lt;em&gt;rule&lt;/em&gt;, and can be overridden by a &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This gives us two new ways to apply colour schemes to our pages and an amended hierarchy of how colour schemes can be applied:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Element-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-2&quot;&gt;Page-level Override&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-3&quot;&gt;Site-level Preference&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;Element-level Suggestion&lt;/li&gt;
    &lt;li&gt;Page-level Suggestion&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#part-1&quot;&gt;OS/Browser-level Preference&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre data-language=&quot;css&quot; data-language-friendly=&quot;CSS&quot;&gt;&lt;code&gt;:where(:root) {
	color-scheme: light dark;
}
&lt;/code&gt;&lt;p&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;&quot;]:checked):not([data-color-scheme], .light, .dark))&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;&amp;amp;:where(.suggested-light),&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&amp;amp; :where(.suggested-light)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;		&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; light&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;&amp;amp;:where(.suggested-dark),&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&amp;amp; :where(.suggested-dark)&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;		&lt;span&gt;color-scheme&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; dark&lt;span&gt;;&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;	&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;span&gt;+&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;
&lt;/span&gt;&lt;br&gt;
:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;light&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;light&quot;]),&lt;br&gt;
.light {&lt;br&gt;
color-scheme: light;&lt;br&gt;
}&lt;br&gt;
:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;dark&quot;]:checked)),&lt;br&gt;
:where([data-color-scheme=&quot;dark&quot;]),&lt;br&gt;
.dark {&lt;br&gt;
color-scheme: dark;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;
&lt;div&gt;
    &lt;p&gt;This introduces a rather unwieldy selector, &lt;code&gt;:where(:root:has([name=&quot;color-scheme&quot;] [value=&quot;&quot;]:checked):not([data-color-scheme], .light, .dark))&lt;/code&gt;, so let’s break down what it does:&lt;/p&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;code&gt;:root:has([name=&quot;color-scheme&quot;] [value=&quot;&quot;]:checked)&lt;/code&gt; checks if the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; on the page has its default value but targets the document root when applying styles. When this is the case, it means that the user has selected neither &lt;code&gt;light&lt;/code&gt; nor &lt;code&gt;dark&lt;/code&gt; as their &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;:not([data-color-scheme], .light, .dark)&lt;/code&gt; ensures that the document root has neither a &lt;code&gt;data-color-scheme&lt;/code&gt; attribute nor the classes &lt;code&gt;light&lt;/code&gt; or &lt;code&gt;dark&lt;/code&gt; applied to it.&lt;/li&gt;
        &lt;li&gt;&lt;code&gt;:where(...)&lt;/code&gt; makes sure that this complex selector has a specificity of &lt;code&gt;(0,0,0)&lt;/code&gt;. This ensures that it doesn’t compete in specificity with other important parts of this solution, but rather takes a specific place in the source order to help define its place in the hierarchy (see below).&lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;The two extra classes that this introduces, &lt;code&gt;.suggested-light&lt;/code&gt; and &lt;code&gt;.suggested-dark&lt;/code&gt;, can be applied to our HTML in the same way as our previous classes (&lt;code&gt;.light&lt;/code&gt; and &lt;code&gt;.dark&lt;/code&gt;), but the important thing to note here again is the source order.&lt;/p&gt;
&lt;p&gt;By placing these declarations &lt;em&gt;between&lt;/em&gt; the two parts of our previous solution (and matching the specificity of &lt;code&gt;(0,0,0)&lt;/code&gt;), they receive &lt;em&gt;higher&lt;/em&gt; precendence than the &lt;em&gt;OS/Browser-level Preference&lt;/em&gt; but &lt;em&gt;lower&lt;/em&gt; precedence than the &lt;em&gt;Site-level Preference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This can be useful in situations where, for artistic reasons, you&#39;d like a particular page or section to be a specific colour scheme, but if the user has set a &lt;em&gt;Site-level Preference&lt;/em&gt;—maybe for reasons relating to eyesight or otherwise—then that choice should be respected and the particular page/section should be rendered as they’ve chosen, &lt;em&gt;not&lt;/em&gt; from your &lt;q&gt;suggested&lt;/q&gt; colour scheme.&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS. This post is part of &lt;a href=&quot;https://chrisburnell.com/rss-club/&quot;&gt;RSS Club&lt;/a&gt;, which means it appears &lt;em&gt;only&lt;/em&gt; in my RSS feeds for 3 days (until &lt;time datetime=&quot;2025-10-27T12:01:00-03:00&quot;&gt;Monday, 27 October 2025&lt;/time&gt;), rewarding folks who subscribe to my RSS feeds with knowing about this post early!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/color-scheming/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/july-2024-project-updates/</id>
		<link href="https://chrisburnell.com/article/july-2024-project-updates/" />
		<title>July Project Updates</title>
		<published>2024-07-20T15:17:49+08:00</published>
		<publishedFriendly>20 July 2024</publishedFriendly>
		<updated>2024-07-20T15:17:49+08:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>An update on two projects I’ve been working on—one new and one old—based on some development oversights I’ve made in the past that I’d like to prevent going forward.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;An update on two projects I’ve been working on—one new and one old—based on some development oversights I’ve made in the past that I’d like to prevent going forward.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Howdy folks!&lt;/p&gt;
&lt;p&gt;It’s been a little while since my last post. I think I gassed myself out a little bit after &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;posting every day during May&lt;/a&gt;, but I’ve still been keeping busy working on a couple of projects.&lt;/p&gt;
&lt;h2&gt;eleventy-cache-webmentions v2.1.0 Beta&lt;/h2&gt;
&lt;p&gt;I managed to finish an important fix for my Webmentions plugin for Eleventy.&lt;/p&gt;
&lt;p&gt;The problem that this new version fixes comes from an oversight that I made in the project’s documentation with regards to pulling down Webmentions from &lt;a href=&quot;https://webmention.io&quot;&gt;Webmention.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In short, &lt;em&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt;&lt;/em&gt; provides basic pagination support by using the &lt;code&gt;per-page&lt;/code&gt; and &lt;code&gt;page&lt;/code&gt; parameters. In an attempt to simplify my plugin’s code, the documentation instructs using the &lt;code&gt;per-page&lt;/code&gt; parameter to request &lt;code&gt;9001&lt;/code&gt; Webmentions per page. At the time, my entire website only had a few hundred Webmentions, so, naïvely, this seemed like a number of Webmentions that would reasonably never be reached.&lt;/p&gt;
&lt;p&gt;It’s abundantly clear now that this number is &lt;em&gt;not&lt;/em&gt; reasonably high enough, particularly when I come across others’ websites that have as many Webmentions per post as I’ve ever received on &lt;em&gt;all&lt;/em&gt; my posts.&lt;/p&gt;
&lt;p&gt;I try to be sympathetic towards the pivotal role &lt;em&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt;&lt;/em&gt; plays for so many people, so rather than changing the recommended &lt;code&gt;per-page&lt;/code&gt; value in the documentation to an even higher number, I decided to rewrite part of the plugin to traverse multiple pages of results from the &lt;em&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt;&lt;/em&gt; API.&lt;/p&gt;
&lt;p&gt;Unless a specific &lt;code&gt;per-page&lt;/code&gt; value is dictated in your plugin configuration, the &lt;code&gt;per-page&lt;/code&gt; parameter now has a default value of &lt;code&gt;1000&lt;/code&gt;. For fresh builds, where the list of Webmentions hasn’t yet been cached, the plugin will continue incrementing the &lt;code&gt;page&lt;/code&gt; value until it finds a page from the API with less results than the &lt;code&gt;per-page&lt;/code&gt; value.&lt;/p&gt;
&lt;p&gt;This means that if your website has 1,600 total Webmentions and you’re using the default &lt;code&gt;per-page&lt;/code&gt; value of &lt;code&gt;1000&lt;/code&gt;, the plugin will make two requests to the &lt;em&gt;&lt;a href=&quot;http://Webmention.io&quot;&gt;Webmention.io&lt;/a&gt;&lt;/em&gt; API: one request with 1,000 results and a second request with 600 results.&lt;/p&gt;
&lt;p&gt;As before, when the list of Webmentions is &lt;em&gt;already&lt;/em&gt; cached, the plugin will use the DateTime of the most recent cached Webmention with the &lt;code&gt;since&lt;/code&gt; parameter to only pull down Webmentions that were received by the API &lt;em&gt;after&lt;/em&gt; the most recent Webmention in your cache.&lt;/p&gt;
&lt;p&gt;Beta releases are currently available on both &lt;a href=&quot;https://github.com/chrisburnell/eleventy-cache-webmentions/releases/tag/v2.1.0-beta.2&quot;&gt;GitHub&lt;/a&gt; and &lt;a href=&quot;https://www.npmjs.com/package/@chrisburnell/eleventy-cache-webmentions/v/2.1.0-beta.2&quot;&gt;npm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can install the latest beta release with the following:&lt;/p&gt;
&lt;pre data-language=&quot;bash&quot; data-language-friendly=&quot;bash&quot;&gt;&lt;code&gt;&lt;span&gt;npm&lt;/span&gt; &lt;span&gt;install&lt;/span&gt; @chrisburnell/eleventy-cache-webmentions@beta&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you’d like to provide feedback on this beta release, you can &lt;a href=&quot;/about/#contact&quot;&gt;get in touch with me directly&lt;/a&gt; or through the related &lt;a href=&quot;https://github.com/chrisburnell/eleventy-cache-webmentions/issues/6&quot;&gt;Issue&lt;/a&gt; or &lt;a href=&quot;https://github.com/chrisburnell/eleventy-cache-webmentions/pull/7&quot;&gt;Pull Request&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;h2&gt;check-invalid-datetimes&lt;/h2&gt;
&lt;p&gt;Earlier this year, when I was refactoring my website build to take advantage of Eleventy’s ESM support, I kept running into issues with how I was handling DateTimes with &lt;a href=&quot;https://moment.github.io/luxon/&quot;&gt;luxon&lt;/a&gt;. This resulted in &lt;code&gt;Invalid ​DateTime&lt;/code&gt; being printed in my output HTML and XML files, which would have caused issues for my RSS feeds and been &lt;em&gt;less-than-ideal&lt;/em&gt; to see on the front end of my website, to say the least.&lt;/p&gt;
&lt;p&gt;Because these issues could have been caused by wrongly-formatted DateTimes in the front matter of posts or by using &lt;em&gt;luxon&lt;/em&gt; incorrectly, it felt like playing a constant game of cat and mouse trying to track down where the problems originated from.&lt;/p&gt;
&lt;p&gt;A few weeks ago, I took a swing at building a more robust solution to tracking down these problems and came up with a package called &lt;code&gt;check-invalid-datetimes&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It’s based on the &lt;a href=&quot;https://www.npmjs.com/package/check-html-links&quot;&gt;&lt;code&gt;check-html-links&lt;/code&gt;&lt;/a&gt; package by &lt;a href=&quot;https://modern-web.dev/&quot;&gt;Modern Web&lt;/a&gt; which crawls a given directory to alert on any broken links and references in HTML files, which I’ve been using for a couple of months.&lt;/p&gt;
&lt;p&gt;Similarly, my package crawls a given directory to alert on any instances of &lt;code&gt;Invalid ​DateTime&lt;/code&gt; that it finds in HTML and XML files.&lt;/p&gt;
&lt;p&gt;It’s still a work-in-progress, as there are some cases that it needs to account for so that it doesn’t flag intentional instances of the string (in technical articles, for example). I’m considering refactoring the package further to only search for the string inside specific elements, e.g. inside &lt;code&gt;&amp;lt;time&amp;gt;&lt;/code&gt; elements and their &lt;code&gt;datetime&lt;/code&gt; attribute in HTML files.&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/july-2024-project-updates/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/weblogpomo2024-wrap-up/</id>
		<link href="https://chrisburnell.com/article/weblogpomo2024-wrap-up/" />
		<title>WeblogPoMo 2024 Wrap Up</title>
		<published>2024-06-02T20:55:41+08:00</published>
		<publishedFriendly>2 June 2024</publishedFriendly>
		<updated>2024-06-02T20:55:41+08:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>It’s officially June now, which means #WeblogPoMo2024 has come to a close! Let’s review what I wrote about and what I’m taking away from participating in this event.</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;It’s officially June now, which means &lt;a href=&quot;/tag/weblogpomo2024/&quot;&gt;#WeblogPoMo2024&lt;/a&gt; has come to a close! Let’s review what I wrote about and what I’m taking away from participating in this event.&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;&lt;em&gt;Somehow&lt;/em&gt; I managed to post every single day this month. It was oftentimes tiring and some days a real struggle to get things done and published, but I’m really happy that I managed to stay committed and see it through to the end.&lt;/p&gt;
&lt;p&gt;Over the course of the event, there’s been a dramatic shift in my attitude towards perfectionism when it comes to finishing and getting articles published. On the 3&lt;sup&gt;rd&lt;/sup&gt;, I wrote this on the &lt;a href=&quot;https://discourse.32bit.cafe/t/weblogpomo-2024/&quot;&gt;32-Bit Café thread for WeblogPoMo 2024&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There’s typically at least a week between starting writing something on my website and publishing it—sometimes even months—but learning not to stress too much about making everything I publish as perfect as I can has been truly cathartic. I’m hoping I have the sense to remember these feelings when the month is over. 😅&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lo and behold, it actually became easier and easier for me to write as the days passed by. It felt more and more natural for me to hone in on the idea(s) and information I wanted to convey, get it out of my brain and onto the metaphorical page, make some quick revisions and edits, and hit publish.&lt;/p&gt;
&lt;p&gt;There are certainly times where my words were more meandering that I’d have preferred, but I’m glad that didn’t stop me from publishing at all, rather than let my ideas pile up and clog the drain. And what better way to get comfortable writing and find my own, unique writing style than to do it for 31 days straight!&lt;/p&gt;
&lt;p&gt;That being said, publishing something new &lt;em&gt;every day&lt;/em&gt; isn’t something that always fit into my schedule. There were days where coming up with post ideas, writing, and publishing weren’t in the cards, but my desire to stay committed to posting every day had me pushing through those mental barriers, and I don’t think that’s a healthy headspace to be in. If I was working a full-time job, I don’t know how I would have managed to cope; at the very least, I wouldn’t have been able to publish as much content as I did last month.&lt;/p&gt;
&lt;p&gt;Even though I feel like I’ve broken the shackles of heavily-editing my posts before I feel comfortable publishing them, having the time and mental capacity to plan out the flow of posts and do more than a cursory read-through of my words would benefit the readability and strength of the ideas I’m conveying.&lt;/p&gt;
&lt;h2&gt;Takeaways&lt;/h2&gt;
&lt;p&gt;I feel really accomplished. &lt;em&gt;Really&lt;/em&gt; accomplished and proud of the work that I put into this. As tired as I am now, I’m pretty confident that I’ll be participating again next year, although with perhaps a bit more planning ahead of time. Participating did a lot more for me than just add 31 new posts to the archives.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Got over my obsession with perfection and endless editing before publishing&lt;/li&gt;
&lt;li&gt;Found myself looking forward to reading again every day&lt;/li&gt;
&lt;li&gt;Made and documented numerous technical changes and improvements to my website&lt;/li&gt;
&lt;li&gt;Finally got the idea for &lt;code&gt;/interests&lt;/code&gt; pages out into the wild and &lt;a href=&quot;https://chrisburnell.github.io/interests-directory/&quot;&gt;made a directory&lt;/a&gt; for folks to join&lt;/li&gt;
&lt;li&gt;Extremely thankful to have had a lot of fun conversations with friends as we supported each other in ideating and writing (and coping!) over the month&lt;/li&gt;
&lt;li&gt;Discovered more than a handful of excellent blogs and the wonderful people behind them that I’ve since added to &lt;a href=&quot;/blogroll/&quot;&gt;my blogroll&lt;/a&gt;—check out a &lt;a href=&quot;https://web.archive.org/web/20241109010318/https://weblog.anniegreens.lol/weblog-posting-month-2024/participators&quot;&gt;list of participators on Anne Studivant’s website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;stats&quot;&gt;Some stats&lt;/h2&gt;
&lt;dl&gt;
	&lt;dt&gt;Word Count&lt;/dt&gt;
	&lt;dd&gt;15,863&lt;/dd&gt;
	&lt;dt&gt;Most Verbose Post&lt;/dt&gt;
	&lt;dd&gt;&lt;a href=&quot;/article/open-source-dilemma/&quot;&gt;The Open Source Dilemma&lt;/a&gt; &lt;small&gt;with&lt;/small&gt; 1,266 words&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Based on &lt;a href=&quot;/stats/&quot;&gt;my stats page&lt;/a&gt;, this month’s posts account for a whopping &lt;strong&gt;26%&lt;/strong&gt; of the words published on this website to date!&lt;/p&gt;
&lt;figure&gt;
    &lt;svg-sparkline values=&quot;419,605,215,1208,31,34,336,101,524,1058,593,603,426,251,189,127,1266,819,231,204,1203,660,128,630,380,359,1002,397,397,680,785&quot; fill=&quot;true&quot; start-label=&quot;Word Count&quot;&gt;&lt;/svg-sparkline&gt;
&lt;/figure&gt;
&lt;h3&gt;Categories&lt;/h3&gt;
&lt;table&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;th&gt;Article&lt;/th&gt;
			&lt;td&gt;12&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Music Review&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Note&lt;/th&gt;
			&lt;td&gt;16&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Recipe&lt;/th&gt;
			&lt;td&gt;2&lt;/td&gt;
			
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Tags&lt;/h3&gt;
&lt;table&gt;
	&lt;tbody&gt;
		&lt;tr&gt;
			&lt;th&gt;AI&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Art&lt;/th&gt;
			&lt;td&gt;2&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Color&lt;/th&gt;
			&lt;td&gt;2&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Crossword&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;CSS&lt;/th&gt;
			&lt;td&gt;5&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;CSS Variables&lt;/th&gt;
			&lt;td&gt;2&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Eleventy&lt;/th&gt;
			&lt;td&gt;5&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;GitHub&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;HTML&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;JavaScript&lt;/th&gt;
			&lt;td&gt;6&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Jekyll&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Nunjucks&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Personal&lt;/th&gt;
			&lt;td&gt;3&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;PHP&lt;/th&gt;
			&lt;td&gt;2&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;State of the Web&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;TTRPG&lt;/th&gt;
			&lt;td&gt;1&lt;/td&gt;
			
		&lt;/tr&gt;
&lt;tr&gt;
			&lt;th&gt;Web Components&lt;/th&gt;
			&lt;td&gt;3&lt;/td&gt;
			
		&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;favourites&quot;&gt;My favourite posts&lt;/h2&gt;
&lt;ul data-skip-wordcount=&quot;&quot;&gt;
    &lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/slash-interests/&quot;&gt;&lt;strong&gt;What are you interested in?&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-01T19:37:12+08:00&quot;&gt;&lt;em&gt;1&lt;sup&gt;st&lt;/sup&gt; 1&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In the world of online self-expression, there’s been a fascinating trend of website authors creating discoverable pages to help others learn about who they are, what they’re thinking about, and more. I’m proposing an addition to these initiatives that helps us discover what people are passionate about.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/early-2024-web-components/&quot;&gt;&lt;strong&gt;Web Components from Early 2024&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-02T12:00:00+08:00&quot;&gt;&lt;em&gt;2&lt;sup&gt;nd&lt;/sup&gt; 2&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I’ve been having a lot of fun creating reusable Web Components, so here are three that I’ve built and been using so far this year.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/cluster-composition/&quot;&gt;&lt;strong&gt;The Cluster Composition&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-07T18:39:29+08:00&quot;&gt;&lt;em&gt;7&lt;sup&gt;th&lt;/sup&gt; 7&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In this post, I’m going to cover how I use a snippet of CSS for laying out list items that called the &lt;q&gt;Cluster&lt;/q&gt;.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/open-source-dilemma/&quot;&gt;&lt;strong&gt;The Open Source Dilemma&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-17T23:58:16+08:00&quot;&gt;&lt;em&gt;17&lt;sup&gt;th&lt;/sup&gt; 17&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In this post, I discuss some thoughts I’ve been mulling over about the open source nature of my website, particularly after a great discussion I had with &lt;a href=&quot;https://flamedfury.com&quot;&gt;fLaMEd&lt;/a&gt; that galvanised some of my recent feelings about ownership on the web.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/some-eleventy-filters/&quot;&gt;&lt;strong&gt;Some of my Eleventy Filters&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-18T22:18:38+08:00&quot;&gt;&lt;em&gt;18&lt;sup&gt;th&lt;/sup&gt; 18&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In refactoring my website earlier this year, part of my process was to evaluate and revise the many, many &lt;a href=&quot;https://www.11ty.dev/docs/filters/&quot;&gt;Eleventy Filters&lt;/a&gt; I use throughout my website’s build, so in this post, I’ll run through a handful of them.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/daily-word-games/&quot;&gt;&lt;strong&gt;Daily Word Games&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-21T23:23:21+08:00&quot;&gt;&lt;em&gt;21&lt;sup&gt;st&lt;/sup&gt; 21&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;For at least a year now, I’ve been having daily video calls with my parents for a quick catch-up and to play some online word games. It’s a real highlight to my day (especially considering I’m on the opposite side of the world from them), so in this post I’ll run through some of those games that we play.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/dynamic-content-includes/&quot;&gt;&lt;strong&gt;Dynamic Content Includes&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-24T18:55:11+08:00&quot;&gt;&lt;em&gt;24&lt;sup&gt;th&lt;/sup&gt; 24&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In this post, I explain how I solved two issues at the same time by introducing a feature to my post layout that I’m calling &lt;q&gt;pre&lt;/q&gt; and &lt;q&gt;post&lt;/q&gt; includes.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/interpolating-colours/&quot;&gt;&lt;strong&gt;Interpolating Colours&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-27T21:39:56+08:00&quot;&gt;&lt;em&gt;27&lt;sup&gt;th&lt;/sup&gt; 27&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Today I’ll be talking about how we can use some relatively new data types in CSS for finer control over how we use colour spaces in mixing and creating gradients from colours.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/indent-outdent/&quot;&gt;&lt;strong&gt;Indent Outdent&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-28T18:07:40+08:00&quot;&gt;&lt;em&gt;28&lt;sup&gt;th&lt;/sup&gt; 28&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In the last few days, I’ve been working on a small redesign of my website, and thought I’d share a handy little implementation of CSS Grid I’ve been using to lay out the contents of my pages.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/strike-while-the-iron-is-hot/&quot;&gt;&lt;strong&gt;Strike while the iron is hot&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-31T23:45:27+08:00&quot;&gt;&lt;em&gt;31&lt;sup&gt;st&lt;/sup&gt; 31&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Where does my creativity come from, and what creates those environments that open the floodgates of inspiration and fervour?&lt;/p&gt;
        &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;others&quot;&gt;My other posts&lt;/h2&gt;
&lt;ul data-skip-wordcount=&quot;&quot;&gt;
    &lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/incredible-musician-performances/&quot;&gt;&lt;strong&gt;Incredible Musician Performances&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-03T20:24:08+08:00&quot;&gt;&lt;em&gt;3&lt;sup&gt;rd&lt;/sup&gt; 3&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Today I’m sharing a small handful of videos from YouTube that have been captivating me, showcasing some &lt;em&gt;tremendously&lt;/em&gt; talented musicians’ performances.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/revisiting-php-images/&quot;&gt;&lt;strong&gt;Revisiting PHP-Generated Images&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-04T21:02:10+08:00&quot;&gt;&lt;em&gt;4&lt;sup&gt;th&lt;/sup&gt; 4&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Generating images using PHP was a bit like magic to me back in 2007. In this post, I’m going to revisit the technique to create an image that shows dynamically-updating information about my website content.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/photos-early-2024/&quot;&gt;&lt;strong&gt;Some photos from early 2024&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-05T19:50:21+08:00&quot;&gt;&lt;em&gt;5&lt;sup&gt;th&lt;/sup&gt; 5&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Here are a handful of photos I’ve taken across the last couple of months.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/88x31-early-2024/&quot;&gt;&lt;strong&gt;88x31 Badges from early 2024&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-06T23:19:38+08:00&quot;&gt;&lt;em&gt;6&lt;sup&gt;th&lt;/sup&gt; 6&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I spent quite a bit of my early years on the web creating pixel art, and it’s been fun to get back into it. Here are a couple of badges I made for the footer of my site this year.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/interests-directory/&quot;&gt;&lt;strong&gt;The /interests Directory&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-08T23:57:10+08:00&quot;&gt;&lt;em&gt;8&lt;sup&gt;th&lt;/sup&gt; 8&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I made a directory for /interests pages! If you’ve built your own, why not submit it to the list!&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/obfuscating-api-calls/&quot;&gt;&lt;strong&gt;How I’m obfuscating API calls in my front end JavaScript&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-09T22:43:00+08:00&quot;&gt;&lt;em&gt;9&lt;sup&gt;th&lt;/sup&gt; 9&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I use a rudimentary Web Component on my website to pull in data from the LastFM API, but I needed a way to prevent exposing my API key. To get around this, I put a short PHP script on my server that makes the API calls for me.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/website-settings/&quot;&gt;&lt;strong&gt;Website Settings&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-10T11:04:55+08:00&quot;&gt;&lt;em&gt;10&lt;sup&gt;th&lt;/sup&gt; 10&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In this post, I’m going to run through how I’m using some exciting &lt;q&gt;new&lt;/q&gt; browser features to power the settings/preferences on my website.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/rebuilding-instant-photo/&quot;&gt;&lt;strong&gt;Rebuilding a Silly Web Component&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-11T22:41:01+08:00&quot;&gt;&lt;em&gt;11&lt;sup&gt;th&lt;/sup&gt; 11&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;A few months ago I built a fun little experiment of a Web Component, but in today’s post, I’m going to try building it using just CSS.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/vigenere-cipher/&quot;&gt;&lt;strong&gt;Vigenère Cipher&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-12T23:05:49+08:00&quot;&gt;&lt;em&gt;12&lt;sup&gt;th&lt;/sup&gt; 12&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In this interactive article, I’m going to show how the &lt;em&gt;Vigenère Cipher&lt;/em&gt; works and how you can use it as an Eleventy filter.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/buried-bookworm/&quot;&gt;&lt;strong&gt;Buried Bookworm&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-13T22:03:10+08:00&quot;&gt;&lt;em&gt;13&lt;sup&gt;th&lt;/sup&gt; 13&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Reflecting on my reading habits, or lack thereof, and what I plan to do to get back my appetite for reading.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/tempest/&quot;&gt;&lt;strong&gt;Tempest&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-14T23:09:41+08:00&quot;&gt;&lt;em&gt;14&lt;sup&gt;th&lt;/sup&gt; 14&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Keeping up with &lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot;&gt;Weblog Posting Month&lt;/a&gt; has been &lt;em&gt;tiring&lt;/em&gt;, so I’m going to take the slightly easy way out today by posting a short excerpt from a &lt;abbr title=&quot;Dungeons and Dragons&quot;&gt;D&amp;amp;D&lt;/abbr&gt; story/campaign I’ve been writing on and off for a couple of years.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/recipe/french-pancakes/&quot;&gt;&lt;strong&gt;French Pancakes&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Recipe&lt;/span&gt; &lt;time datetime=&quot;2024-05-15T22:53:45+08:00&quot;&gt;&lt;em&gt;15&lt;sup&gt;th&lt;/sup&gt; 15&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Much like my mother’s &lt;a href=&quot;/recipe/bread-rolls/&quot;&gt;Bread Rolls&lt;/a&gt;, these pancakes were a bit hit when I was growing up. Whenever I’m back in Canada visiting family, I always look forward to having these!&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/recipe/almond-crescents/&quot;&gt;&lt;strong&gt;Almond Crescents&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Recipe&lt;/span&gt; &lt;time datetime=&quot;2024-05-16T23:25:55+08:00&quot;&gt;&lt;em&gt;16&lt;sup&gt;th&lt;/sup&gt; 16&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I’m sharing another all-star family recipe today, a total must-have for me every Christmas!&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/berserk-1997/&quot;&gt;&lt;strong&gt;Berserk (1997)&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-19T22:55:47+08:00&quot;&gt;&lt;em&gt;19&lt;sup&gt;th&lt;/sup&gt; 19&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Yesterday, I finished watching &lt;a href=&quot;https://trakt.tv/shows/berserk&quot;&gt;Berserk&lt;/a&gt;, an anime adaptation of the Japanese manga of the same name, for the second time.&lt;br&gt; As far as animes go, I have to put it right up there with some of my other favourites...&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/how-may-i-help-you/&quot;&gt;&lt;strong&gt;How may I help you?&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-20T22:22:26+08:00&quot;&gt;&lt;em&gt;20&lt;sup&gt;th&lt;/sup&gt; 20&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Want my help? Head over to my new Help page to book some of my time!&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/watching-listening-stats-may-2024/&quot;&gt;&lt;strong&gt;Watching and Listening Stats (as of May 2024)&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-22T22:55:48+08:00&quot;&gt;&lt;em&gt;22&lt;sup&gt;nd&lt;/sup&gt; 22&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I’ve been tracking music I listen to since 2010, and recently started using Trakt for movies and TV shows. I decided to collate some of the data to visualise my listening and watching habits.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/music/endtroducing/&quot;&gt;&lt;strong&gt;Endtroducing.....&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Music Review&lt;/span&gt; &lt;time datetime=&quot;2024-05-23T22:40:32+08:00&quot;&gt;&lt;em&gt;23&lt;sup&gt;rd&lt;/sup&gt; 23&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;DJ Shadow’s &lt;em&gt;Endtroducing.....&lt;/em&gt; is, beyond a shadow of a doubt, one of the greatest albums of all time, and certainly one of my favourites.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/spongebob-filter/&quot;&gt;&lt;strong&gt;Spongebob Sentiment&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-25T23:10:30+08:00&quot;&gt;&lt;em&gt;25&lt;sup&gt;th&lt;/sup&gt; 25&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;I’ve got a bit of a SiLLy POsT for you today.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/beneficial-browser-extensions/&quot;&gt;&lt;strong&gt;Beneficial Browser Extensions&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-26T22:10:19+08:00&quot;&gt;&lt;em&gt;26&lt;sup&gt;th&lt;/sup&gt; 26&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;Over the last few months, I’ve come across some excellent browser extensions, mainly through friends on Mastodon, so thought I’d share some of my favourites.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/note/layout-update-may-2024/&quot;&gt;&lt;strong&gt;Layout Update&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;time datetime=&quot;2024-05-29T23:19:17+08:00&quot;&gt;&lt;em&gt;29&lt;sup&gt;th&lt;/sup&gt; 29&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;A short update on my website’s layout.&lt;/p&gt;
        &lt;/li&gt;&lt;li&gt;
            &lt;div&gt;&lt;span&gt;&lt;a href=&quot;/article/generating-palette-file/&quot;&gt;&lt;strong&gt;Generating a Palette File from Site Colours&lt;/strong&gt;&lt;/a&gt;&lt;/span&gt; &lt;span&gt;Article&lt;/span&gt; &lt;time datetime=&quot;2024-05-30T23:50:26+08:00&quot;&gt;&lt;em&gt;30&lt;sup&gt;th&lt;/sup&gt; 30&lt;/em&gt;&lt;/time&gt;&lt;/div&gt;
            &lt;p&gt;In this post, I explain how I dynamically-generate a GIMP palette file based on the design tokens for my website’s colours.&lt;/p&gt;
        &lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Huge thanks for &lt;a href=&quot;https://web.archive.org/web/20250709024810/https://weblog.anniegreens.lol/&quot;&gt;Anne Studivant&lt;/a&gt; for organising this event.&lt;/p&gt;
&lt;p&gt;Whether you read all my Weblog Posting Month posts or only a few, thank you for reading, and I’ll see you again next year!&lt;/p&gt;
			
			
			
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/weblogpomo2024-wrap-up/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	<entry>
		<id>https://chrisburnell.com/article/strike-while-the-iron-is-hot/</id>
		<link href="https://chrisburnell.com/article/strike-while-the-iron-is-hot/" />
		<title>Strike while the iron is hot</title>
		<published>2024-05-31T23:45:27+08:00</published>
		<publishedFriendly>31 May 2024</publishedFriendly>
		<updated>2024-05-31T23:45:27+08:00</updated>
		<category term="article" scheme="https://chrisburnell.com/article/" label="Article" />
		<summary>Where does my creativity come from, and what creates those environments that open the floodgates of inspiration and fervour?</summary>
		<content xml:lang="en" type="html">
			&lt;p&gt;Where does my creativity come from, and what creates those environments that open the floodgates of inspiration and fervour?&lt;/p&gt;
				&lt;hr&gt;
			
			
			&lt;p&gt;Ever since my first taste of web development, I eagerly threw myself down the rabbit hole. Here was something I loved doing so much that I forsake sleep and rest and a very many other things to pursue this new-found passion. It was not uncommon for me to stay up late and into the early morning hours tinkering on one thing or another.&lt;/p&gt;
&lt;p&gt;I remember during my first few months of building my very first website thinking to myself, &lt;q&gt;if it’s supposed to take 10,000 hours of deliberate and purposeful practice to achieve mastery of a craft, I’m on my way there now&lt;/q&gt;. After 18 years, give or take, spent dedicating so much of my time and effort to this craft, I’d like to think I’ve achieved something. &lt;em&gt;Certainly not mastery&lt;/em&gt;, but something worth acknowledging, at least. And at least half that time has been spent under the cover of night.&lt;/p&gt;
&lt;p&gt;There’s something about the quiet and the dark of the midnight hours that helps me find my best ideas and work. I think it’s the solitude, the peacefulness, this sense that the day’s obligations have come and gone, and now &lt;em&gt;this&lt;/em&gt; time is for &lt;em&gt;me&lt;/em&gt;. Whether it’s a quirk about who I am or a reflection of building the habit from my teenage years into my twenties, nighttime is when I feel the most comfortable and energised.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;When COVID struck and I had to work from home—a fact that I don’t totally resent—I went on a &lt;em&gt;lot&lt;/em&gt; of walks. At the time, I lived in East London, close to the beautiful Walthamstow Marshes, where I would take a walk just about every day, if not more often than that.&lt;/p&gt;
&lt;p&gt;Having this time away to enjoy nature, when it &lt;em&gt;wasn’t&lt;/em&gt; the time to be developing or writing or drawing, when it &lt;em&gt;was&lt;/em&gt; the time to hold my partner’s hand and talk about whatever, enjoy the weather, look out for local birds, and think about how old the great trees must be or how cosmically breathtaking all this is, this world we live in… The value of this time and routine of looking forward to the mental time-off cannot be overstated.&lt;/p&gt;
&lt;p&gt;As someone who’s spent my fair share of time living away from my family and loved ones, I can say with serious conviction that distance &lt;em&gt;does&lt;/em&gt; make the heart grow fonder. Just like the first hug from someone who I haven’t seen in far too long, having to step away from my creative endeavours fills me with a real sense of renewal and vigour when the time comes to return to it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Having lived in London for 12 years, I consider myself immensely lucky to have had the opportunity to attend many &lt;a href=&quot;/rsvps/&quot;&gt;meet-ups and conferences&lt;/a&gt;. In 2018, I was even more lucky to have been invited to join the team of organisers for &lt;a href=&quot;https://londonwebstandards.org/&quot;&gt;London Web Standards&lt;/a&gt; and &lt;a href=&quot;https://stateofthebrowser.com/&quot;&gt;State of the Browser&lt;/a&gt;. Challenging and stressful work to be sure, but immensely rewarding.&lt;/p&gt;
&lt;p&gt;Although I tend to be a quiet and shy person—I am unquestionably an introvert—attending conferences have helped me get out of my shell and feel connected to my peers like nothing else. I’ve had the pleasure of meeting so many incredible people and, heartwarmingly, have witnessed myself fill the distinguished role of being considered their friends.&lt;/p&gt;
&lt;p&gt;There’s something too to be said about the wealth of bright and engaging thinkers, bloggers, designers, developers, etc. in the communities I’m proud to be part of. It would feel like counting stars if I were to tally the people I’ve come to know and whose work I now follow, and the value of their words is beyond measure.&lt;/p&gt;
&lt;p&gt;I’ve also had the good fortune to behold scores of life-changing talks. If activity on my website is any evidence, there is very little so motivating and inspiring as being in this space. For every spark of creativity found in the depths of night, plucking away on the keyboard on my own, there are a hundred more that erupt like a lightning storm from being around such amazing people and captivating conferences and meet-ups.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If it can be boiled down at all, my well of creativity springs from a measured temperence. Solitude, space to focus, time away to unfocus, and the everflowing inspiration and motivation that comes from time with friends and diving into the rabbit holes of someone else’s mind all stand shoulder-to-shoulder in this ideal balance.&lt;/p&gt;
&lt;hr&gt;
&lt;div id=&quot;indieweb-carnival&quot;&gt;
	&lt;p&gt;This post is part of &lt;a href=&quot;https://indieweb.org/indieweb-carnival&quot; rel=&quot;external noopener&quot;&gt;May 2024’s IndieWeb Carnival&lt;/a&gt; for the topic, &lt;a href=&quot;https://hamatti.org/posts/indie-web-carnival-may-2024-creative-environments/&quot; rel=&quot;external noopener&quot;&gt;Creative Environments&lt;/a&gt;, hosted by &lt;a href=&quot;https://hamatti.org&quot; rel=&quot;external noopener&quot;&gt;Juha-Matti Santala&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
			
			&lt;hr&gt;
&lt;div id=&quot;weblogpomo&quot;&gt;
	&lt;p&gt;This is post #31 of &lt;a href=&quot;/article/weblogpomo2024-wrap-up/&quot;&gt;#WeblogPoMo2024 / Weblog Posting Month 2024&lt;/a&gt;, a one-month challenge to post as often as possible (daily, ideally) for the duration of May 2024!&lt;/p&gt;
	&lt;p&gt;&lt;a href=&quot;https://web.archive.org/web/20240420081004/https://weblog.anniegreens.lol/weblog-posting-month-2024&quot; rel=&quot;external noopener&quot;&gt;Learn more on Anne Sturdivant’s website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
			
				&lt;hr&gt;
				&lt;p&gt;Thanks for subscribing and reading this post via RSS!&lt;/p&gt;
				&lt;p&gt;You can read &lt;a href=&quot;https://chrisburnell.com/article/strike-while-the-iron-is-hot/&quot;&gt;this post&lt;/a&gt; and others &lt;a href=&quot;https://chrisburnell.com/posts/&quot;&gt;on my website&lt;/a&gt;.&lt;/p&gt;
		</content>
		
		
	</entry>
	
</feed>
