<rss version="2.0">
<channel>
<title>alanwsmith.com</title>
<link>https://www.alanwsmith.com/</link><item>
<title><![CDATA[Photoshop's Content-Aware Fill Ain't Half Bad]]></title>
<link>https://www.alanwsmith.com/en/3f/go/ss/jn/</link>
<pubDate>Thu, 18 Jun 2026 17:28:00 -0400</pubDate>
<guid>19bdb372-c44a-53bf-8853-4761c3d38c5f</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow">


<p>Discussing generative AI is fraught<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-images-text"
    id="footnote-images-link"
    >images</a></sup>. It's easy to make binary distinctions. Love it, hate it. No in-between.</p>


<p>I'm mostly against it for images. Fully admitting some look dope, the fact that it's making it harder for artists to make a living is too much<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-time-text"
    id="footnote-time-link"
    >time</a></sup>. Not to mention the resource usage<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-energy-text"
    id="footnote-energy-link"
    >energy</a></sup>.</p>


<p>There <em class="emphasis-shorthand-span">is</em> one place I'm fine with it: background generation.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Behind the Scenes</h2>


<p>I've taken to playing Magic: The Gathering. The crew I play with is spread across multiple countries. We use Tabletop Simulator<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-tts-text"
    id="footnote-tts-link"
    >tts</a></sup> for our virtual play surface. The app lets you customize play mats and card backs. I'm collecting a bunch of images for them<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-playmats-text"
    id="footnote-playmats-link"
    >playmats</a></sup>.</p>


<p>Take this awesome bear from The Smithsonian's public domain collection<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-bear-text"
    id="footnote-bear-link"
    >bear</a></sup>.</p></section>




<section class="image-section">
    <img 
      class="image"
      src="/neo-files/images/original-bear/original-bear.avif" 
      alt="A photo of a small, plaster sculputer of a bear made by Edward Kemeys sometime between 1871-1894. It looks a little like bronze with the bear sittting on a little platform looking down like it's looking into a river for salmon. The background is black at the top and behind most of the bear before transitioning to white on the surface. The image has roughly a 4 to 3 ratio." 
      />
</section>


<section class="p-section default-flow">


<p>Wonderful. But, not the right aspect ratio. Play mats are 16:9. I don't know what the bear is. Just that it ain't that. I'd been dropping images into the middle of black backgrounds to cover the size. Something like this:</p></section>




<section class="image-section">
    <img 
      class="image"
      src="/neo-files/images/bear-with-black-background/bear-with-black-background.avif" 
      alt="The same image of the bear with black bars on either side of it to extend the width so the image has a 16 to 9 aspect ratio." 
      />
</section>


<section class="p-section default-flow">


<p>Not bad. Better than stretching the image. But, not great.</p>


<p>Then, I remembered Content-Aware Fill<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-fill-text"
    id="footnote-fill-link"
    >fill</a></sup>.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Better Backing</h2>


<p>Content-Aware Fill is a Photoshop feature. It attempts to use existing parts of an image to generate something that looks reasonable for new areas. It uses machine learning to figure out which pixels go where. "Machine learning" being what AI was called before AI became the buzz word.</p>


<p>A few clicks, and we get this:</p></section>




<section class="image-section">
    <img 
      class="image"
      src="/neo-files/images/filled-background-bear/filled-background-bear.avif" 
      alt="A wider image of the same bear with the background extended to the sides to expand the aspect ratio to 16 by 9." 
      />
</section>


<section class="p-section default-flow">


<p>16:9 but with a background that matches the original instead of black bars.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Close Enough for Jazz</h2>


<p>It' not perfect. The gradient between dark and light is splotchy on the left side. The hard edge of the shadow on the right maybe cuts off a little quick. I could clean it up. Make it impossible to tell where the original ends and the addition begins. That would take time and effort. Content-Aware Fill took a few clicks and about 20 seconds.</p>


<p>Hard to beat.</p>


<p>-a</p></section>


</div>
  <div class="end-block">
          <section class="endnotes-section default-flow xxlarge-bottom-margin">
            <h3 class="back-matter">Endnotes</h3>
            <div class="xxlarge-flow">
          
        


<section class="endnote-section default-flow">
  


<p>A quick video showing how to use Content-Aware Fill.</p>


<section class="youtube-section default-flow"><youtube-player 
:video="zrDgfm7VJpQ"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/zrDgfm7VJpQ" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="p-section default-flow">


<p>More videos should be like this. 24 seconds of mouse movement showing you exactly where to click. Most videos aren't even out of their "Hey, Guy!" intro in that time.</p></section>
</section>





<section class="endnote-section default-flow">
  


<p>Here's Kermit with another example of extending an image with a more complicated visual to match.</p>


<p>Original:</p>




<section class="image-section">
    <img 
      class="image"
      src="/neo-files/images/original-kermit/original-kermit.avif" 
      alt="Kermit The Frog sitting on a round blue floaty on top of paper cutout waves. He's holding yellow sunglasses up in one hand and a red cup in the other." 
      />
</section>


<section class="p-section default-flow">


<p>Content-Aware Filled:</p></section>




<section class="image-section">
    <img 
      class="image"
      src="/neo-files/images/filled-background-kermit/filled-background-kermit.avif" 
      alt="The same image of Kermit, but with the background extended with content-aware fill to make the image 16 by 9." 
      />
</section>


<section class="p-section default-flow">


<p>It doesn't do the greatest of jobs. The extended waves are all blurry and it emphasizes the darkening gradient of the background. I'll adjust the lighting a little but it's way better than black bars with nothing more than this.</p></section>
</section>



            </div>
          </section>
    
        <section class="footnotes-section flow">
            <h3 class="back-matter">Footnotes</h3>
        
        


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-images-link">
        <span id="footnote-images-text">images &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div></div>
    <div class="default-flow">


<p>I'm referring here to image generation. Code and prose generation are separate topics.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-time-link">
        <span id="footnote-time-text">time &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div></div>
    <div class="default-flow">


<p>Check back in a few years. I have a feeling I'm in the same position from a couple decades ago when professional photographers refused to use digital/phone cameras. There's something different with AI since it's a different category of tool that makes the actual images, but still.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-energy-link">
        <span id="footnote-energy-text">energy &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div></div>
    <div class="default-flow">


<p>Everything I understand about generative AI is that it takes a lot of energy and</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-playmats-link">
        <span id="footnote-playmats-text">playmats &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://al9000.com/tts"><strong>My virtual play mats</strong></a></div>
    <div class="default-flow">


<p>The mats (and card backs) I'm collecting to use during rounds.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-tts-link">
        <span id="footnote-tts-text">tts &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://www.tabletopsimulator.com/"><strong>Tabletop Simulator</strong></a></div>
    <div class="default-flow">


<p>It make my fans spin up like all hell. Small price to pay for being able to play with a globally diverse group. The feature set built in for Magic is great. (It's also hackable. I haven't gone down that rabbit hole yet.)</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-bear-link">
        <span id="footnote-bear-text">bear &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://www.si.edu/object/grizzly-bear-sitting:saam_1895.10.2"><strong>Grizzly Bear Sitting from The Smithsonian</strong></a></div>
    <div class="default-flow">


<p>Just a little guy.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-fill-link">
        <span id="footnote-fill-text">fill &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://www.adobe.com/in/products/photoshop/content-aware-fill.html"><strong>Content-Aware Fill</strong></a></div>
    <div class="default-flow">


<p>The marketing page focuses more on removing things. That works well too.</p></div>
    
  </div>


</section>
        </section>
    </div>
]]></description> 
</item><item>
<title><![CDATA[Free Image/Art Resources]]></title>
<link>https://www.alanwsmith.com/en/3e/c5/mz/ls/</link>
<pubDate>Mon, 25 May 2026 10:44:30 -0500</pubDate>
<guid>6115bdb0-0a70-57fd-b1d0-cbce196f82d5</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow"></section>


<section class="list-section default-flow"><h2>Some Links</h2><ul class="default-flow">


<li class="default-flow">

<a href="https://www.artic.edu/collection?is_public_domain=1" > Art Institute of Chicago</a>
 via their 
<a href="https://www.artic.edu/open-access/open-access-images" > open access images</a>
</li>


<li class="default-flow">

<a href="https://www.biodiversitylibrary.org/" > Biodiversity Heritage Library</a>
</li>


<li class="default-flow">

<a href="https://www.clevelandart.org/art/collection/search?i=1&limit=8&cc0=1" > The Cleveland Museum of Art</a>
 via their 
<a href="https://www.clevelandart.org/open-access" >Open Access Images</a>
</li>


<li class="default-flow">

<a href="https://www.getty.edu/art/collection/search?open_content=true" > Getty Museum Collection</a>
 via their 
<a href="https://www.getty.edu/news/download-edit-print-your-favorite-getty-artwork-for-free/" >free artwork collection</a>
</li>


<li class="default-flow">

<a href="https://www.europeana.eu/en/collections" > Common European Data Space for Cultural Heritage</a>
</li>


<li class="default-flow">

<a href="https://www.si.edu/openaccess" > Smithsonian Open Access</a>
</li>


<li class="default-flow">

<a href="https://collections.discovernewfields.org/" > The Indianapolis Museum of Art Collection</a>
</li>


<li class="default-flow">

<a href="https://www.getty.edu/projects/open-content-program/faqs/" > Getty Open Content</a>
</li>


<li class="default-flow">

<a href="https://collections.lacma.org/search" > Los Angeles County Museum of Art</a>
</li>


<li class="default-flow">

<a href="https://www.metmuseum.org/art/collection/search#!?searchField=All&showOnly=openAccess&sortBy=relevance&offset=0&pageSize=0" > The Met</a>
 via their 
<a href="https://www.metmuseum.org/hubs/open-access" > Open Access images</a>
</li>


<li class="default-flow">

<a href="https://mohistory.org/research/photographs-prints/photograph-print-collection-guides-and-finding-aids" > Missouri Historical Society</a>
</li>


<li class="default-flow">

<a href="https://www.moma.co.uk/public-domain-images/" > MoMa.co.uk</a>
</li>


<li class="default-flow">

<a href="https://www.nga.gov/artworks/free-images-and-open-access" > National Gallery of Art</a>
</li>


<li class="default-flow">

<a href="https://www.slam.org/public-domain-and-open-access/" > Saint Louis Art Museum</a>
</li>


<li class="default-flow">

<a href="https://www.parismuseescollections.paris.fr/en" > Paris Museum</a>
</li>


<li class="default-flow">

<a href="https://art.thewalters.org/" > The Walters Art Museum</a>
</li>


<li class="default-flow">

<a href="https://commons.wikimedia.org/wiki/Main_Page" > Wikimedia Commons</a>
</li>


<li class="default-flow">

<a href="https://britishart.yale.edu/" > Yale Center for British Art</a>
</li>


<li class="default-flow">

<a href="https://artgallery.yale.edu/collection" > Yale University Art Gallery</a>
</li>


<li class="default-flow">

<a href="https://pdimagearchive.org/" > Public Domain Image Archive</a>
</li>


<li class="default-flow">

<a href="https://whitney.org/open-access" > Whitney</a>
</li>


<li class="default-flow">

<a href="https://nmaahc.si.edu/explore/initiatives/nmaahc-open-access" > National Museum of African American History and Culture</a>
</li>


<li class="default-flow">

<a href="https://high.org/" > High Museum of Art</a>
</li>


<li class="default-flow">

<a href="https://www.moma.org/" > MOMA</a>
</li>


<li class="default-flow">

<a href="https://www.jstor.org/site/collection-list/" > JSTOR</a>
</li>


<li class="default-flow">

<a href="https://images.nasa.gov/" > NASA Images</a>
</li>


<li class="default-flow">

<a href="https://www.flickr.com/photos/nasahqphoto/" > NASA Images on Flickr</a>
</li>


<li class="default-flow">

<a href="https://www.brooklynmuseum.org/" > Brooklyn Museum</a>
</li>


<li class="default-flow">

<a href="https://www.artmuseums.go.jp/en" > National Museum of Art</a>
</li>


<li class="default-flow">

<a href="https://www.loc.gov/free-to-use/" > Library of Congress</a>
</li>


<li class="default-flow">

<a href="https://artvee.com/" > Artvee</a>
 - a curator</li>


<li class="default-flow">

<a href="https://www.heritagetype.com/pages/free-vintage-illustrations" > Heritage Library</a>
 - a curator</li></ul>
</section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Still Looking</h2>


<p>If you've got other good ones with open access policies, 
<a href="https://bsky.app/profile/alanwsmith.com" >let me know</a>
.</p>


<p>-a</p></section>


</div>
  <div class="end-block">
          <section class="endnotes-section default-flow xxlarge-bottom-margin">
            <h3 class="back-matter">Endnotes</h3>
            <div class="xxlarge-flow">
          
        


<section class="endnote-section default-flow">
  


<p>There are some sites like 
<a href="https://unsplash.com/" >unsplash</a>
 but I'm not putting them on this list. They have some free images but are largely ads for paid stock image sites.</p>


<p>There are also some sites out there that have deceiving ads trying to get folks to download and install various pieces of nefarious software. I'm not linking to those.</p>
</section>
            </div>
          </section>
    </div>
]]></description> 
</item><item>
<title><![CDATA[Stress Writing]]></title>
<link>https://www.alanwsmith.com/en/3d/ev/2d/mv/</link>
<pubDate>Sun, 3 May 2026 20:57:17 -0500</pubDate>
<guid>8279bbac-c591-54b4-8883-430a13a8ed72</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow">


<p>Normally, I write to think.</p>


<p>Today, we're trying something new.</p>


<p>Writing not to think.</p>


<p>Or, really, writing to not think about things that are stressing me out.</p>


<p>I'm one of the least stressed folks I know. I can go with pretty much any flow without much fanfare.</p>


<p>Thresholds exist. I'm on the other side of one.</p>


<p>There are some ideas floating around in my head. Things I could work on to draw my focus and give some reprieve. They require a certain amount of spoons. I ain't got them.</p>


<p>So, this is an experiment. A stream of consciousness thing to try to release some pressure.</p>


<p>It's working.</p>


<p>So, I'm just gonna keep writing.</p>


<p>I'm trying to decide if I want to get into what's stressing me out or not. Probably not. Not because it's something I want to avoid posting about. It's because it's something I'd want to get the words right for.</p>


<p>Writing mode with a capital "W".</p>


<p>Editing too. It takes me a bunch of passes to get things shaped the way I want.</p>


<p>There's none of that here.</p>


<p>Forward, always forward.</p>


<p>That's a quote from somewhere I think.</p>


<p>Writing this makes me want to start recording podcast episodes again. I just turn on a mic and let my mind wander. Same thing I'm doing now.</p>


<p>Kicking back into the audio has been on my mind for a while. I haven't pulled the trigger. Mainly, because I want to move the old stuff and redo it and get thing line up.</p>


<p>That's one of those perfection paralysis things though. I just need to rip one and let it fly.</p>


<p>(Okay, okay, writing is helping me think. That's not the purpose of this post. Just a natural side effect.)</p>


<p>Status Update: Everyone else just went to bed. Now I can sit in the dark and write. It's so much nicer. It's that whole "introvert recharge thing".</p>


<p>Anyway, this is helping way more that I would have expected. I can feel the tension easing out of my shoulders.</p>


<p>by the way: take 5 seconds and relax your shoulders.</p>


<p>better, right?</p>


<p>I know it is for me.</p>


<p>-a</p></section>


</div>
  <div class="end-block">
          <section class="endnotes-section default-flow xxlarge-bottom-margin">
            <h3 class="back-matter">Endnotes</h3>
            <div class="xxlarge-flow">
          
        


<section class="endnote-section default-flow">
  


<p>I ended up making one edit pass on this. A single run from top to bottom. That's basically nothing for me. You can watch a bit of my crafting a reponse to a tweet to get an idea of what I mean. (The music kicks in at 30sec.)</p>


<section class="youtube-section default-flow"><youtube-player 
:video="vqcendFpmeg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/vqcendFpmeg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>
</section>



            </div>
          </section>
    </div>
]]></description> 
</item><item>
<title><![CDATA[The AI Phone Assault Has Begun]]></title>
<link>https://www.alanwsmith.com/en/3d/bb/ci/ro/</link>
<pubDate>Sat, 2 May 2026 13:10:53 -0500</pubDate>
<guid>cdf0edbf-4e06-5ea7-b9c1-b763b604500c</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow">


<p>I'm visiting a friend of the over 65 variety. His name isn't Ron, but that's what I'm going to call him. His mind used to be very sharp. It's dulled a lot this year. He's a naturally trusting soul and I'm worried sick about him.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Incoming</h2>


<p>Ron told me his biggest frustration is the number of spam calls he gets every day. He doesn't answer calls from unknown numbers outside his area code. He generally picks up the local ones, though.</p>


<p>I saw it happen twice in an hour while we were hanging out. Ron's hard of hearing. His phone volume is up so high it might as well be on speaker. I heard both sides of the conversations.</p>


<p>Each times, they were AI bots.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Two Strikes</h2>


<p>The calls sounded like they were from friendly women. The introductions were both some form of "we've noticed you have unused Medicaid benefits and want to make sure you're not missing out."</p>


<p>Ron ended the first call quickly. He recognized it as spam, but not a bot. He stayed on the second one longer. It started asking questions with no prelude. He just started answering them. He didn't have time to get his guard up.</p>


<p>I stopped him as soon as I realized he hadn't clocked the nature of the call. After telling him it was an AI bot, he asked how I knew. I couldn't offer much beyond just having experience and learning how they sound.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Medicaid is the New Car Warranty</h2>


<p>Spam robo-calls were easy to spot when they were recorded messages telling you to press one because your car warranty had expired. Now that they interact, they're way more dangerous.</p>


<p>You can get an idea about why from this video demonstrating a call:</p></section>


<section class="youtube-section default-flow"><youtube-player 
:video="r_Iy0xZ1CYY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/r_Iy0xZ1CYY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="p-section default-flow">


<p>To be clear, there is no woman on the other end of that call. The voice and the words it says are completely computer generated.</p>


<p>The voice in the video sounds exactly like the bot that called Ron. The bot in video says it's AI in its introduction. The one that called Ron did not. I don't know what the play was, but anything that starts off by implying it has access to your Medicaid information is absolutely a scam.</p></section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Playing Defense</h2>


<p>This shit is gonna get worse. The bots are brand new and they're already convincing. They'll get better and cheaper to deploy. The onslaught will increase.</p>


<p>The bots will also pull in increasing amounts of personal information about their targets. They'll use it to be even more effective at manipulation.</p>


<p>There's nothing realistic we can do to stop them. The best we can do is work to protect ourselves. Currently, that looks like this:</p></section>


<section class="olist-section default-flow">
  <ol class="default-flow">


<li class="default-flow">
Auto-forward every incoming call from an unknown number directly to voice mail.</li>


<li class="default-flow">
Start from the assumption that every voice mail form an unknown number is malicioius.</li>


<li class="default-flow">
Don't call the number back drirectly even if it's from a company/bank/service you use. Instead, find the companies phone number on their website and use that to contact them.</li></ol>
</section>


<section class="p-section default-flow">


<p>I helped Ron set up his phone. I suggest you do the same. Then, help friends and family who might not know how to do it on their own.</p>


<p>-a</p></section>


</div>
  <div class="end-block">
          <section class="endnotes-section default-flow xxlarge-bottom-margin">
            <h3 class="back-matter">Endnotes</h3>
            <div class="xxlarge-flow">
          
        


<section class="endnote-section default-flow">
  


<p>Preying on the elderly is nothing new. These bots are just the latest iteration. They're going to be particularly nasty. But, senior citizens won't be the only ones targeted. We'll all have to deal with them.</p>
</section>


<section class="endnote-section default-flow">
  


<p>The use of the "um" in the opening line in the video is particularly insidious. The computer isn't struggling to find the next word. It's an explicit deceit included to trick us into thinking we're talking to a person.</p>
</section>


<section class="endnote-section default-flow">
  


<p>Here's 
<a href="https://support.apple.com/en-au/guide/iphone/iphe4b3f7823/ios" >the iPhone page</a>
 showing how to set things up. It's done by following the instruction in the "Screen or silence unknown numbers" section and choosing "Silence: Calls from unsaved numbers will be silenced, sent to voicemail, and appear in the Recents list."</p>


<p>I haven't found an official support page for how to do it on Android devices. You'll need to look up your specific phone for how to do it.</p>
</section>


<section class="endnote-section default-flow">
  


<p>AI is a giant topic. I have different thoughts about different parts of it. Some of those thoughts are complicated. When it comes to this type of shit, that's not the case. I can't think of a single improvement that'll be added to the world by deploying AI spam bots. Even if they aren't outright scams.</p>


<p>What I could get behind is AI being used on our side. Bots that provide protection from spam and scams.</p>


<p>Someone go build that.</p>
</section>


<section class="endnote-section default-flow">
  


<p>I've found the 
<a href="https://www.razmobility.com/solutions/memory-cellphone/" >RAZ Memory Phone</a>
. It's designed specifically for seniors and folks with cognitive issues. Basically, it lets you lock down the phone so that only numbers in the contact list can call/text both in or out. The phone is managed via an app on a caregiver's phone.</p>


<p>Dealing with things like one time login code text messages presents issues, but I'm going to suggest John and his family give it a shot.</p>


<p>It's basically just having to make a decision about where to place your mark on the security/convenience continuum.</p>
</section>
            </div>
          </section>
    </div>
]]></description> 
</item><item>
<title><![CDATA[Sleep for a Time in Rust's tokio]]></title>
<link>https://www.alanwsmith.com/en/3b/ql/f1/bk/</link>
<pubDate>Fri, 3 Apr 2026 09:56:20 -0400</pubDate>
<guid>e6fc8880-9ef5-5e14-8dd6-775da46df74c</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow"></section>


<section class="code-section default-flow"><pre class="code-block"><code><span class="aws-code-block-marker"></span><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">tokio<span class="punctuation accessor rust">::</span></span><span class="meta path rust">time<span class="punctuation accessor rust">::</span></span><span class="meta block rust"><span class="punctuation section block begin rust">{</span>sleep<span class="punctuation separator rust">,</span> Duration</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="support function rust">sleep</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Duration<span class="punctuation accessor rust">::</span></span>from_millis<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">100</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.await<span class="punctuation terminator rust">;</span>
<span class="aws-code-block-marker"></span><span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>100 ms have elapsed<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span></span></code></pre></section>


</div>
  <div class="end-block"></div>
]]></description> 
</item><item>
<title><![CDATA[Open Videos - March 30, 2026]]></title>
<link>https://www.alanwsmith.com/en/3b/fg/fx/oe/</link>
<pubDate>Mon, 30 Mar 2026 08:13:37 -0400</pubDate>
<guid>ec57e003-dce0-5937-beeb-23a720d86922</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow">


<p>The current set of video tabs I have open right now. Archiving them here and closing them in the browser.</p></section>


<section class="youtube-section default-flow"><youtube-player 
:video="S_D9WqWGhHw"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/S_D9WqWGhHw" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="9Dg8w6gk4cE"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/9Dg8w6gk4cE" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="5UMygviK2tA"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/5UMygviK2tA" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="YxgsxaFWWHQ"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/YxgsxaFWWHQ" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="BpeqUCazpzY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/BpeqUCazpzY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="ldxFjLJ3rVY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/ldxFjLJ3rVY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="1svFCGywpSs"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/1svFCGywpSs" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="M47YdERx11s"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/M47YdERx11s" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="gz9BRl7DVSM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/gz9BRl7DVSM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="pUhXi9C5N2k"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/pUhXi9C5N2k" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="wXT-22qSxEU"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/wXT-22qSxEU" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="RQYuyHNLPTQ"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/RQYuyHNLPTQ" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="9szhjhO9epA"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/9szhjhO9epA" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="h4X3rAg6lhY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/h4X3rAg6lhY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="JAmw-TTG2Ds"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/JAmw-TTG2Ds" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="qxuADBE4Zoc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/qxuADBE4Zoc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="2A4bs40scSo"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/2A4bs40scSo" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="G5SeUf2anO8"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/G5SeUf2anO8" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="kILYJ0qFhHM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/kILYJ0qFhHM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="KLHRjaUBb3o"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/KLHRjaUBb3o" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="S34wuJKVB0g"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/S34wuJKVB0g" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="5u604lTkGAY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/5u604lTkGAY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="g8yLNIMwWuc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/g8yLNIMwWuc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="t7OIc-DBRXM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/t7OIc-DBRXM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="jndlbCWs1Tg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/jndlbCWs1Tg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="BjPNPuHpX7w"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/BjPNPuHpX7w" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="zkOEdhfwXok"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/zkOEdhfwXok" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="73iTHJQaxcY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/73iTHJQaxcY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="shrIyQ2GLj4"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/shrIyQ2GLj4" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="XAtPa28baak"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/XAtPa28baak" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="iV12kgWEgG0"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/iV12kgWEgG0" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="TtO88CoW5Pg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/TtO88CoW5Pg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="ibNvyTD4Icg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/ibNvyTD4Icg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="8XR2RvfZ-68"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/8XR2RvfZ-68" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="FEcoxUZnsMc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/FEcoxUZnsMc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="PvSMiHFAjzo"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/PvSMiHFAjzo" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="N8QkFFe4zMA"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/N8QkFFe4zMA" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="tHQ5fOJkI-g"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/tHQ5fOJkI-g" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="K71XefOlJh0"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/K71XefOlJh0" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="1yE-TKQpl_Y"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/1yE-TKQpl_Y" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="XfOWX--CzNg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/XfOWX--CzNg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="1xZxxVlu7BM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/1xZxxVlu7BM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="H1j1KgKlyZU"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/H1j1KgKlyZU" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="9BjCxh5jRgQ"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/9BjCxh5jRgQ" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="PfZgOV4UHBU"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/PfZgOV4UHBU" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="_zkRjrGmTl4"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/_zkRjrGmTl4" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="uDqE8ImgdsM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/uDqE8ImgdsM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="BkpL42aLEAg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/BkpL42aLEAg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="nhbYveaV0pk"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/nhbYveaV0pk" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="Sx9zG7wa4FA"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/Sx9zG7wa4FA" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="mZFN_YxpDpU"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/mZFN_YxpDpU" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="53s-5RKAdGE"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/53s-5RKAdGE" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="kT4p1GXq4HY"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/kT4p1GXq4HY" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="-6lBfwiXnZ4"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/-6lBfwiXnZ4" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="mRT31iYaWOw"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/mRT31iYaWOw" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="-cVx8zOL4gc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/-cVx8zOL4gc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="36mEaTK9Fu4"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/36mEaTK9Fu4" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="X1tyybVuSBU"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/X1tyybVuSBU" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="OSNV6224cHg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/OSNV6224cHg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="fWiXZAfIH2Y"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/fWiXZAfIH2Y" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="RWNauvVJr6s"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/RWNauvVJr6s" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="uYMpMcmpfkI"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/uYMpMcmpfkI" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="_nk6rtLXyaQ"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/_nk6rtLXyaQ" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="IYnvxc_Kp9Q"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/IYnvxc_Kp9Q" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="Lsi1ZhmbNDc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/Lsi1ZhmbNDc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="hnq2bX3EYxM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/hnq2bX3EYxM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="Hvfa6p10H6c"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/Hvfa6p10H6c" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="_TrZdA3rRUo"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/_TrZdA3rRUo" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="ZDPyzUCwhxo"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/ZDPyzUCwhxo" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="I6lNQU7pchM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/I6lNQU7pchM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="hckwxq8rnr0"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/hckwxq8rnr0" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><youtube-player 
:video="MiUHjLxm3V0"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/MiUHjLxm3V0" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


</div>
  <div class="end-block"></div>
]]></description> 
</item><item>
<title><![CDATA[Pulling Magic Commander Rankings from EDHREC]]></title>
<link>https://www.alanwsmith.com/en/3b/e9/v6/zj/</link>
<pubDate>Sun, 29 Mar 2026 22:44:49 -0400</pubDate>
<guid>1cd6dad0-989a-5917-bee6-b4d30d8d4a4f</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow">


<p>I'm working on a tool to help me build Magic Decks<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-mdb-text"
    id="footnote-mdb-link"
    >mdb</a></sup>. It'll let me search and assemble cards from data via Scryfall<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-sf-text"
    id="footnote-sf-link"
    >sf</a></sup>. I also want to see other folks are doing. For example, which are the most used commanders. I'm grabbing data from EDHREC<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-edh-text"
    id="footnote-edh-link"
    >edh</a></sup> for that.</p>


<p>This is the script I'm using to pull in the raw data.</p></section>


<section class="code-section default-flow"><pre class="code-block"><code><span class="aws-code-block-marker"></span><span class="source python"><span class="comment line number-sign python"><span class="punctuation definition comment python">#</span>!/usr/bin/env python3
<span class="aws-code-block-marker"></span></span>
<span class="aws-code-block-marker"></span><span class="meta statement import python"><span class="keyword control import python">import</span> <span class="meta qualified-name python"><span class="meta generic-name python">json</span></span></span>
<span class="aws-code-block-marker"></span><span class="meta statement import python"><span class="keyword control import python">import</span> <span class="meta qualified-name python"><span class="meta generic-name python">urllib</span><span class="punctuation accessor dot python">.</span><span class="meta generic-name python">request</span></span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta qualified-name python"><span class="meta generic-name python">url</span></span> <span class="keyword operator assignment python">=</span> <span class="meta string python"><span class="string quoted double python"><span class="punctuation definition string begin python">&quot;</span></span></span><span class="meta string python"><span class="string quoted double python">https://edhrec.com/commanders<span class="punctuation definition string end python">&quot;</span></span></span>
<span class="aws-code-block-marker"></span><span class="meta qualified-name python"><span class="meta generic-name python">output_path</span></span> <span class="keyword operator assignment python">=</span> <span class="meta string python"><span class="string quoted double python"><span class="punctuation definition string begin python">&quot;</span></span></span><span class="meta string python"><span class="string quoted double python">commanders.json<span class="punctuation definition string end python">&quot;</span></span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta function python"><span class="storage type function python">def</span> <span class="entity name function python"><span class="meta generic-name python">get_json</span></span></span><span class="meta function parameters python"><span class="punctuation section parameters begin python">(</span></span><span class="meta function parameters python"><span class="punctuation section parameters end python">)</span></span><span class="meta function python"><span class="punctuation section function begin python">:</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta qualified-name python"><span class="meta generic-name python">response</span></span> <span class="keyword operator assignment python">=</span> <span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">urllib</span><span class="punctuation accessor dot python">.</span><span class="meta generic-name python">request</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">urlopen</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta qualified-name python"><span class="meta generic-name python">url</span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta qualified-name python"><span class="meta generic-name python">html</span></span> <span class="keyword operator assignment python">=</span> <span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">response</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">read</span></span><span class="punctuation section arguments begin python">(</span><span class="punctuation section arguments end python">)</span></span><span class="meta function-call python"><span class="meta qualified-name python"><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">decode</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta string python"><span class="string quoted single python"><span class="punctuation definition string begin python">&#39;</span></span></span><span class="meta string python"><span class="string quoted single python">utf-8<span class="punctuation definition string end python">&#39;</span></span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta qualified-name python"><span class="meta generic-name python">parts</span></span> <span class="keyword operator assignment python">=</span> <span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">html</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">split</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta string python"><span class="string quoted single python"><span class="punctuation definition string begin python">&#39;</span></span></span><span class="meta string python"><span class="string quoted single python">&lt;script id=&quot;__NEXT_DATA__&quot; type=&quot;application/json&quot;&gt;<span class="punctuation definition string end python">&#39;</span></span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta qualified-name python"><span class="meta generic-name python">content</span></span> <span class="keyword operator assignment python">=</span> <span class="meta item-access python"><span class="meta qualified-name python"><span class="meta generic-name python">parts</span></span></span><span class="meta item-access python"><span class="punctuation section brackets begin python">[</span></span><span class="meta item-access arguments python"><span class="constant numeric integer decimal python">1</span></span><span class="meta item-access python"><span class="punctuation section brackets end python">]</span></span><span class="meta function-call python"><span class="meta qualified-name python"><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">split</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta string python"><span class="string quoted single python"><span class="punctuation definition string begin python">&#39;</span></span></span><span class="meta string python"><span class="string quoted single python">&lt;/script&gt;<span class="punctuation definition string end python">&#39;</span></span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta qualified-name python"><span class="meta generic-name python">data</span></span> <span class="keyword operator assignment python">=</span> <span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">json</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">loads</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta item-access python"><span class="meta qualified-name python"><span class="meta generic-name python">content</span></span></span><span class="meta item-access python"><span class="punctuation section brackets begin python">[</span></span><span class="meta item-access arguments python"><span class="constant numeric integer decimal python">0</span></span><span class="meta item-access python"><span class="punctuation section brackets end python">]</span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta statement with python"><span class="keyword control flow with python">with</span> <span class="meta function-call python"><span class="meta qualified-name python"><span class="support function builtin python">open</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta qualified-name python"><span class="meta generic-name python">output_path</span></span><span class="punctuation separator arguments python">,</span> <span class="meta string python"><span class="string quoted double python"><span class="punctuation definition string begin python">&quot;</span></span></span><span class="meta string python"><span class="string quoted double python">w<span class="punctuation definition string end python">&quot;</span></span></span></span><span class="punctuation section arguments end python">)</span></span> <span class="meta statement with python"><span class="keyword control flow with as python">as</span></span></span><span class="meta statement with python"> <span class="meta generic-name python">_out</span><span class="punctuation section block with python">:</span></span>
<span class="aws-code-block-marker"></span>        <span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">_out</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">write</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">json</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">dumps</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta qualified-name python"><span class="meta generic-name python">data</span></span><span class="punctuation separator arguments python">,</span> <span class="variable parameter python">sort_keys</span><span class="keyword operator assignment python">=</span><span class="constant language python">True</span><span class="punctuation separator arguments python">,</span> <span class="variable parameter python">indent</span><span class="keyword operator assignment python">=</span><span class="constant numeric integer decimal python">2</span><span class="punctuation separator arguments python">,</span> <span class="variable parameter python">default</span><span class="keyword operator assignment python">=</span><span class="meta qualified-name python"><span class="support type python">str</span></span></span><span class="punctuation section arguments end python">)</span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta statement if python"><span class="keyword control flow conditional python">if</span> <span class="meta qualified-name python"><span class="support variable magic python">__name__</span></span> <span class="keyword operator comparison python">==</span> <span class="meta string python"><span class="string quoted double python"><span class="punctuation definition string begin python">&quot;</span></span></span><span class="meta string python"><span class="string quoted double python">__main__<span class="punctuation definition string end python">&quot;</span></span></span><span class="punctuation section block conditional python">:</span></span>
<span class="aws-code-block-marker"></span>    <span class="meta function-call python"><span class="meta qualified-name python"><span class="variable function python">get_json</span></span><span class="punctuation section arguments begin python">(</span><span class="punctuation section arguments end python">)</span></span></span></code></pre></section>


<section class="p-section default-flow">


<p>The code's a little brittle in terms of doing a split to pull out the data instead of more advanced parsing with something like Beautiful Soup<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-bs-text"
    id="footnote-bs-link"
    >bs</a></sup>. That's not a big deal. If they change the page and things break I'll just update the script.</p>


<p>-a</p></section>


</div>
  <div class="end-block">
          <section class="endnotes-section default-flow xxlarge-bottom-margin">
            <h3 class="back-matter">Endnotes</h3>
            <div class="xxlarge-flow">
          
        


<section class="endnote-section default-flow">
  


<p>The EDHREC data uses Scryfall IDs. Combining data sets is no fuss, no muss.</p>
</section>
            </div>
          </section>
    
        <section class="footnotes-section flow">
            <h3 class="back-matter">Footnotes</h3>
        
        


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-mdb-link">
        <span id="footnote-mdb-text">mdb &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://www.al9000.com/magic-deck-builder/"><strong>Magic Deck Builder</strong></a></div>
    <div class="default-flow">


<p>The little tool I'm making to make Magic decks. Still very much a work in progress at press time.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-sf-link">
        <span id="footnote-sf-text">sf &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://scryfall.com/"><strong>Scryfall</strong></a></div>
    <div class="default-flow">


<p><em class="emphasis-shorthand-span">The</em> place to search for Magic cards. Even better, they provide 
<a href="https://scryfall.com/docs/api/bulk-data" >bulk data downloads</a>
.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-edh-link">
        <span id="footnote-edh-text">edh &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://edhrec.com/"><strong>EDHREC</strong></a></div>
    <div class="default-flow">


<p>Fantastic fan content for all things Magic. They've got articles and stuff which I'm sure are great. I'm only there for the deck lists and rankings though.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-bs-link">
        <span id="footnote-bs-text">bs &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://beautiful-soup-4.readthedocs.io/en/latest/"><strong>Beautiful Soup</strong></a></div>
    <div class="default-flow">


<p>For those times when doing simple splits doesn't get you what you need, try Beautiful Soup. It's the only way to fly with python HTML parsing.</p></div>
    
  </div>


</section>
        </section>
    </div>
]]></description> 
</item><item>
<title><![CDATA[Parse a String of Text into JSON in Python]]></title>
<link>https://www.alanwsmith.com/en/3b/e8/gm/e5/</link>
<pubDate>Sun, 29 Mar 2026 22:38:08 -0400</pubDate>
<guid>03cd724e-133c-599f-9fab-05f1a55fb6b9</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow"></section>


<section class="code-section default-flow"><pre class="code-block"><code><span class="aws-code-block-marker"></span><span class="source python"><span class="meta statement import python"><span class="keyword control import python">import</span> <span class="meta qualified-name python"><span class="meta generic-name python">json</span></span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta qualified-name python"><span class="support function builtin python">input</span></span> <span class="keyword operator assignment python">=</span> <span class="meta string python"><span class="string quoted single python"><span class="punctuation definition string begin python">&#39;</span></span></span><span class="meta string python"><span class="string quoted single python">{ &quot;alfa&quot;: &quot;bravo&quot;, &quot;charlie&quot;: &quot;delta&quot; }<span class="punctuation definition string end python">&#39;</span></span></span>
<span class="aws-code-block-marker"></span><span class="meta qualified-name python"><span class="meta generic-name python">data</span></span> <span class="keyword operator assignment python">=</span> <span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">json</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">loads</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta qualified-name python"><span class="support function builtin python">input</span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span><span class="meta function-call python"><span class="meta qualified-name python"><span class="support function builtin python">print</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta qualified-name python"><span class="meta generic-name python">data</span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span><span class="meta function-call python"><span class="meta qualified-name python"><span class="support function builtin python">print</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta string python"><span class="string quoted double python"><span class="punctuation definition string begin python">&quot;</span></span></span><span class="meta string python"><span class="string quoted double python">----<span class="punctuation definition string end python">&quot;</span></span></span></span><span class="punctuation section arguments end python">)</span></span>
<span class="aws-code-block-marker"></span><span class="meta function-call python"><span class="meta qualified-name python"><span class="support function builtin python">print</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta function-call python"><span class="meta qualified-name python"><span class="meta generic-name python">json</span><span class="punctuation accessor dot python">.</span></span><span class="meta qualified-name python"><span class="variable function python">dumps</span></span><span class="punctuation section arguments begin python">(</span><span class="meta function-call arguments python"><span class="meta qualified-name python"><span class="meta generic-name python">data</span></span><span class="punctuation separator arguments python">,</span> <span class="variable parameter python">sort_keys</span><span class="keyword operator assignment python">=</span><span class="constant language python">True</span><span class="punctuation separator arguments python">,</span> <span class="variable parameter python">indent</span><span class="keyword operator assignment python">=</span><span class="constant numeric integer decimal python">2</span><span class="punctuation separator arguments python">,</span> <span class="variable parameter python">default</span><span class="keyword operator assignment python">=</span><span class="meta qualified-name python"><span class="support type python">str</span></span></span><span class="punctuation section arguments end python">)</span></span></span><span class="punctuation section arguments end python">)</span></span></span></code></pre></section>


<section class="results-section">
<div class="results-header">Output:</div>
<div class="results-body">
<pre><code>{&#x27;alfa&#x27;: &#x27;bravo&#x27;, &#x27;charlie&#x27;: &#x27;delta&#x27;}
----
{
  &quot;alfa&quot;: &quot;bravo&quot;,
  &quot;charlie&quot;: &quot;delta&quot;
}</code></pre>
</div></section>





</div>
  <div class="end-block"></div>
]]></description> 
</item><item>
<title><![CDATA[Using IndexedDB to Store Key Value Pairs with Vanilla JavaScript]]></title>
<link>https://www.alanwsmith.com/en/3b/yu/de/lh/</link>
<pubDate>Sat, 28 Mar 2026 02:10:06 -0400</pubDate>
<guid>c92d7b3c-b9a2-5675-aa1a-a4fdf53cf91a</guid>
<description><![CDATA[<hr />
  <div>
    <strong>Dear RSS Reader:<br />The original version of this page includes
    JavaScript. It probably won't run in here. So, any
    functionality it might have had probably won't work.
    <a href="https://www.alanwsmith.com/en/3b/yu/de/lh/">Check out the 
    original page</a> to see it in action.
    </strong>
  </div><hr /><div class="flow body-block">


<section class="title-section default-flow"></section>


<section class="forward-section default-flow">


<p>I'm working on a Magic Deck Builder<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-magic-text"
    id="footnote-magic-link"
    >magic</a></sup>. There's about 30,000 cards to choose from. Keeping track of them is beyond the capabilities of localStorage<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-ls-text"
    id="footnote-ls-link"
    >ls</a></sup>. IndexedDB<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-idb-text"
    id="footnote-idb-link"
    >idb</a></sup>, on the other hand, has no problem hanging on to that much stuff.</p>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>An Actual Solution</h2>


<p>Most documentation and tutorials on IndexedDB are disapointing. They show how to store values just fine. They fail to demonstrate how to pull data out in a useful way. The only thing they give you is how to print to <code class="code-span color-alt-1-80" class="code-shorthand-span"><span class="source js"><span class="meta function-call method js"><span class="support type object console js">console</span><span class="punctuation accessor js">.</span><span class="support function console js">log</span><span class="meta group js"><span class="punctuation section group js">(</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span></code>. Nothing about how to, you know, actually use the data outside the functions that query it<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-results-text"
    id="footnote-results-link"
    >results</a></sup>.</p>


<p>The examples also lock in on storing full objects. That's great and all, but I want to use IndexedDB as a simple key/value store<sup class="xsmall-font-size"><a class="footnote-shorthand-span" href="#footnote-kv-text"
    id="footnote-kv-link"
    >kv</a></sup>.</p>


<p>This is how I'm doing that:</p></section></section>






<section class="javascript-section default-flow"><div class="flow show-javascript">

    <h4 class="show-javascript-heading">JavaScript</h4><div class="javascript-body">
      <pre class="code-block"><code><span class="aws-code-block-marker"></span><span class="source js"><span class="storage type js">const</span> <span class="variable other constant js">DB_NAME</span> <span class="keyword operator assignment js">=</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>example_db<span class="punctuation definition string end js">&quot;</span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other constant js">STORE_NAME</span> <span class="keyword operator assignment js">=</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>storage<span class="punctuation definition string end js">&quot;</span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other constant js">DB_VERSION</span> <span class="keyword operator assignment js">=</span> <span class="constant numeric js">1</span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta function declaration js"><span class="storage type js">async</span> <span class="storage type function js">function</span> <span class="entity name function js">initDB</span><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span></span><span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>  <span class="keyword control flow js">return</span> <span class="meta instance constructor js"><span class="keyword operator word new js">new</span><span class="meta function-call constructor js"> <span class="support class builtin js">Promise</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="variable parameter function js">resolve</span><span class="punctuation separator parameter function js">,</span> <span class="variable parameter function js">reject</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">request</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">indexedDB</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="support function dom js">open</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">DB_NAME</span><span class="punctuation separator comma js">,</span> <span class="variable other constant js">DB_VERSION</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onsuccess</span></span> <span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">resolve</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onerror</span></span><span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">reject</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onupgradeneeded</span></span> <span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="variable parameter function js">event</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>      <span class="storage type js">const</span> <span class="variable other readwrite js">db</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">event</span><span class="punctuation accessor js">.</span><span class="meta property object js">target</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>      <span class="meta conditional js"><span class="keyword control conditional js">if</span> <span class="meta group js"><span class="punctuation section group js">(</span><span class="keyword operator logical js">!</span><span class="variable other object js">db</span><span class="punctuation accessor js">.</span><span class="meta property object js">objectStoreNames</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">contains</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation section group js">)</span></span> <span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>        <span class="variable other object js">db</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">createObjectStore</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>      </span><span class="meta block js"><span class="punctuation section block js">}</span></span></span>
<span class="aws-code-block-marker"></span>    <span class="punctuation section block js">}</span></span>
<span class="aws-code-block-marker"></span>  <span class="punctuation section block js">}</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="punctuation section block js">}</span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta function declaration js"><span class="storage type js">async</span> <span class="storage type function js">function</span> <span class="entity name function js">putValue</span><span class="punctuation section group begin js">(</span><span class="variable parameter function js">value</span><span class="punctuation separator parameter function js">,</span> <span class="variable parameter function js">key</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span></span><span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>  <span class="storage type js">const</span> <span class="variable other readwrite js">db</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">await</span> <span class="meta function-call js"><span class="variable function js">initDB</span><span class="meta group js"><span class="punctuation section group js">(</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>  <span class="keyword control flow js">return</span> <span class="meta instance constructor js"><span class="keyword operator word new js">new</span><span class="meta function-call constructor js"> <span class="support class builtin js">Promise</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="variable parameter function js">resolve</span><span class="punctuation separator parameter function js">,</span> <span class="variable parameter function js">reject</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">store</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">db</span>
<span class="aws-code-block-marker"></span>      <span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">transaction</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span><span class="punctuation separator comma js">,</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>readwrite<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span>
<span class="aws-code-block-marker"></span>      <span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">objectStore</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">request</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">store</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">put</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other readwrite js">value</span><span class="punctuation separator comma js">,</span> <span class="variable other readwrite js">key</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onsuccess</span></span> <span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">resolve</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onerror</span></span><span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">reject</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>  <span class="punctuation section block js">}</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="punctuation section block js">}</span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta function declaration js"><span class="storage type js">async</span> <span class="storage type function js">function</span> <span class="entity name function js">getValue</span><span class="punctuation section group begin js">(</span><span class="variable parameter function js">key</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span></span><span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>  <span class="storage type js">const</span> <span class="variable other readwrite js">db</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">await</span> <span class="meta function-call js"><span class="variable function js">initDB</span><span class="meta group js"><span class="punctuation section group js">(</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>  <span class="keyword control flow js">return</span> <span class="meta instance constructor js"><span class="keyword operator word new js">new</span><span class="meta function-call constructor js"> <span class="support class builtin js">Promise</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="variable parameter function js">resolve</span><span class="punctuation separator parameter function js">,</span> <span class="variable parameter function js">reject</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">store</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">db</span>
<span class="aws-code-block-marker"></span>      <span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">transaction</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span><span class="punctuation separator comma js">,</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>readonly<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span>
<span class="aws-code-block-marker"></span>      <span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">objectStore</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">request</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">store</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">get</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other readwrite js">key</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onsuccess</span></span> <span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">resolve</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onerror</span></span><span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">reject</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>  <span class="punctuation section block js">}</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="punctuation section block js">}</span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="meta function declaration js"><span class="storage type js">async</span> <span class="storage type function js">function</span> <span class="entity name function js">deleteValue</span><span class="punctuation section group begin js">(</span><span class="variable parameter function js">key</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span></span><span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>  <span class="storage type js">const</span> <span class="variable other readwrite js">db</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">await</span> <span class="meta function-call js"><span class="variable function js">initDB</span><span class="meta group js"><span class="punctuation section group js">(</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>  <span class="keyword control flow js">return</span> <span class="meta instance constructor js"><span class="keyword operator word new js">new</span><span class="meta function-call constructor js"> <span class="support class builtin js">Promise</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="variable parameter function js">resolve</span><span class="punctuation separator parameter function js">,</span> <span class="variable parameter function js">reject</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="punctuation section block js">{</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">store</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">db</span>
<span class="aws-code-block-marker"></span>      <span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">transaction</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span><span class="punctuation separator comma js">,</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>readwrite<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span>
<span class="aws-code-block-marker"></span>      <span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">objectStore</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other constant js">STORE_NAME</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="storage type js">const</span> <span class="variable other readwrite js">request</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">store</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">delete</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other readwrite js">key</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onsuccess</span></span> <span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">resolve</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>    <span class="meta function declaration js"><span class="support class js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js"><span class="entity name function js">onerror</span></span><span class="keyword operator assignment js">=</span> </span><span class="meta function declaration js"><span class="punctuation section group begin js">(</span><span class="punctuation section group end js">)</span><span class="meta function declaration js"> </span><span class="storage type function arrow js">=&gt;</span></span> <span class="meta block js"><span class="meta function-call js"><span class="variable function js">reject</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other object js">request</span><span class="punctuation accessor js">.</span><span class="meta property object js">result</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>  <span class="punctuation section block js">}</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="punctuation section block js">}</span></span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="keyword control flow js">await</span> <span class="meta function-call js"><span class="variable function js">putValue</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>this is alfa<span class="punctuation definition string end js">&quot;</span></span><span class="punctuation separator comma js">,</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>alfa<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterPut</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">await</span> <span class="meta function-call js"><span class="variable function js">getValue</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>alfa<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterPutEl</span> <span class="keyword operator assignment js">=</span> <span class="support type object dom js">document</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">querySelector</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>#afterPut<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="variable other object js">afterPutEl</span><span class="punctuation accessor js">.</span><span class="meta property object js">innerHTML</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">afterPut</span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="keyword control flow js">await</span> <span class="meta function-call js"><span class="variable function js">deleteValue</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>alfa<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterDelete</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">await</span> <span class="meta function-call js"><span class="variable function js">getValue</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>alfa<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterDeleteEl</span> <span class="keyword operator assignment js">=</span> <span class="support type object dom js">document</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">querySelector</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>#afterDelete<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="variable other object js">afterDeleteEl</span><span class="punctuation accessor js">.</span><span class="meta property object js">innerHTML</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">afterDelete</span><span class="punctuation terminator statement js">;</span></span></code></pre>
    </div>
  </div>
</section>


<section class="html-section default-flow show-html"><h4 class="show-html-heading">HTML</h4><pre class="code-block"><code><span class="aws-code-block-marker"></span><span class="text html basic"><span class="meta tag block any html"><span class="punctuation definition tag begin html">&lt;</span><span class="entity name tag block any html">div</span> <span class="meta attribute-with-value id html"><span class="entity other attribute-name id html">id</span><span class="punctuation separator key-value html">=</span></span><span class="meta attribute-with-value id html"><span class="string quoted double html"><span class="punctuation definition string begin html">&quot;</span></span></span><span class="meta attribute-with-value id html"><span class="string quoted double html"><span class="meta toc-list id html">afterPut</span><span class="punctuation definition string end html">&quot;</span></span></span><span class="punctuation definition tag end html">&gt;</span></span>--<span class="meta tag block any html"><span class="punctuation definition tag begin html">&lt;/</span><span class="entity name tag block any html">div</span><span class="punctuation definition tag end html">&gt;</span></span>
<span class="aws-code-block-marker"></span><span class="meta tag block any html"><span class="punctuation definition tag begin html">&lt;</span><span class="entity name tag block any html">div</span> <span class="meta attribute-with-value id html"><span class="entity other attribute-name id html">id</span><span class="punctuation separator key-value html">=</span></span><span class="meta attribute-with-value id html"><span class="string quoted double html"><span class="punctuation definition string begin html">&quot;</span></span></span><span class="meta attribute-with-value id html"><span class="string quoted double html"><span class="meta toc-list id html">afterDelete</span><span class="punctuation definition string end html">&quot;</span></span></span><span class="punctuation definition tag end html">&gt;</span></span>--<span class="meta tag block any html"><span class="punctuation definition tag begin html">&lt;/</span><span class="entity name tag block any html">div</span><span class="punctuation definition tag end html">&gt;</span></span></span></code></pre>

<h4 class="show-html-heading">Output</h4>

<div class="faded-reverse-border default-padding default-border-radius">
  <div id="afterPut">--</div>
<div id="afterDelete">--</div>
</div>

</section>


<section 
   class="h2-section default-flow xxlarge-top-margin"
>

  <h2>Bulk Storage</h2>


<p>That's a "non-trivial amount of code". It's also async/await based which adds to the complexity of using it. It would be nice if it was easier to work with, but the flexibility makes the complexity worth it.</p>


<p>-a</p></section>


</div>
  <div class="end-block">
          <section class="endnotes-section default-flow xxlarge-bottom-margin">
            <h3 class="back-matter">Endnotes</h3>
            <div class="xxlarge-flow">
          
        


<section class="endnote-section default-flow">
  


<p>Using localStorage to do the same thing looks like this:</p>


<section class="code-section default-flow"><pre class="code-block"><code><span class="aws-code-block-marker"></span><span class="source js"><span class="variable other object js">localStorage</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">setItem</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>bravo<span class="punctuation definition string end js">&quot;</span></span><span class="punctuation separator comma js">,</span> <span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>this is bravo<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterSet</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">localStorage</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">getItem</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>bravo<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterSetEl</span> <span class="keyword operator assignment js">=</span> <span class="support type object dom js">document</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">querySelector</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>#afterSet<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="variable other object js">afterSetEl</span><span class="punctuation accessor js">.</span><span class="meta property object js">innerHTML</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">afterSet</span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span>
<span class="aws-code-block-marker"></span><span class="variable other object js">localStorage</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">removeItem</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>bravo<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterRemove</span> <span class="keyword operator assignment js">=</span> <span class="variable other object js">localStorage</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">getItem</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>bravo<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="storage type js">const</span> <span class="variable other readwrite js">afterRemoveEl</span> <span class="keyword operator assignment js">=</span> <span class="support type object dom js">document</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">querySelector</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="string quoted double js"><span class="punctuation definition string begin js">&quot;</span>#afterRemove<span class="punctuation definition string end js">&quot;</span></span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span><span class="punctuation terminator statement js">;</span>
<span class="aws-code-block-marker"></span><span class="variable other object js">afterRemoveEl</span><span class="punctuation accessor js">.</span><span class="meta property object js">innerHTML</span> <span class="keyword operator assignment js">=</span> <span class="variable other readwrite js">afterRemove</span><span class="punctuation terminator statement js">;</span></span></code></pre></section>


<section class="p-section default-flow">


<p>Less than ten lines compared to more than sixty with no async to worry about is nice. It just falls over when trying to store large amounts of data since browsers have much lower limits on localStorage vs IndexedDB.</p></section>
</section>





<section class="endnote-section default-flow">
  


<p>Normally, you'd check the return values in both the IndexedDB and localStorage approaches before trying to use them. I've skipped both here to reduce the code.</p>
</section>


<section class="endnote-section default-flow">
  


<p>I'm using <code class="code-span color-alt-1-80" class="code-shorthand-span"><span class="source js"><span class="variable other object js">store</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="variable function js">put</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other readwrite js">value</span><span class="punctuation separator comma js">,</span> <span class="variable other readwrite js">key</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span></code> to add the values to the database. This is an <code class="code-span color-alt-1-80" class="code-shorthand-span"><span class="text plain">upsert</span></code> style change that updates the value if it exists and adds it if it doesn't. <code class="code-span color-alt-1-80" class="code-shorthand-span"><span class="source js"><span class="variable other object js">store</span><span class="punctuation accessor js">.</span><span class="meta function-call method js"><span class="support function dom js">add</span><span class="meta group js"><span class="punctuation section group js">(</span><span class="variable other readwrite js">value</span><span class="punctuation separator comma js">,</span> <span class="variable other readwrite js">key</span></span><span class="meta group js"><span class="punctuation section group js">)</span></span></span></span></code> can be used to do an add without the update functionality.</p>
</section>


<section class="endnote-section default-flow">
  


<p>The AI search results have the same problem with only showing how to log data instead of using it. When prompted for how to actually use the data they point to external libraries. 
<a href="https://dexie.org/" >Dexie</a>
, in particular. It looks great. It does tons of stuff including auth. Overkill for what I'm doing right now so I'm avoiding the dependency. It's on the radar though.</p>
</section>
            </div>
          </section>
    
        <section class="references-section flow">
            <h3 class="back-matter large-bottom-padding">References</h3>
            <div class="default-flow">
        
        


<section class="ref-section faded-reverse-left-border default-left-padding">
    <div>
      <a href="https://www.youtube.com/watch?v=J8fr-xc3bis">IndexedDB: What Makes It Better Than LocalStorage and Cookies? - YouTube</a>
    </div>
    <div class="default-flow">
      


<p>This is the video where I got the approach. It uses React and TypeScript. My version is vanilla JS.</p>
    </div>
</section>


<section class="ref-section faded-reverse-left-border default-left-padding">
    <div>
      <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB API - MDN</a>
    </div>
    <div class="default-flow">
      
    </div>
</section>


<section class="ref-section faded-reverse-left-border default-left-padding">
    <div>
      <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Terminology">IndexedDB key characteristics and basic terminology - MDN</a>
    </div>
    <div class="default-flow">
      
    </div>
</section>


<section class="ref-section faded-reverse-left-border default-left-padding">
    <div>
      <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB">Using IndexedDB - MDN</a>
    </div>
    <div class="default-flow">
      
    </div>
</section>


<section class="ref-section faded-reverse-left-border default-left-padding">
    <div>
      <a href="https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/createObjectStore">IDBDatabase: createObjectStore() method - MDN</a>
    </div>
    <div class="default-flow">
      
    </div>
</section>


<section class="ref-section faded-reverse-left-border default-left-padding">
    <div>
      <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise - MDN</a>
    </div>
    <div class="default-flow">
      
    </div>
</section>
      </div>
        </section>
    
        <section class="footnotes-section flow">
            <h3 class="back-matter">Footnotes</h3>
        
        


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-magic-link">
        <span id="footnote-magic-text">magic &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://www.al9000.com/magic-deck-builder/"><strong>My Magic Deck Builder</strong></a></div>
    <div class="default-flow">


<p>Very much a Work-In-Progress at press time. It's a lot like 
<a href="https://archidekt.com/" >Archidekt</a>
. Just refined down only the feature I want (and a way to kick the tires for 
<a href="https://bittyjs.com" >bitty</a>
.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-ls-link">
        <span id="footnote-ls-text">ls &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage"><strong>localStorage</strong></a></div>
    <div class="default-flow">


<p>The traditional way to store data for a web site when you need something more than a cookie. Great for simple key/value pairs when the values are strings and you don't have too many of them. Storing objects requires jumping through <code class="code-span color-alt-1-80" class="code-shorthand-span"><span class="source js"><span class="support class js">JSON</span><span class="punctuation accessor js">.</span><span class="meta property object js">stringify</span></span></code> and <code class="code-span color-alt-1-80" class="code-shorthand-span"><span class="source js"><span class="support class js">JSON</span><span class="punctuation accessor js">.</span><span class="meta property object js">parse</span></span></code>. There are stricter size limits than IndexedDB as well.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-idb-link">
        <span id="footnote-idb-text">idb &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div><a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API"><strong>The IndexedDB API</strong></a></div>
    <div class="default-flow">


<p>The new hotness in web app data storage. Just gotta jump through some more hoops.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-results-link">
        <span id="footnote-results-text">results &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div></div>
    <div class="default-flow">


<p>Using results from IndexedDB without async/await promises moves you into the world of callbacks. I could probably remember how do do that if I tried. I'd rather not.</p></div>
    
  </div>


</section>


<section class="footnote-section small-font-size">
  <div><sup>
      <a href="#footnote-kv-link">
        <span id="footnote-kv-text">kv &#x2934;
        </span>
      </a>
      </sup></div>
  <div>
    
    <div></div>
    <div class="default-flow">


<p>The general IndexedDB tutorials show how to store objects with IDs. The requires putting the ID in the object. Great when you need it. More complicated than necessary when all you need is a key/value.</p></div>
    
  </div>


</section>
        </section>
    </div>
]]></description> 
</item><item>
<title><![CDATA[Music for Today (March 15, 2026)]]></title>
<link>https://www.alanwsmith.com/en/3b/08/4i/uv/</link>
<pubDate>Sun, 15 Mar 2026 18:40:34 -0400</pubDate>
<guid>55a67f66-dbac-5a58-a441-db0c1b6c868e</guid>
<description><![CDATA[<div class="flow body-block">


<section class="title-section default-flow">


<p>I published a big block of work last night. Stayed up super late to do it.</p>


<p>Today, I'm zoned out. In the post-deployment come down. I've mostly been poking around youtube. Lots of music in the mix.</p>


<p>A few selections from the day.</p></section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Down to the River to Pray - The Petersens</div><youtube-player 
:video="PvSMiHFAjzo"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/PvSMiHFAjzo" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Tom Waits - "Get Behind The Mule"</div><youtube-player 
:video="O_v2HChe350"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/O_v2HChe350" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Going to California - Led Zeppelin - Sierra Eagleson Cover</div><youtube-player 
:video="FEcoxUZnsMc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/FEcoxUZnsMc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Getting Ready to Get Down - Josh Ritter - 2017-13-05</div><youtube-player 
:video="3eyzc11gsWc"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/3eyzc11gsWc" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">San Fermin - Daedalus</div><youtube-player 
:video="MY9cuETTWC0"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/MY9cuETTWC0" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">the Mountain Goats - This Year - Jordan Lake Sessions</div><youtube-player 
:video="2Se76S0XH-I"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/2Se76S0XH-I" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Siren Song - Didn't Leave Nobody but the Baby - O Brother, Where Art Thou</div><youtube-player 
:video="jI99ScMCWMg"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/jI99ScMCWMg" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Lake Street Dive feat. Tiny Habits - "Leaving on a Jet Plane" - Live From the Road</div><youtube-player 
:video="zusFHHAhim4"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/zusFHHAhim4" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Chet Faker - Gold</div><youtube-player 
:video="hi4pzKvuEQM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/hi4pzKvuEQM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">San Fermin - Daedalus</div><youtube-player 
:video="MY9cuETTWC0"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/MY9cuETTWC0" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Sweet Child O' Mine Bluegrass Cover - Thunder and Rain</div><youtube-player 
:video="SDfBxudHWIA"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/SDfBxudHWIA" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="youtube-section default-flow"><div class="youtube-player-title">Can't Find My Way Home (Blind Faith) - Rachael Price - Live from Here with Chris Thile</div><youtube-player 
:video="1xZxxVlu7BM"></youtube-player>

<noscript>
  <iframe 
    width="560" 
    height="315" 
    src="https://www.youtube.com/embed/1xZxxVlu7BM" 
    title="YouTube video player" 
    frameborder="0" 
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" 
    referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</noscript>
</section>


<section class="p-section default-flow">


<p>It's gray outside. A light rain. Perfect for the chill mood.</p>


<p>-a</p></section>


</div>
  <div class="end-block"></div>
]]></description> 
</item></channel>
</rss>