<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Blog Title</title>
  <subtitle>This is a longer description about your blog.</subtitle>
  <link href="https://example.com/kaesluder-blog/feed/feed.xml" rel="self" />
  <link href="https://example.com/kaesluder-blog/" />
  <updated>2025-10-03T00:00:00Z</updated>
  <id>https://example.com/kaesluder-blog/</id>
  <author>
    <name>Your Name</name>
  </author>
  <entry>
    <title>5 October 2025: Thoughts on Documentation vs. Self-Documenting Code</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-10-05-code-not-documentation/" />
    <updated>2025-10-03T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-10-05-code-not-documentation/</id>
    <content type="html">&lt;p&gt;A central problem with the idea of &#39;self-documenting code&#39; is that natural human writing has a rhetorical structure designed to teach the reader basic vocabulary and concepts needed for understanding. Code -- especially DRY (don&#39;t repeat yourself) code -- is non-linear.  As developers maintaining existing code, we&#39;re tasked with jumping into the middle and working backwards to understand what we need before moving on to the next ticket.&lt;/p&gt;
&lt;p&gt;Let&#39;s say I get asked to rewrite the following bit of poetry to a different style:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Wailing her woe, the widow[1] old,&lt;br&gt;
her hair upbound, for Beowulf&#39;s death&lt;br&gt;
sung in her sorrow, and said full oft&lt;br&gt;
she dreaded the doleful days to come,&lt;br&gt;
deaths enow, and doom of battle,&lt;br&gt;
and shame. -- The smoke by the sky was devoured.&lt;br&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Understanding this requires answering several questions.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Who is the widow? (Unstated in text, usually interpreted as Beowulf&#39;s widow.)&lt;/li&gt;
&lt;li&gt;How did Beowulf die? (Killed by a dragon earlier in the same act.)&lt;/li&gt;
&lt;li&gt;Who is he? Why does his death foreshadow doom and battle? (The loss of a community hero leaves it vulnerable to cycles of violence from neighboring groups.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In poetry, these questions are answered organically over the course of three acts. In code, each entity might be separated into separate files or modules. Back-tracing the definition of each can be done through import declarations and LSP features, but this takes critical time. Understanding the lifecycle of each object can be another challenge.&lt;/p&gt;
&lt;p&gt;In nonfiction there&#39;s a similar structure:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Development&lt;/li&gt;
&lt;li&gt;Argument&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each step teaches the reader the &lt;em&gt;specific&lt;/em&gt; concepts, definitions, and meanings used within the work. By the time we get to the conclusions, most issues of ambiguity can be resolved.&lt;/p&gt;
&lt;p&gt;Combining context and intent documentation with clear code can help make code easier to understand.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>6 September 2025: More Nix with home manager</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-09-06-nixos-home-manager/" />
    <updated>2025-09-06T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-09-06-nixos-home-manager/</id>
    <content type="html">&lt;h2 id=&quot;nixos-after-a-week&quot;&gt;Nixos after a week&lt;/h2&gt;
&lt;p&gt;So far so good. Been running a week and not experienced the issue I was having with wake from sleep. I didn&#39;t expect Nixos to become a daily driver, but it is for now.&lt;/p&gt;
&lt;h2 id=&quot;home-manager&quot;&gt;Home-manager&lt;/h2&gt;
&lt;p&gt;One of my goals is to have a consistent set of software and utilities I can easily manage across multiple linux and Macos systems. These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;helix and/or nvim: primary editors&lt;/li&gt;
&lt;li&gt;fd and rg: &amp;quot;easier&amp;quot; replacements for find and grep&lt;/li&gt;
&lt;li&gt;yazi, zellij, zoxide, chezmoi: shell helper utilities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nix is very good at declaring software installs. And home manager built on nix seems like a good solution for keeping that list in my user-space.&lt;/p&gt;
&lt;h3 id=&quot;problem-1-global-or-standalone&quot;&gt;Problem 1: Global or Standalone?&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://nix-community.github.io/home-manager/&quot;&gt;home-manager manual&lt;/a&gt; has instructions for installing home-manager in stand-alone mode and as an extension of the global &lt;code&gt;/etc/nixos/configuration.nix&lt;/code&gt; file. I found out the hard way I can&#39;t do both (documentation is inconsistent and a bit frustrating.) Standalone seems to be more portable. Integration with &lt;code&gt;configuration.nix&lt;/code&gt; might be useful if you want to configure everything in one file.&lt;/p&gt;
&lt;p&gt;The one change I made at the OS level was to add home-manager to &lt;code&gt;environment.systemPackages&lt;/code&gt; in &lt;code&gt;/etc/nixos/configuration.nix/&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;problem-2-portability&quot;&gt;Problem 2: Portability?&lt;/h3&gt;
&lt;p&gt;The recommend determinate MacOS installer uses the &amp;quot;experimental&amp;quot; feature flakes, which pushes me into flakes on Nixos as well. It took me a long time and a lot of fiddling to figure out how to use a flake as part of my home profile. I credit &lt;a href=&quot;https://zero-to-nix.com/&quot;&gt;Zero to Nix&lt;/a&gt; for somewhat figuring out how flakes work, and &lt;a href=&quot;https://jade.fyi/blog/flakes-arent-real/&quot;&gt;Flakes aren&#39;t real and cannot hurt you: a guide to using Nix flakes the non-flake way&lt;/a&gt; for figuring out some perspective.&lt;/p&gt;
&lt;p&gt;If you have flakes enabled as a feature, home-manager creates two boilerplate files, &lt;code&gt;home.nix&lt;/code&gt; and &lt;code&gt;flake.nix&lt;/code&gt;. However neither of these are exactly portable &lt;code&gt;home.nix&lt;/code&gt; includes references to my username and home directory:&lt;/p&gt;
&lt;pre class=&quot;language-nix&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;kaes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/home/kaes&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While flake.nix specifies a system architecture.&lt;/p&gt;
&lt;pre class=&quot;language-nix&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;	system &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;x86_64-linux&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why not use environment variables? Nix with flakes considers environment variable, &amp;quot;impure&amp;quot;, one of those pure-functional language choices that I understand but find annoying.&lt;/p&gt;
&lt;p&gt;So far the hack I&#39;m using is to add third file that only includes the list of packages I want installed. My &lt;code&gt;packages.nix&lt;/code&gt; file is careful not to include any platform-specific code:&lt;/p&gt;
&lt;pre class=&quot;language-nix&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;packages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    btop
    fish
    fzf
    zsh
    helix

    gh
    nodejs_24
    typescript
    typescript&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;language&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;server

		&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

    ripgrep
    fd
    neovim

  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is imported into the boilerplate flake.nix as a module:&lt;/p&gt;
&lt;pre class=&quot;language-nix&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;  outputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
      system &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;x86_64-linux&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;system&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      homeConfigurations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;kaes&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeManagerConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;inherit&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Specify your home configuration modules here, for example,&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# the path to your home.nix.&lt;/span&gt;
        modules &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;token url&quot;&gt;./home.nix&lt;/span&gt;
          &lt;span class=&quot;token url&quot;&gt;./packages.nix&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;# Optionally use extraSpecialArgs&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# to pass through arguments to home.nix&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ideally I want to either auto-detect the system and username or modularize that as a minimal local config. But I&#39;m still a beginner at this.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>31 August 2025: Surfshark and NixOS</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-08-31-nixos-surfshark/" />
    <updated>2025-08-31T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-08-31-nixos-surfshark/</id>
    <content type="html">&lt;h1 id=&quot;nixos-and-surfshark&quot;&gt;NixOS and Surfshark&lt;/h1&gt;
&lt;p&gt;With all the anti-trans news of this week I&#39;m working on bringing up some better internet security, including a vpn subscription to Surfshark. Simultaneously, I&#39;m distro-hopping again looking for a few improvements on some minor issues that individually are not a big deal, but over the months have become more and more frustrating.&lt;/p&gt;
&lt;p&gt;NixOS is worth a shot. There are some configuration and software things I end up setting up in nearly every new computer. My experience at Amazon has sold me on configuration as code. And my personal laptop (Thinkpad E14 Intel Gen. 1) has some quirks that require some special handling. The NixOS config file reminds me of the Freebsd centralized &lt;a href=&quot;https://docs.freebsd.org/en/books/handbook/config/&quot;&gt;config files&lt;/a&gt;. Nix has its own quirks.&lt;/p&gt;
&lt;p&gt;Honestly the most challenging part so far was setting up Surfshark, which uses its own configuration client distributed as snap or flatpak. The first step was setting up flatpak &lt;a href=&quot;https://wiki.nixos.org/wiki/Flatpak&quot;&gt;according to wiki instructions&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-nix&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;  services&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flatpak&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  systemd&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;services&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flatpak&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;repo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    wantedBy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;multi-user.target&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;flatpak &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    script &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;
      flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
    &#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A trickier problem to fix was DNS resolution failures when Surfshark is active. A solution was to disable &lt;code&gt;resolv.conf&lt;/code&gt; in favor of NetworkManager DNS settings. These settings configure the system to use the Surfshark DNS servers set through NetworkManager rather than attempt to use resolv.conf.&lt;/p&gt;
&lt;pre class=&quot;language-nix&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;  services&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resolved&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  networking&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resolvconf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  networking&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;networkmanager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dns &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;systemd-resolved&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Future work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;using NixOS for a while to get a feel for how to manage it&lt;/li&gt;
&lt;li&gt;separating agnostic command-line utils from linux-specific to possibly use nix on other systems&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;kagi&quot;&gt;Kagi&lt;/h1&gt;
&lt;p&gt;Also experimenting with &lt;a href=&quot;https://kagi.com/&quot;&gt;Kagi search&lt;/a&gt;. Never been comfortable with google&#39;s privacy models, their results just keep getting worse, and I like the ability to downrank less-reliable sites and sources that inexplicably get the top results elesewhere.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>23 August 2025: React Reducer Pattern</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-08-23-react-reducer-pattern/" />
    <updated>2025-08-23T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-08-23-react-reducer-pattern/</id>
    <content type="html">&lt;p&gt;Some of my &amp;quot;side&amp;quot; project work includes prototyping with strategies that I&#39;d like to apply at work. We have moderately complex, legacy Vue and React interfaces that are difficult to test for a variety of reasons. One of my maintenance tasks is look for ways to refactor for testability, and some of the themes for React are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Division of application state into multiple &lt;code&gt;useState()&lt;/code&gt; variables.&lt;/li&gt;
&lt;li&gt;Internal React variables are not directly observable without rendering. This makes it difficult to test &amp;quot;business&amp;quot; (data modification) logic separate from UI rendering logic.&lt;/li&gt;
&lt;li&gt;Multiple UI events can trigger state changes.&lt;/li&gt;
&lt;li&gt;Tacit updates and component lifecycle events trigger unexpected results and errors.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The reducer pattern helps to address many of these problems.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kaesluder/ttrpg-tools&quot;&gt;ttrpg-tools&lt;/a&gt; is a side project to create a set of creative brainstorming oracles for &lt;a href=&quot;https://www.tabletopgaming.co.uk/features/a-beginners-guide-to-solo-tabletop-rpgs/&quot;&gt;solo role-playing games&lt;/a&gt;. Many of these games include a mechanic that increases the risk of negative events as play continues. Examples include jenga towers and playing card layouts.&lt;/p&gt;
&lt;p&gt;My experimental mechanic uses solitaire blackjack with the addition of a &amp;quot;resource&amp;quot; pile of cards that can be played at any time. The &amp;quot;dealer&amp;quot; represents a hostile environment, and players will need to balance wins and losses to reach the endgame. My first attempt at managing game state through React&#39;s &lt;code&gt;useState&lt;/code&gt; came out something of a mess, which pushed me to read more about &lt;code&gt;useReducer&lt;/code&gt; as an alternative.&lt;/p&gt;
&lt;pre class=&quot;mermaid&quot;&gt;

erDiagram

		direction LR
		state ||--|| view : configures
		state {
			Card[] playerHand
			Card[] dealerHand
			Card[] resources
			Card[] discardPile
			number playerScore
			number dealerScore
		}

		view ||--|{ actions : sends
		view {
			ul playerHand
			ul dealerHand
			ul resources
			div playerScore
			div dealerScore
			nav turnNav
		}

		actions }|--|| reducer : direct
		actions {
			action setupRound
			action playerTurn
			action playerHit
			action playerStand
			action dealerTurn
			action scoreRound
		}

		reducer ||--|| state : updates
		reducer {
			param state
			param action
			returns state
		}
&lt;/pre&gt;
&lt;p&gt;Currently the game code consists of four main components, each with their own responsibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Game State&lt;/strong&gt;: This is a class that manages the deck of cards, and multiple arrays representing a draw pile, player hand, dealer hand, and discard pile. It also contains functions for updating the total score, and calculating the score for each hand. This bundles almost all of the app state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The View&lt;/strong&gt;: A set of JSX components that is primarily responsible for displaying the current game state as a list of rendered cards and numbers. It also includes an action bar that displays only the actions relevant to each stage, and has minimal event handlers to create &lt;em&gt;actions&lt;/em&gt; for the &lt;em&gt;reducer&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actions&lt;/strong&gt;: Each action is a simple message object that represents a single game events a high level. These are sent to the &lt;em&gt;reducer&lt;/em&gt; via a &lt;em&gt;dispatch&lt;/em&gt; function. A simple action is:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-typescript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;SETUP_ROUND&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Reducer&lt;/strong&gt;: The &lt;em&gt;reducer&lt;/em&gt; is a pure function (not triggering or depending on side effects) that takes the current &lt;em&gt;game state&lt;/em&gt; and an &lt;em&gt;action&lt;/em&gt;. It reads the action, calls the appropriate methods on the &lt;em&gt;game state&lt;/em&gt;, and generates the next &lt;em&gt;game state&lt;/em&gt;. It uses &lt;a href=&quot;https://immerjs.github.io/immer/&quot;&gt;immer&lt;/a&gt; to ensure that the new state is an immutable copy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reducer is simply an extended switch statement. Here&#39;s a minimal example&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Create a reducer function using drawPile as the array iterator.
 * @param {ArrayIterator&amp;lt;Card&gt;} drawPile
 * @returns {(SurvivalBlackjack, ReducerAction) =&gt; SurvivalBlackjack} reducer function
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;makeReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  drawPile&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ArrayIterator&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Card&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// shuffled deck for game&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SurvivalBlackjack&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReducerAction&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; SurvivalBlackjack &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

	&lt;span class=&quot;token comment&quot;&gt;// The reducer starts here as a closure.&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; SurvivalBlackjack&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; action&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReducerAction&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;action&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// start the game drawing resources&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; turnStage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// turnStage is a typescript enum&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;produce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// immer.produce() ensures immutability&lt;/span&gt;
          state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;drawPile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setStage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;turnStage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;drawPile&lt;/code&gt; is an iterator object with its own internal state. I keep it separate from &lt;code&gt;state&lt;/code&gt; to ensure that &lt;code&gt;state&lt;/code&gt; can be immutably handled by both React and immer without complications. This is &#39;passed&#39; into the reducer via a closure. The reducer and initial game state are created early and added to the view with the following line of code:&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;game&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dispatch&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useReducer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;reducer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; initialGame&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is parallel to &lt;code&gt;[state, setState] = useState(initialState)&lt;/code&gt; State properties can be accessed through &lt;code&gt;game.current&lt;/code&gt; for rendering. The view does not directly modify the state, which makes handling events very simple:&lt;/p&gt;
&lt;pre class=&quot;language-typescript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;button onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;dispatch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; sb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;turnStage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;playerTurn &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  Start Game
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;dispatch&lt;/code&gt; calls the &lt;em&gt;reducer&lt;/em&gt;, captures the new game state, and triggers a redraw. The &lt;em&gt;reducer&lt;/em&gt; takes care of round and game management. The &lt;em&gt;state&lt;/em&gt; methods take care of game mechanics. Some of the advantages include:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;MVC organization.&lt;/li&gt;
&lt;li&gt;Game management, game mechanics, and display logic can be tested independently.&lt;/li&gt;
&lt;li&gt;Direct access to state properties for testing.&lt;/li&gt;
&lt;li&gt;Game management and game mechanics are not dependent on any UI framework.&lt;/li&gt;
&lt;li&gt;Interdependent states can be managed together, without worrying about the rendering cycle.&lt;/li&gt;
&lt;/ol&gt;
</content>
  </entry>
  <entry>
    <title>16 August 2025: Reviewing JS Functions</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-08-15-js-functions-review/" />
    <updated>2025-08-16T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-08-15-js-functions-review/</id>
    <content type="html">&lt;h2 id=&quot;functions-review&quot;&gt;Functions Review&lt;/h2&gt;
&lt;p&gt;I&#39;m reviewing basic function and scope rules to help in working with some legacy code. I have my own style but I&#39;m maintaining code that&#39;s written in a different style. See the &lt;a href=&quot;https://google.github.io/styleguide/tsguide.html#features-this&quot;&gt;Google Typescript Style Guide section on &lt;code&gt;this&lt;/code&gt;&lt;/a&gt; for a suggestion to avoid using &lt;code&gt;this&lt;/code&gt; and &lt;code&gt;arguments&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;function-creation&quot;&gt;Function Creation&lt;/h3&gt;
&lt;p&gt;Function Declaration is traditional. &lt;code&gt;this&lt;/code&gt; is bound to parent object (&lt;code&gt;Window&lt;/code&gt; in browser). Name is immediately available.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Function Expression: &lt;code&gt;function&lt;/code&gt; defined but not directly declared with a name. Can only be used as an expression, typically assigned to something else. Similar to a &lt;code&gt;lambda&lt;/code&gt;. &lt;code&gt;this&lt;/code&gt; bound to context of invocation.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Arrow Functions: Concise lambda functions. No declared name. &lt;code&gt;this&lt;/code&gt; bound to nearest ancestor at time of definition.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Class Methods: Functions created as part of a class. &lt;code&gt;this&lt;/code&gt; is bound to the created object.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;adder&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;function-calling&quot;&gt;Function Calling&lt;/h3&gt;
&lt;p&gt;The way functions are called can influence the behavior of the function by changing the context.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Function as function: &lt;code&gt;add(1, 1)&lt;/code&gt; Standard way of calling functions. Returns &lt;code&gt;return&lt;/code&gt; value. &lt;code&gt;this&lt;/code&gt; comes from context parent.&lt;/li&gt;
&lt;li&gt;Function as constructor: &lt;code&gt;obj = new adder()&lt;/code&gt; Creates a new class instance. Implicitly returns new object &lt;em&gt;unless &lt;code&gt;return&lt;/code&gt; statement uses a different Object instance.&lt;/em&gt;  &lt;code&gt;this&lt;/code&gt; is new instance.&lt;/li&gt;
&lt;li&gt;Function as object method: &lt;code&gt;adder.add(1,1)&lt;/code&gt; Returns &lt;code&gt;return&lt;/code&gt; value. &lt;code&gt;this&lt;/code&gt; defaults to instance.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Function.prototype.bind(context)&lt;/code&gt; Creates a bound function in which &lt;code&gt;this&lt;/code&gt; is bound to the specified context. Can also bind additional variables for currying.&lt;/li&gt;
&lt;li&gt;Call and apply: &lt;code&gt;add.call(context, a, b)&lt;/code&gt; and &lt;code&gt;add.apply(context, [a, b])&lt;/code&gt;. Calls function with bound context and arguments.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Explicitly define context outside of instance methods.&lt;/li&gt;
&lt;li&gt;Avoid ambiguity, avoid &lt;code&gt;this&lt;/code&gt; outside of instance methods.&lt;/li&gt;
&lt;li&gt;Use bind or closures when moving a function to a different context.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>3 August 2025: Documentation Wishlist</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-08-03-doc-wishlist/" />
    <updated>2025-08-03T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-08-03-doc-wishlist/</id>
    <content type="html">&lt;h2 id=&quot;documentation-wishlist&quot;&gt;Documentation Wishlist&lt;/h2&gt;
&lt;p&gt;Most of these are things I had to reverse engineer refactoring a wizard component. And I&#39;ll probably forget all of this in six months when I&#39;m asked to do a bugfix.&lt;/p&gt;
&lt;h3 id=&quot;module-level-readme-md&quot;&gt;Module Level (README.md)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;What are the UI frameworks and dependencies, and where can I find documentation?&lt;/li&gt;
&lt;li&gt;What are the build requirements and process?&lt;/li&gt;
&lt;li&gt;What are needed environment variables?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;linked-components-readme-folder-md&quot;&gt;Linked Components (README.folder.md)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;What is the goal or task?&lt;/li&gt;
&lt;li&gt;Is there a component hierarchy? What is it?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;functions&quot;&gt;Functions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Description: What is the business/ui purpose of this function?&lt;/li&gt;
&lt;li&gt;Parameters&lt;/li&gt;
&lt;li&gt;Return values&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Exceptions&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;Side effects/state changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;august-goals&quot;&gt;August Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Get a deeper understanding of how JavaScript handles fundamental variables and functions.&lt;/li&gt;
&lt;li&gt;Continue learning Czech.&lt;/li&gt;
&lt;li&gt;Finish bell hooks, &lt;em&gt;All About Love&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>20 July 2025: Home Music Server Setup</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-07-20-home-audio-server/" />
    <updated>2025-07-20T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-07-20-home-audio-server/</id>
    <content type="html">&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/9iJQQTg5_Kg?si=0_bZniuXGMVmfrEG&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Prepping for a move in October and working on digitizing old cds and setting up a backup server. Not creative work but productive.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Raspberry Pi 4 running &lt;a href=&quot;https://www.raspberrypi.com/software/operating-systems/&quot;&gt;Raspberry Pi OS&lt;/a&gt;. The Pi was left over from another project a few years ago. Setting it up for headless operation was pretty easy following instructions. Using an external HDD and an enclosure, also from an earlier project.&lt;/li&gt;
&lt;li&gt;Basic &lt;a href=&quot;https://ubuntu.com/tutorials/install-and-configure-samba&quot;&gt;Samba&lt;/a&gt; setup with a &lt;code&gt;Music&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.navidrome.org/&quot;&gt;Navidrome&lt;/a&gt; music server.&lt;/li&gt;
&lt;li&gt;Ripping: &lt;a href=&quot;http://littlesvr.ca/asunder/&quot;&gt;Asunder&lt;/a&gt; and &lt;a href=&quot;https://picard.musicbrainz.org/&quot;&gt;Musicbrainz Picard&lt;/a&gt; for tagging/organization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A goal is to move away from depending on streaming services to personal music curation. Some of the discoveries from the archives include some independently published local music by hometown bands like &lt;a href=&quot;https://www.salaamband.com/&quot;&gt;Salaam&lt;/a&gt; and a Live From Bloomington project I&#39;ve not found on the internet. Also discovering CDs I didn&#39;t know we had, like three Beatles collections and a Siouxsie and the Banshees single.&lt;/p&gt;
&lt;p&gt;I started a practice in spring of putting notable songs on a year playlist. It just crossed 100 songs:&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;300&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/playlists/2046291804&amp;color=%23ff5500&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true&amp;visual=true&quot;&gt;&lt;/iframe&gt;&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/kae-sluder&quot; title=&quot;Kae Sluder&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Kae Sluder&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/kae-sluder/sets/2025-daily&quot; title=&quot;2025 Daily&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;2025 Daily&lt;/a&gt;&lt;/div&gt;
</content>
  </entry>
  <entry>
    <title>13 July 2025: Vitest Mocking</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-07-13-mocking-js/" />
    <updated>2025-07-13T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-07-13-mocking-js/</id>
    <content type="html">&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/ZKCGilFFFPk?si=KzYO6xsQ8G_Uemka&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Some notes on vitest after working out a few things. Needed to look beyond the cookbook examples to why vitest and jest mocks work.&lt;/p&gt;
&lt;h3 id=&quot;modules-are-objects&quot;&gt;Modules are objects&lt;/h3&gt;
&lt;p&gt;Modules can be structured as objects with method variables. A simple module with one function (not complete):&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// /src/mosaicUtils.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mosaicFetch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/mosaic/index.json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; imageList&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; imageList&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Can be mocked as:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// App.test.ts&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; exampleData &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;15th_century_egyptian_anatomy_of_horse.jpg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;163_of_&#39;Five_Years_in_Siam_from_1891_to_1896_..._With_maps_and_illustrations_by_the_author&#39;_(11249062174).jpg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token string&quot;&gt;&quot;640px-Avon_Fantasy_Reader_8.jpg&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// Argument 1: source of the old module&lt;/span&gt;
vi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;../src/mosaicUtils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// set up the mock function to return the data&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mockMosaicFetch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; vi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; exampleData&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// return a new module&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    mosaicFetch&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; mockMosaicFetch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;vi-mock-and-vitest-replace-the-old-module&quot;&gt;&lt;code&gt;vi.mock()&lt;/code&gt; and vitest &amp;quot;replace&amp;quot; the old module&lt;/h2&gt;
&lt;p&gt;The utility library is imported with:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; mosaicFetch &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../src/mosaicUtils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;vitest intercepts this import call and replaces the entire module, not just mosaicFetch.&lt;/p&gt;
&lt;h2 id=&quot;mocking-one-or-some-objects-in-a-module&quot;&gt;Mocking one or some objects in a module&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;vi.mock()&lt;/code&gt; replaces the entire module, not just a single function. Use &lt;code&gt;vi.importActual(&lt;/code&gt;sourceFile`) to include other objects without modification.&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// from https://vitest.dev/api/vi.html#vi-importactual&lt;/span&gt;
vi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./example.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; originalModule &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; vi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;importActual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./example.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;originalModule&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; get&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; vi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;vi-spyon-watches-a-single-method-getter-or-setter&quot;&gt;&lt;code&gt;vi.spyOn()&lt;/code&gt; watches a &lt;em&gt;single&lt;/em&gt; method, getter or setter&lt;/h2&gt;
&lt;p&gt;A spy can be used to watch a single function in a module with optional replacement. See &lt;a href=&quot;https://vitest.dev/api/vi.html#vi-spyon&quot;&gt;documentation&lt;/a&gt;.
The same mock can be made as:&lt;/p&gt;
&lt;pre class=&quot;language-ts&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-ts&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; mosaicUtils &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;../src/mosaicUtils&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

vi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;spyOn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mosaicUtils&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;mosaicFetch&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mockImplementation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; exampleData&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, spyOn can be used to count how many times the existing function is called during the test.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>5 July 2025: Strudel, New Role, and Mermaid Diagrams in Eleventy</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-07-05-strudel-4th/" />
    <updated>2025-07-05T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-07-05-strudel-4th/</id>
    <content type="html">&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/9ivqFkLYxp8?si=nmCMHwGYycWJhFhw&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;strudel-learning-to-understand-cat-seq-and-stack&quot;&gt;Strudel: Learning to Understand cat, seq, and stack&lt;/h2&gt;
&lt;p&gt;I&#39;ve been experimenting with music programming languages. This week it&#39;s been &lt;a href=&quot;https://strudel.cc/&quot;&gt;strudel&lt;/a&gt; which is built around the concept of a cycle—typically either a measure or a beat in most music notation.&lt;/p&gt;
&lt;p&gt;Strudel interprets strings that represent sequences of notes, drumbeats, or other events. &amp;quot;c4 e4 g4&amp;quot; plays three notes of a c-major chord. But a tricky matter is determining how the notes should be interpreted. Does that fit in one cycle (fast) or three cycles (slow)? After a fair bit of frustration, I learned the following concepts for strudel. Something that tripped me up here was that the Strudel docs teach the abbreviated notation first.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cat&lt;/code&gt; (&lt;code&gt;&amp;quot;&amp;lt;c4 e4 g4&amp;gt;&amp;quot;&lt;/code&gt;): treats each item in the list as a separate cycle. This can be used to create extended phrases or songs. This is also known as &lt;code&gt;slowcat&lt;/code&gt; if you&#39;re using the long notation.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;seq&lt;/code&gt; (&lt;code&gt;&amp;quot;c4 e4 g4&amp;quot;&lt;/code&gt;): processes each item in the list inside one cycle. This is used to push notes inside a measure. (Also known as &lt;code&gt;fastcat&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stack&lt;/code&gt; (&lt;code&gt;&amp;quot;c4, e4, g4&amp;quot;&lt;/code&gt;): process each event in parallel and at the same time. Used for chords, but also having multiple instruments playing together.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Patterns can be nested inside each other. The example below is a simple Strauss waltz loop that consists of four sequences &lt;code&gt;[bd rim rim]&lt;/code&gt; inside a cat &lt;code&gt;&amp;lt;[bd rim rim] ...&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;iframe src=&quot;https://strudel.cc/#c2V0Y3BtKDE4MC8zKQpzb3VuZCgiPFtiZCByaW0gcmltXSBbYmQgcmltIHJpbV0gW2JkIHJpbSByaW1dIFtyaW0gfiB%2BXT4iKQo%3D&quot; width=&quot;600&quot; height=&quot;200&quot;&gt;&lt;/iframe&gt;
&lt;p&gt;Here&#39;s the logic in flowchart form.&lt;/p&gt;
&lt;pre class=&quot;mermaid&quot;&gt;
flowchart TD
    Start[&quot;I want to play notes...&quot;]
    Choice1{&quot;... at the same time?&quot;}
    Stack[&quot;stack&quot;]
    Choice2{&quot;... over multiple cycles?&quot;}
    Cat[&quot;cat&quot;]
    Seq[&quot;seq&quot;]

    Start --&gt; Choice1
    Choice1 -- Yes --&gt; Stack
    Choice1 -- No --&gt; Choice2
    Choice2 -- Yes --&gt; Cat
    Choice2 -- No --&gt; Seq
&lt;/pre&gt;
&lt;h2 id=&quot;new-role&quot;&gt;New Role&lt;/h2&gt;
&lt;p&gt;Starting in October I&#39;ll transition from contract to full time software development at Prime Revenue focused on JS. It&#39;s been a four-year journey and I&#39;m very thankful for all the people at Ada Developer&#39;s Academy, Amazon, and Prime Revenue who have given me valuable support, advice, and learning opportunities.&lt;/p&gt;
&lt;h2 id=&quot;getting-mermaid-on-this-page&quot;&gt;Getting Mermaid on This Page&lt;/h2&gt;
&lt;p&gt;In the template &lt;code&gt;base.njk&lt;/code&gt;, add the code to load and run the mermaid api.&lt;/p&gt;
&lt;pre class=&quot;language-nunjucks&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-nunjucks&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;module&quot;&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;eleventy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;ignore&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;mermaid&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a paired shortcode in &lt;code&gt;eleventy.config.js&lt;/code&gt; to explicitly format the code block:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;eleventyConfig&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addPairedShortcode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;mermaid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;pre class=&quot;mermaid&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;content&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;lt;/pre&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use the shortcode to wrap the mermaid code in a &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; block in the post markdown.&lt;/p&gt;
&lt;pre class=&quot;language-md&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-md&quot;&gt;{% mermaid %}
flowchart TD
    Start[&quot;I want to play notes...&quot;]
    Choice1{&quot;... at the same time?&quot;}
    Stack[&quot;stack&quot;]
    Choice2{&quot;... over multiple cycles?&quot;}
    Cat[&quot;cat&quot;]
    Seq[&quot;seq&quot;]

&lt;span class=&quot;token code keyword&quot;&gt;    Start --&gt; Choice1
    Choice1 -- Yes --&gt; Stack
    Choice1 -- No --&gt; Choice2
    Choice2 -- Yes --&gt; Cat
    Choice2 -- No --&gt; Seq&lt;/span&gt;
{% endmermaid %}&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>28 June 2025: Shuffle and Backup</title>
    <link href="https://example.com/kaesluder-blog/blog/2025-06-28-shuffle-and-backup/" />
    <updated>2025-06-28T00:00:00Z</updated>
    <id>https://example.com/kaesluder-blog/blog/2025-06-28-shuffle-and-backup/</id>
    <content type="html">&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/-CR628yT7aE?si=kFxctrIzZ27sry7c&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;visual-card-shuffle&quot;&gt;Visual Card Shuffle&lt;/h2&gt;
&lt;p&gt;Continuing my exploration of &lt;a href=&quot;https://example.com/kaesluder-blog/posts/cut-ups-krell/&quot;&gt;cut-ups&lt;/a&gt; my sourcing interesting images from Wikimedia Commons and the Met Open Access collection. Then I shuffle the images and arrange nine of them on a grid:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source type=&quot;image/avif&quot; srcset=&quot;https://example.com/kaesluder-blog/blog/2025-06-28-shuffle-and-backup/ssn3u3mX8W-834.avif 834w&quot;&gt;&lt;source type=&quot;image/webp&quot; srcset=&quot;https://example.com/kaesluder-blog/blog/2025-06-28-shuffle-and-backup/ssn3u3mX8W-834.webp 834w&quot;&gt;&lt;img loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://example.com/kaesluder-blog/blog/2025-06-28-shuffle-and-backup/ssn3u3mX8W-834.png&quot; alt=&quot;screenshot of web interface with photo tiles arranged in a 3 by 3 grid&quot; width=&quot;834&quot; height=&quot;721&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Pain points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Image manipulation in css: My original idea was to use css to zoom in on random sections of each image, hoping for some creative serendipity. After an evening struggling with this. I gave up and started curating square tiles manually. The result is a bit creatively more satisfying, and it&#39;s a nice easy low-bandwidth task.&lt;/li&gt;
&lt;li&gt;Typescript: Kept getting warnings on a helper function that returns a JSX.Element type. Documentation on how to deal with it is inconsistent. Is it handled automatically by a vite setting (and if so, why is it being flagged)? Basic conclusion is that I need to learn a lot more about how to work with Typescript before picking it up for projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In-page documentation&lt;/li&gt;
&lt;li&gt;A keep-and-draw mechanic with limited keeps&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;backups&quot;&gt;Backups&lt;/h2&gt;
&lt;p&gt;A few months ago the disk that had my only copy of multiple desktop backup failed. My thought process in procrastinating on new backups was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Essential work is on github&lt;/li&gt;
&lt;li&gt;Most of those backups were ephemera&lt;/li&gt;
&lt;li&gt;I rarely re-read books&lt;/li&gt;
&lt;li&gt;I&#39;ve not looked at that stuff in a while&lt;/li&gt;
&lt;li&gt;Well crap, my sewing patterns are gone.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last point pushed me to set up backups on the Thinkpad T420 I mentioned earlier as a backup system. It was mostly easy sailing once I specified full paths and set up my ssh keys. I used the Pika front end for BackupBorg to make everything work.&lt;/p&gt;
&lt;h2 id=&quot;reading-quote&quot;&gt;Reading Quote&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Taking responsibility does not mean that we deny the reality of institutional injustice. For example, racism, sexism, and homophobia all create barriers and concrete instances of discrimination. Simply taking responsibility does not mean we can prevent discriminatory acts from happening. But we can choose how we respond to acts of injustice. Taking responsibility means that in the face of barriers we still have the capacity to invent our lives, to shape our destinies in ways that maximize our well-being. Every day we practice this shape shifting to cope with realities we cannot easily change.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;bell hooks, &amp;quot;All About Love,&amp;quot; Chapter 4&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
</feed>