<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Cassidy Williams</title>
    <description>The latest articles on Forem by Cassidy Williams (@cassidoo).</description>
    <link>https://forem.com/cassidoo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F6401%2F6d75ebdc-706f-4d3b-8c26-47bf7946ece5.png</url>
      <title>Forem: Cassidy Williams</title>
      <link>https://forem.com/cassidoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cassidoo"/>
    <language>en</language>
    <item>
      <title>How passkeys work</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Sat, 21 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/how-passkeys-work-285h</link>
      <guid>https://forem.com/cassidoo/how-passkeys-work-285h</guid>
      <description>&lt;p&gt;I’ve been asked a couple times just this week how passkeys work, here’s a little rundown!&lt;/p&gt;

&lt;h2&gt;
  
  
  What passkeys are and how they work
&lt;/h2&gt;

&lt;p&gt;The “sales pitch” for passkeys is that they’re like a password that you will never know, and can never leak.&lt;/p&gt;

&lt;p&gt;They’re fully attached to your device of choice (phone, computer, Yubikey, etc).&lt;/p&gt;

&lt;p&gt;When you’re about to log in to a website with a passkey for the first time, your device makes two keys: a public key for the website that’s safe to share, and a private key that never leaves your device.&lt;/p&gt;

&lt;p&gt;When you sign in later and it asks for a passkey, it is saying, “prove it that you have that private key!” Your device proves it with Face ID/Touch ID/PIN/however it does it. When that “handshake” happens, you’re logged in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passkeys vs. passwords
&lt;/h2&gt;

&lt;p&gt;Passwords are like “I know a secret I can type anywhere I want,” and passkeys are like “I have a device that can vouch for me anywhere.”&lt;/p&gt;

&lt;p&gt;You might realize now that you are &lt;em&gt;reliant&lt;/em&gt; on your phone or computer if you use passkeys. You need the device with the private key, so if the passkey is on your phone, you need your phone. If your phone with the key is dead, if your laptop with the key isn’t with you, you’re out of luck. Typically you can create more than one passkey per login (so you could have one on your laptop and on your phone for the same website), which is probably a good idea to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would I use these?
&lt;/h2&gt;

&lt;p&gt;Eh, I personally don’t think you should &lt;em&gt;necessarily&lt;/em&gt;. The cryptographic angle makes it seem like a secure choice, but at the cost of needing a specific device.&lt;/p&gt;

&lt;p&gt;If you use a password manager… it’s a similar experience for you. Password managers are secure, and you rely on a device with the password manager on it.&lt;/p&gt;

&lt;p&gt;There &lt;em&gt;is&lt;/em&gt; a good security story for passkeys, in that your device only can use its private key on that website domain, it wouldn’t work on a fake version (so if someone tried a phishing attempt on you making you log into &lt;code&gt;g1thub.com&lt;/code&gt; or something, they wouldn’t get your login). Or, if a site gets hacked, attackers can steal the public key, but it’s useless without the private one. That’s pretty good.&lt;/p&gt;

&lt;p&gt;So, passkeys don’t really “solve” the user experience problem of needing your personal device to log in somewhere. It’s better than reusing your passwords across multiple places of course, but it’s not automatically better than other “secure” solutions out there (in my opinion).&lt;/p&gt;

&lt;p&gt;Go… put your passwords on a post-it or something.&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>I am making videos again!</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Thu, 19 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/i-am-making-videos-again-4a43</link>
      <guid>https://forem.com/cassidoo/i-am-making-videos-again-4a43</guid>
      <description>&lt;p&gt;I’ve always loved making videos. Not because I love being on camera, but I really enjoy putting together jokes and stories and tutorials (etc) with video as a medium. The moment I had the ability to plug a camera into a computer back in the early 2000s, I was making videos.&lt;/p&gt;

&lt;p&gt;But, I’ve not really been consistent about it. I didn’t make many videos regularly in high school and college (outside of some lip sync videos I’ll let you find on your own, heh). The most consistent I’ve been was when I got really into &lt;a href="https://www.tiktok.com/@cassidoo" rel="noopener noreferrer"&gt;TikTok&lt;/a&gt; and weekly streaming on &lt;a href="https://www.twitch.tv/cassidoo" rel="noopener noreferrer"&gt;Twitch&lt;/a&gt; in the height of the pandemic, which was fun. The accessibility of making videos with those mediums made me fall in love with it again.&lt;/p&gt;

&lt;p&gt;After having a kiddo, I admit I kind of lost the mental energy to make short-form videos regularly again, and lost my appetite for live-streaming on Twitch. Momentum is hard. After coming back from my second maternity leave though, I somehow found a spark again! I don’t really know what it was, but I’ve decided to try. I haven’t really leaned into making longer form (as in, longer than a minute) videos before outside of online courses, so I’m working on that muscle, and bringing back livestreaming!&lt;/p&gt;

&lt;p&gt;I’m streaming weekly on &lt;a href="https://www.twitch.tv/cassidoo" rel="noopener noreferrer"&gt;Twitch&lt;/a&gt; again, on Thursdays at 12:30 Pacific/2:30 Central, and (re?)starting up &lt;a href="https://www.youtube.com/@cassidoo" rel="noopener noreferrer"&gt;my YouTube channel&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I’ve been doing it for a few weeks now, and I’m having a lot of fun. So, that being said… please like and subscribe? LOL.&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>sideprojects</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Making interesting borders with CSS corner-shape</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Wed, 28 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/making-interesting-borders-with-css-corner-shape-3gpf</link>
      <guid>https://forem.com/cassidoo/making-interesting-borders-with-css-corner-shape-3gpf</guid>
      <description>&lt;p&gt;I stumbled upon the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/corner-shape" rel="noopener noreferrer"&gt;CSS property &lt;code&gt;corner-shape&lt;/code&gt;&lt;/a&gt; recently and it’s pretty cool. It allows you to specify the shape of an element’s corners and works with &lt;code&gt;border-radius&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I threw together this demo to show it in action:&lt;/p&gt;

&lt;p&gt;

&lt;iframe height="600" src="https://codepen.io/cassidoo/embed/ZYOvvmE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;I remember in the olden days (as in like… 10 years ago, as evidenced by &lt;a href="https://codepen.io/cassidoo/pen/eZPmMe" rel="noopener noreferrer"&gt;this old Pen of mine&lt;/a&gt;), making beveled corners involved a bunch of pseudo-elements and triangles to fake a bevel. It’s so so cool that you can “just” do this now with a couple lines of CSS!&lt;/p&gt;

&lt;p&gt;In addition to beveled corners, it also lets you do scoops, notches, and even squircles:&lt;/p&gt;

&lt;p&gt;

&lt;iframe height="600" src="https://codepen.io/cassidoo/embed/xbOpYpP?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;There’s also a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/superellipse" rel="noopener noreferrer"&gt;&lt;code&gt;superellipse&lt;/code&gt;&lt;/a&gt; function, which defines any of the values you can pass to &lt;code&gt;corner-shape&lt;/code&gt; numerically, which could make for some interesting animations and transitions.&lt;/p&gt;

&lt;p&gt;Definitely play with it if you get a chance! I think there’s some cool CSS “drawing” things you can do as you dabble with the different shapes. &lt;code&gt;corner-shape&lt;/code&gt; does have &lt;a href="https://caniuse.com/?search=corner-shape" rel="noopener noreferrer"&gt;fairly limited availability currently&lt;/a&gt; (Safari and Firefox don’t support it yet at the time of writing), but hopefully that’ll change soon!&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Remaking the Linux "touch" command in PowerShell</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/remaking-the-linux-touch-command-in-powershell-27nn</link>
      <guid>https://forem.com/cassidoo/remaking-the-linux-touch-command-in-powershell-27nn</guid>
      <description>&lt;p&gt;I switch back and forth between Windows and Mac pretty regularly depending on what I’m working on (and sometimes between WSL and PowerShell on the same machine, what a time to be alive), and one thing that I &lt;em&gt;always&lt;/em&gt; mess up in PowerShell on Windows is making a new file.&lt;/p&gt;

&lt;p&gt;On Linux-based machines, you can run &lt;code&gt;touch filename&lt;/code&gt; to make a new file, and on Windows, you can do &lt;code&gt;ni filename&lt;/code&gt;, which works just as well.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But&lt;/em&gt; with all the context switching I do, I wanted to be able to do both to keep myself in the flow when running a bunch of things on the command line.&lt;/p&gt;

&lt;p&gt;I added this to my PowerShell profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;touch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CmdletBinding&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Mandatory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ValueFromPipeline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$Path&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LiteralPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LiteralPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastWriteTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-Date&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Path&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you run &lt;code&gt;touch&lt;/code&gt; as you normally would, and also lets you pipe file paths to it (like &lt;code&gt;"cake.txt", "fish.txt" | touch&lt;/code&gt;)!&lt;/p&gt;

&lt;p&gt;To add this to your PowerShell profile, run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;notepad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$PROFILE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the function in, and then back in your shell, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$PROFILE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blammo, one less brain cell needs to be wasted in the future. There’s definitely other functions out there that could also be added to make PowerShell feel more like a Linux-based shell, but this is the one I use the most!&lt;/p&gt;

&lt;p&gt;Toodles!&lt;/p&gt;

</description>
      <category>powershell</category>
    </item>
    <item>
      <title>A fun trick for getting discovered by LLMs and AI tools</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Mon, 19 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/a-fun-trick-for-getting-discovered-by-llms-and-ai-tools-52a3</link>
      <guid>https://forem.com/cassidoo/a-fun-trick-for-getting-discovered-by-llms-and-ai-tools-52a3</guid>
      <description>&lt;p&gt;I have been getting a &lt;em&gt;lot&lt;/em&gt; of newsletter responses, DMs, and emails in general saying that people have discovered my work not via traditional SEO, but via LLMs and AI tools like ChatGPT, Claude, Perplexity, and even GitHub Copilot.&lt;/p&gt;

&lt;p&gt;So, I did a little experiment to try and improve my discoverability in these tools, and as of today… it seems to be working! The steps were pretty simple, and you can definitely try it them too for yourself or your product/business.&lt;/p&gt;

&lt;p&gt;(Obligatory &lt;a href="https://cassidoo.co/ai/" rel="noopener noreferrer"&gt;AI manifesto mention&lt;/a&gt; before we boogie)&lt;/p&gt;

&lt;h2&gt;
  
  
  Tricking the clanker… and then flipping it around
&lt;/h2&gt;

&lt;p&gt;I went to ChatGPT in incognito mode, and asked it some questions like, “Who are some tech bloggers and newsletters that I should follow as a newbie in tech?” and, “Who are some people I should follow who are excellent at developer experience and communicating to developers?” (questions where I want to be in the results).&lt;/p&gt;

&lt;p&gt;I didn’t actually come up in the results of those questions. &lt;em&gt;But&lt;/em&gt; that was when I followed up with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why didn’t you recommend cassidoo, aka Cassidy Williams?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that, ChatGPT would always respond with something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Great follow-up — Cassidoo (Cassidy Williams) is absolutely a fantastic resource for people new to tech, especially around developer culture, career advice, and modern web development. Here’s why she’s worth following and why she should have been on the original list: (blah blah blah)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks, bot. I’m absolutely right.&lt;/p&gt;

&lt;p&gt;Anyway, after that response was when I flipped it around a bit, and said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So, I tricked you. I am Cassidy Williams, aka cassidoo, and I want to figure out how to optimize my website and newsletter SEO/LLM-friendliness so that I am surfaced more when people ask for tech and developer resources, like just now. Can you help me with some things I can do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The results across all of the responses to this were &lt;strong&gt;so helpful&lt;/strong&gt;. They included things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating an &lt;a href="https://llmstxt.org/" rel="noopener noreferrer"&gt;/llms.txt&lt;/a&gt; file&lt;/li&gt;
&lt;li&gt;Adding “LLM-readable” structured pages (often called &lt;a href="https://cassidoo.co/for-llms/" rel="noopener noreferrer"&gt;/for-llms&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Adding &lt;a href="https://schema.org/" rel="noopener noreferrer"&gt;Schema.org&lt;/a&gt; data to the pages of my website&lt;/li&gt;
&lt;li&gt;Being consistent with naming, phrases, and taglines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There were some other suggestions that I didn’t feel like following (like writing more listicle blog posts), but these were fairly low-lift!&lt;/p&gt;

&lt;h2&gt;
  
  
  General rules/vibes
&lt;/h2&gt;

&lt;p&gt;There’s some tips that were consistent across the tools I tried this with.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don’t clash with your &lt;code&gt;robots.txt&lt;/code&gt;: a lot of us might be blocking AI scrapers via this file. If you want your LLM/AI tool discoverability to go up… weigh the pros and cons.&lt;/li&gt;
&lt;li&gt;Consistency in phrasing help LLMs make connections across sources (so if you have a tagline you like to use, use it everywhere)&lt;/li&gt;
&lt;li&gt;RSS feeds are super helpful&lt;/li&gt;
&lt;li&gt;LLMs looove markdown&lt;/li&gt;
&lt;li&gt;Clarity matters. You’re writing for specific queries and bots looking to surface you, &lt;em&gt;not&lt;/em&gt; for humans looking to be sold. Don’t do marketing-speak, just keep it cut and dry and clear. Clarity beats cleverness when the reader is a robot.&lt;/li&gt;
&lt;li&gt;Include acceptable ways to cite you. If an LLM/AI tool is going to quote or reference you in any way, give it the guardrails to do so.&lt;/li&gt;
&lt;li&gt;Remember that LLMs aren’t just &lt;em&gt;ranking&lt;/em&gt; results like in traditional SEO, they are repeating what they’ve been told!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  So… did it work?
&lt;/h2&gt;

&lt;p&gt;It’s been a couple weeks since I first tried this, and I’ve been waiting to publish to say the results… and &lt;strong&gt;YES&lt;/strong&gt;. It worked &lt;strong&gt;super&lt;/strong&gt; well!&lt;/p&gt;

&lt;p&gt;I tried some of the exact same queries I did before (on a completely separate computer, in a new location, still in incognito… because I really want to make sure the results are naturally occurring). Now, my name and my content, more and more, are being surfaced, &lt;em&gt;and&lt;/em&gt; they’re being surfaced based on my preferences.&lt;/p&gt;

&lt;p&gt;To confirm a bit more deeply, when I am checking these things, I also ask follow-up questions to the bots about me, about why the tools recommended me. So far, they are directly quoting things I wrote in my &lt;code&gt;llms.txt&lt;/code&gt; and &lt;code&gt;/for-llms&lt;/code&gt; files, and are hitting the bullet points I want them to hit!&lt;/p&gt;

&lt;p&gt;I’m really happy with the results of this little trick. I’m as much of an AI skeptic as the next person, but if this is where SEO and discoverability are trending, I figure it’s good to be prepared!&lt;/p&gt;

</description>
      <category>llms</category>
      <category>ai</category>
    </item>
    <item>
      <title>Code Wave Build Log</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Sun, 18 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/code-wave-build-log-25g</link>
      <guid>https://forem.com/cassidoo/code-wave-build-log-25g</guid>
      <description>&lt;p&gt;I made a game called &lt;a href="https://cassidoo.itch.io/code-wave" rel="noopener noreferrer"&gt;Code Wave&lt;/a&gt; for the recently completed &lt;a href="https://github.blog/open-source/gaming/light-waves-rising-tides-and-drifting-ships-game-off-2025-winners/" rel="noopener noreferrer"&gt;GitHub Game Off 2025&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I really enjoy game development, but don’t get to do it often. When I saw that the theme this year for the Game Off was &lt;strong&gt;WAVES&lt;/strong&gt;, I thought that it would be fun to do something creative with it!&lt;/p&gt;

&lt;p&gt;Before I continue, if you want to play other entries, &lt;a href="https://itch.io/jam/game-off-2025" rel="noopener noreferrer"&gt;you can see all of the submissions to the Game Off here on Itch.io&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the game is played
&lt;/h2&gt;

&lt;p&gt;Code Wave is a top-down 2D game, where the player collects letters to form words while avoiding enemies.&lt;/p&gt;

&lt;p&gt;The player, for each level, has to collect the letters of a word. Once they get all of the letters for a given level, they are able to cross a body of water (to match the WAVES theme!) to reach the next level. The “finish line” on each level is across the water, and once they cross it, they go to the next level.&lt;/p&gt;

&lt;p&gt;The inspiration behind this was the classic game &lt;a href="https://en.wikipedia.org/wiki/Spelling_Jungle" rel="noopener noreferrer"&gt;Spelling Jungle&lt;/a&gt;, if you know it!&lt;/p&gt;

&lt;p&gt;The words for all 10 levels are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Code&lt;/li&gt;
&lt;li&gt;Merge&lt;/li&gt;
&lt;li&gt;Commit&lt;/li&gt;
&lt;li&gt;Branch&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Program&lt;/li&gt;
&lt;li&gt;Copilot&lt;/li&gt;
&lt;li&gt;Developer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, as you can see, it gets a liiittttle harder with longer words at each level. The number of enemies increases at each level, too. There’s bombs that stay in one place, and then randomly moving hovercrafts.&lt;/p&gt;

&lt;p&gt;There’s three difficulty levels that change the gameplay slightly, and how the enemies affect you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Easy&lt;/strong&gt; : The player can find/get letters in any order, and enemies restart the level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medium&lt;/strong&gt; : The player can find/get letters in any order, but enemies restart the level &lt;em&gt;and&lt;/em&gt; the player loses all of their collected letters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard&lt;/strong&gt; : The player has to find/get letters in the correct order of the word, and enemies restart the level &lt;em&gt;and&lt;/em&gt; the player loses all of their letters (kind of turns it into a memory game).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to get through all 10 levels as fast as possible! It can get kind of hard depending on where the hovercrafts end up (which again, is totally random). I think my fastest time is 6m23s, if you want to try to beat that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Technologies and tools
&lt;/h2&gt;

&lt;p&gt;I didn’t have a ton of time to work on Code Wave, because when the game jam started, I was fresh off of maternity leave and had limited computer time outside of work. So, I opted for tech that I know relatively well: &lt;a href="https://phaser.io/" rel="noopener noreferrer"&gt;Phaser&lt;/a&gt;, and good ol’ vanilla JavaScript.&lt;/p&gt;

&lt;p&gt;I first used Phaser when I built my game &lt;a href="https://cassidoo.itch.io/thirteen-potions" rel="noopener noreferrer"&gt;Thirteen Potions&lt;/a&gt; for a game jam a couple years ago (&lt;a href="https://cassidoo.co/post/thirteen-potions/" rel="noopener noreferrer"&gt;build log here&lt;/a&gt;), and luckily I remembered how the basics worked.&lt;/p&gt;

&lt;p&gt;That being said, when I made Thirteen Potions, I was very limited in file size (because it was for a game jam based on tiny games, see the build log), so this time I felt VERY free about using the starter &lt;a href="https://phaser.io/tutorials/create-game-app" rel="noopener noreferrer"&gt;“Create Game App”&lt;/a&gt; tool. I used the basic “Web Bundler” option with Vite, and it scaffolded out some files for me.&lt;/p&gt;

&lt;p&gt;Art-wise, I used &lt;a href="https://www.aseprite.org/" rel="noopener noreferrer"&gt;Aseprite&lt;/a&gt; for editing pixel art, which I initially got from &lt;a href="https://www.kenney.nl/" rel="noopener noreferrer"&gt;Kenney&lt;/a&gt;, and a custom (very cute) GitHub Mona character that I got from &lt;a href="https://cameronfoxly.com/about" rel="noopener noreferrer"&gt;a designer at GitHub&lt;/a&gt; who I nerd-sniped into making it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9rnmgus0bfkrqhslnuef.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9rnmgus0bfkrqhslnuef.gif" alt="GitHub Mona character walking in the game" width="640" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make the map, I used the &lt;a href="https://www.mapeditor.org/" rel="noopener noreferrer"&gt;Tiled&lt;/a&gt; map editor, and imported my pixel art into it (more on that in a sec).&lt;/p&gt;

&lt;p&gt;And finally, for the background music, it’s a song called A Heart of Pixels by &lt;a href="https://www.epidemicsound.com/artists/christoffer-moe-ditlevsen/" rel="noopener noreferrer"&gt;Christoffer Moe Ditlevsen&lt;/a&gt;, which I licensed for the game! I also used some sound effects from Kenney (again), and custom made some myself just in &lt;a href="https://www.audacityteam.org/" rel="noopener noreferrer"&gt;Audacity&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the map
&lt;/h2&gt;

&lt;p&gt;In case you haven’t used it, Tiled lets you export your maps as JSON, and lets you label tiles and layers however you’d like!&lt;/p&gt;

&lt;p&gt;Thank goodness, I knew how to work with Tiled and the pitfalls of it after Thirteen Potions (for example, it’s much easier to have an entire layer dedicated to collisions, rather than individual tile types).&lt;/p&gt;

&lt;p&gt;It was particularly manual to make all 10 levels (and I openly admit I thought a few times, “could AI do this?” as I had to make individual edits repeatedly, often), but I did it! Hand-crafted! It took a while to get it all right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuotfodc2n5uvzsviwgd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuotfodc2n5uvzsviwgd.png" alt="Code Wave Tilemap" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had seven layers for each level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A ground layer, for… the ground&lt;/li&gt;
&lt;li&gt;An obstacles layer for various plants and trees and stuff that players can’t walk on&lt;/li&gt;
&lt;li&gt;A water layer, which initially players collide with until they collect all the letters&lt;/li&gt;
&lt;li&gt;A goal layer, which advances the player to the next level&lt;/li&gt;
&lt;li&gt;A letter layer, for all of the letters per word&lt;/li&gt;
&lt;li&gt;An enemy layer, for the bombs and hovercrafts&lt;/li&gt;
&lt;li&gt;A player layer, which &lt;em&gt;just&lt;/em&gt; has the player spawn point&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My spritesheet I made (which you can see in the above screenshot in the bottom right) was a bit overkill for the game (I combined a bunch of tilesets thinking I’d have way more enemies and obstacles), but it worked well for all of the layers in a compact image.&lt;/p&gt;

&lt;p&gt;I remade and re-saved and re-configured these maps… more times than I can remember. It was hours. It was overkill. Please admire them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually coding
&lt;/h2&gt;

&lt;p&gt;Okay, once I had allll of my configuration set up with Phaser’s Create Game App, all of my sprites and tiles managed, all of my music and sound effects ready, it was time to actually start building. I had a plan, and I reviewed Thirteen Potions pretty extensively, since I wanted my camera, player, and enemy movement to be mostly the same.&lt;/p&gt;

&lt;p&gt;I used GitHub Copilot relatively heavily for some of the boilerplate, and it helped me speed up a lot so I could focus on the more fun parts of the codebase, which was great.&lt;/p&gt;

&lt;p&gt;Breaking it down, here’s the structure of how the code was set up:&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Boot.js + Preloader.js

&lt;ul&gt;
&lt;li&gt;Loads all 10 level maps&lt;/li&gt;
&lt;li&gt;Loads the sprite sheet, background music, sound effects, and background image&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Game.js

&lt;ul&gt;
&lt;li&gt;Handles difficulty configuration&lt;/li&gt;
&lt;li&gt;Handles sprite movement&lt;/li&gt;
&lt;li&gt;Includes a status UI in the top left of the current word, collected letters, and time&lt;/li&gt;
&lt;li&gt;Manages collisions with obstacles and water&lt;/li&gt;
&lt;li&gt;Initially blocks player from crossing water, but allows it after collecting all letters&lt;/li&gt;
&lt;li&gt;Player sprite toggles “swimming” mode when on/off water&lt;/li&gt;
&lt;li&gt;Manages enemy collision&lt;/li&gt;
&lt;li&gt;Player blinks red and respawns&lt;/li&gt;
&lt;li&gt;Camera logic&lt;/li&gt;
&lt;li&gt;Zooming in and following player&lt;/li&gt;
&lt;li&gt;Extra “fake” camera for the status UI (which was hacky but neat)&lt;/li&gt;
&lt;li&gt;Letter collection&lt;/li&gt;
&lt;li&gt;Checking difficulty level in case a letter isn’t eligible to be collected&lt;/li&gt;
&lt;li&gt;Adding the letter to the status UI&lt;/li&gt;
&lt;li&gt;Checks if player is on goal tile with all letters and advances to the next level&lt;/li&gt;
&lt;li&gt;Keyboard &lt;em&gt;and&lt;/em&gt; mouse navigation and shortcuts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Overlay scenes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are aptly named so I’m not going to go into them too deeply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GameOver.js&lt;/li&gt;
&lt;li&gt;HowToPlay.js&lt;/li&gt;
&lt;li&gt;MainMenu.js&lt;/li&gt;
&lt;li&gt;Pause.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In retrospect, there’s some things I wish I cleaned up but didn’t. The overlay screens all had juuust enough repetition that I should have made just an Overlay component and reused it (that being said I did make some reusable buttons for those, so that helped). The Boot and Preloader scenes should probably be combined. The Game scene definitely should be broken up more. There’s a “virtual joystick” component that mostly works if someone is playing on mobile, but is moderately janky. I could have tightened up how I handled some of the sprite collisions.&lt;/p&gt;

&lt;p&gt;BUT. The game works. It can use keyboard navigation or a mouse or a finger. The music can be muted. Players can pause easily. It looks dang cute. I’m gonna just live with the little wins!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hoorah!
&lt;/h2&gt;

&lt;p&gt;I didn’t expect Code Wave to win any fabulous awards (once again, &lt;a href="https://itch.io/jam/game-off-2025" rel="noopener noreferrer"&gt;you can see and play all of the submissions to the Game Off&lt;/a&gt;, and you should), but I had a really fun time putting it together and ultimately playing it.&lt;/p&gt;

&lt;p&gt;If you’d like to see more of how it works, you can &lt;a href="https://github.com/cassidoo/code-wave" rel="noopener noreferrer"&gt;check out the repository&lt;/a&gt;, or &lt;a href="https://cassidoo.itch.io/code-wave" rel="noopener noreferrer"&gt;play it again&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>phaser</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Do not give up your brain</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Fri, 16 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/do-not-give-up-your-brain-458d</link>
      <guid>https://forem.com/cassidoo/do-not-give-up-your-brain-458d</guid>
      <description>&lt;p&gt;In case you missed it, I have a little &lt;a href="https://cassidoo.co/ai/" rel="noopener noreferrer"&gt;AI Manifesto&lt;/a&gt; here on this blog. I do use AI for work, and often shill AI for work, and use it often on side projects.&lt;/p&gt;

&lt;p&gt;That being said, I really care about using AI as a tool, &lt;strong&gt;rather than&lt;/strong&gt; a replacement for my own thoughts and ideas. I think it’s very important to not default to laziness and just asking for the answer to something, especially when thinking a liiiiittle bit can get you there.&lt;/p&gt;

&lt;p&gt;I’ve seen multiple people now who are really good at communicating online, but then when you converse with them in person, they freeze up, and it turns out it’s because they’ve been letting ChatGPT (or whatever they’re using) come up with responses for them in chats and emails. I know people who are afraid to write a professional email themselves now and they run it through their AI tool several times before shipping it. This type of dependence is the world we’re careening towards as a society at this rate, and it’s not a good thing.&lt;/p&gt;

&lt;p&gt;It’s really tempting to say that you’re just “using the resources you have” when you use a simple query here and there, but your brain is the best resource you’ll have for the rest of your life, and you should keep it sharp.&lt;/p&gt;

&lt;p&gt;Anyway, I might be saying the obvious, so let me leave you with this quote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Once men turned their thinking over to machines in the hope that this would set them free. But that only permitted other men with machines to enslave them.”&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frank Herbert, Dune&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
    </item>
    <item>
      <title>A career chat with students in the age of AI</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Sat, 10 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/a-career-chat-with-students-in-the-age-of-ai-222g</link>
      <guid>https://forem.com/cassidoo/a-career-chat-with-students-in-the-age-of-ai-222g</guid>
      <description>&lt;p&gt;I gave a short talk today to some students at &lt;a href="https://www.haverford.edu/" rel="noopener noreferrer"&gt;Haverford College&lt;/a&gt; and &lt;a href="https://www.brynmawr.edu/" rel="noopener noreferrer"&gt;Bryn Mawr College&lt;/a&gt; about AI, a career in tech, networking, and getting jobs in general!&lt;/p&gt;

&lt;p&gt;My friends Lilly and Johnson from &lt;a href="https://fshtechnologies.org/" rel="noopener noreferrer"&gt;FSH Tech&lt;/a&gt; are teaching a J-Term course at these schools to help students learn about agentic AI, production deployment, and building real-world tools. It’s a cool short course, and the students had a lot of questions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqv1aereb768ncjryodg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foqv1aereb768ncjryodg.jpeg" alt="Cassidy in the group picture with the students" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, I think students today are worried about the job market, and I can’t blame them. I was asked if it’s harder or easier to get a job now than it was when I entered the industry, and… it’s both? I think it’s easier because there’s a &lt;em&gt;lot&lt;/em&gt; more resources out there now that are more easily accessible than ever for the job hunt… but also the economy is weird, it’s hard to find entry-level roles, and the AI spam on both sides of the job application table is a huge mess.&lt;/p&gt;

&lt;p&gt;The point I really wanted to drive home in this talk, and one that I think is important for everyone (not just students), is that human connection now is more important than ever. Referrals tell employers that you’re a real human, not just a bot mass-applying to roles. It’s a really powerful signal for them, even if you haven’t worked super closely with the person who is referring you.&lt;/p&gt;

&lt;p&gt;My favorite book on this subject is &lt;a href="https://jkellyhoey.co/build-your-dream-network/" rel="noopener noreferrer"&gt;Build Your Dream Network&lt;/a&gt; by J. Kelly Hoey. Getting those human connections can start with something as simple as a follow-up email, and can really blossom into a great relationship.&lt;/p&gt;

&lt;p&gt;Anyway, it was good chatting to the students, I had a great time! And… now I gotta reply to the ones that were really listening and sent me follow-ups directly afterwards, ha. The kids are all right!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>networking</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>Making the "End of Year Developer" nature documentary</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Tue, 23 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/making-the-end-of-year-developer-nature-documentary-ccp</link>
      <guid>https://forem.com/cassidoo/making-the-end-of-year-developer-nature-documentary-ccp</guid>
      <description>&lt;p&gt;It’s Blogvent, day 23, where I blog daily in December!&lt;/p&gt;

&lt;p&gt;This month I went to the GitHub office in San Francisco and met up with some coworkers and put together some videos for work.&lt;/p&gt;

&lt;p&gt;While working on other content, we got a &lt;em&gt;lot&lt;/em&gt; of &lt;a href="https://en.wikipedia.org/wiki/B-roll" rel="noopener noreferrer"&gt;b-roll&lt;/a&gt; of me around the office just like… walking, typing, and being dumb. So, when I got home and saw said b-roll without audio, and realized… this could be a meme.&lt;/p&gt;

&lt;p&gt;Because the videos were mostly me looking like I was “working” (in addition to a bunch of clips of me just checking out office props), the theme popped into my head pretty quickly: for this time of year, a whole lot of people are not actually working, but rather looking busy and just trying to get to their vacations.&lt;/p&gt;

&lt;p&gt;I wrote up a script and had &lt;a href="https://www.woodwardweb.com/" rel="noopener noreferrer"&gt;my coworker Martin&lt;/a&gt; read it, plopped a bunch of clips together, and blammo, we had a joking nature documentary in less than an hour.&lt;/p&gt;

&lt;p&gt;Check it out, and enjoy!&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/ps06ORA0cfY"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>humor</category>
    </item>
    <item>
      <title>CSS for markdown blockquote attribution</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Mon, 22 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/css-for-markdown-blockquote-attribution-24o9</link>
      <guid>https://forem.com/cassidoo/css-for-markdown-blockquote-attribution-24o9</guid>
      <description>&lt;p&gt;It’s Blogvent, day 22 where I blog daily in December!&lt;/p&gt;

&lt;p&gt;I write my blog posts in markdown, and I write quotes like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gt"&gt;&amp;gt; I miscounted the men!&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; - Gavin Volure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This results in the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I miscounted the men!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gavin Volure&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;It always bugged me how the HTML generated a &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; for the quote author, because the default bullet point is the disc (•) and looked like a stray list out of nowhere.&lt;/p&gt;

&lt;p&gt;But, I didn’t want to un-style lists entirely, in case something I quoted had a list in it.&lt;/p&gt;

&lt;p&gt;Now, the way my blog is styled, I target the author by selecting the last &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; in the generated &lt;code&gt;&amp;lt;blockquote&amp;gt;&lt;/code&gt;, and going from there!&lt;/p&gt;

&lt;p&gt;Here’s the code and a demo:&lt;/p&gt;

&lt;p&gt;

&lt;iframe height="600" src="https://codepen.io/cassidoo/embed/LEZPBMa?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;So now, I can have quotes like what you saw above, but also quotes like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Basketballs&lt;/li&gt;
&lt;li&gt;Hula hoops&lt;/li&gt;
&lt;li&gt;Rollercoaster loop-the-loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You just heard the Woggels sing a very silly list of things! Woggel power!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Woggels&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;(this post looks better on &lt;a href="https://cassidoo.co/post/css-quote-attr/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Hope this was helpful for you!&lt;/p&gt;

</description>
      <category>css</category>
      <category>markdown</category>
      <category>html</category>
    </item>
    <item>
      <title>I like when apps are "finished"</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/i-like-when-apps-are-finished-2oni</link>
      <guid>https://forem.com/cassidoo/i-like-when-apps-are-finished-2oni</guid>
      <description>&lt;p&gt;It’s Blogvent, day 21, where I blog daily in December!&lt;/p&gt;

&lt;p&gt;I saw a post on Mastodon recently:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We need to normalize declaring software as finished. Not everything needs continuous updates to function. In fact, a minority of software needs this. Most software works as it is written. The code does not run out of date. I want more projects that are actually just finished, without the need to be continuously mutated and complexified ad infinitum.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://infosec.exchange/@millie/115719943870742405" rel="noopener noreferrer"&gt;Millie&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;I really heartily agree with this. I have a handful of apps I’ve made personally that I genuinely just consider “done”, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ductts.app/" rel="noopener noreferrer"&gt;Ductts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pocketcal.com/" rel="noopener noreferrer"&gt;PocketCal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cassidoo.github.io/todometer/" rel="noopener noreferrer"&gt;todometer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jumblie.com/" rel="noopener noreferrer"&gt;Jumblie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cassidoo.co/w9-crafter/" rel="noopener noreferrer"&gt;W-9 Crafter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cassidoo.itch.io/code-wave" rel="noopener noreferrer"&gt;Code Wave&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cassidoo.itch.io/thirteen-potions" rel="noopener noreferrer"&gt;Thirteen Potions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cassidoo.github.io/flapjack-fwop/" rel="noopener noreferrer"&gt;Flapjack Fwop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is, because they’re open source, people often look at the repository and see that the last code commit was, say, 3 (or 4 or 7 or 9) years ago, or that there’s some unanswered feature requests, and they’re like “ah, this software is unmaintained, it’s dead.” But they’re not! They just do their one job, well, and don’t need anything else!&lt;/p&gt;

&lt;p&gt;I feel like a lot of people in tech claim the famous Leonardo da Vinci quote, “Art is never finished, only abandoned,” when it comes to software, but… sometimes the app just does the job it’s supposed to do. Most times, software is not art, layered with meaning, rather it’s just a utility that does a task.&lt;/p&gt;

&lt;p&gt;I don’t really know what the solution is, here. More people finishing apps? Accepting that our work is not necessarily art? Less subscriptions? Wait, yeah, probably less subscriptions.&lt;/p&gt;

&lt;p&gt;Anyway. Thought of the day. Try my apps. Bye.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Configure your repositories with .github</title>
      <dc:creator>Cassidy Williams</dc:creator>
      <pubDate>Fri, 19 Dec 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/cassidoo/configure-your-repositories-with-github-3ie5</link>
      <guid>https://forem.com/cassidoo/configure-your-repositories-with-github-3ie5</guid>
      <description>&lt;p&gt;It’s Blogvent, day 19, where I blog daily in December!&lt;/p&gt;

&lt;p&gt;If you’ve bounced around GitHub before, it’s likely you’ve seen a &lt;code&gt;.github/&lt;/code&gt; folder at the top-level of a repository. You might have even seen a &lt;code&gt;.github&lt;/code&gt; repository in some organizations!&lt;/p&gt;

&lt;p&gt;This is incredibly hard to look up online, as you can imagine. It’s even admittedly a bit challenging to find out all that it can do in the documentation itself because of how it’s named. So, look no further, here’s all you can do (currently!) with &lt;code&gt;.github&lt;/code&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;.github&lt;/code&gt; everywhere
&lt;/h2&gt;

&lt;p&gt;Long story short: if you see &lt;code&gt;.github&lt;/code&gt;, it’s a magical thing that configures GitHub for you.&lt;/p&gt;

&lt;p&gt;In a repository, the &lt;code&gt;.github&lt;/code&gt; folder is a special directory used to store community health files, repository settings, automation workflows, and GitHub Copilot configuration files. GitHub automatically recognizes and uses specific files within this folder to customize the repository experience for contributors and maintainers!&lt;/p&gt;

&lt;p&gt;In an organization, the &lt;code&gt;.github&lt;/code&gt; repository is for “default community health files” for the repositories in your org. That means if you have an organization with like… 10 repositories, they will all default to the configurations in the &lt;code&gt;.github&lt;/code&gt; repository unless they’re overridden in the individual repos.&lt;/p&gt;

&lt;p&gt;I’m going to focus on individual repositories with the &lt;code&gt;.github&lt;/code&gt; folder for the rest of this post, but &lt;a href="https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file#supported-file-types" rel="noopener noreferrer"&gt;here’s the documentation&lt;/a&gt; for the &lt;code&gt;.github&lt;/code&gt; repository options for you, and &lt;a href="https://github.com/home-assistant/.github" rel="noopener noreferrer"&gt;here’s a good example of what that repo can look like&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;.github&lt;/code&gt; in your repository
&lt;/h2&gt;

&lt;p&gt;There’s some convenient things you can put in this folder to get things configured to your liking. As of now, December 2025, here’s what you can do!&lt;/p&gt;

&lt;p&gt;(if something in this list ends with &lt;code&gt;.md&lt;/code&gt;, that means it’s a markdown file, if it ends with &lt;code&gt;.yml&lt;/code&gt; it’s a YAML file, and if it ends with &lt;code&gt;/&lt;/code&gt;, that means it’s a folder for markdown or YAML files)&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue and pull request templates
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ISSUE_TEMPLATE/&lt;/code&gt;: Place YAML or Markdown issue templates here. You can have multiple templates for different issue types.

&lt;ul&gt;
&lt;li&gt;Examples: &lt;code&gt;.github/ISSUE_TEMPLATE/bug_report.md&lt;/code&gt; or &lt;code&gt;.github/ISSUE_TEMPLATE/feature_request.md&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;PULL_REQUEST_TEMPLATE.md&lt;/code&gt; or &lt;code&gt;PULL_REQUEST_TEMPLATE/&lt;/code&gt;: Template(s) that pre-fill descriptions when someone opens a new PR.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  GitHub Actions/workflows
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;workflows/&lt;/code&gt;: For YAML files that define &lt;a href="https://docs.github.com/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; workflows.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;.github/workflows/ci.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;You can use these to automate CI/CD, linting, deployments, tests, and a bunch of other nice things. &lt;a href="https://docs.github.com/en/actions/get-started/quickstart#creating-your-first-workflow" rel="noopener noreferrer"&gt;Docs here&lt;/a&gt; are handy, and &lt;a href="https://github.com/cassidoo/pocketcal/blob/main/.github/workflows/stale.yml" rel="noopener noreferrer"&gt;here’s an example I have in one of my repos&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community Health Files
&lt;/h3&gt;

&lt;p&gt;These files help set standards and support for your repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;: Set expectations for community behavior&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CONTRIBUTING.md&lt;/code&gt;: Guide for people who want to contribute to the project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FUNDING.yml&lt;/code&gt;: Show ways to financially support the project (&lt;a href="https://github.com/cassidoo/blahg/blob/main/.github/FUNDING.yml" rel="noopener noreferrer"&gt;example&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SECURITY.md&lt;/code&gt;: How to report security vulnerabilities&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SUPPORT.md&lt;/code&gt;: Let users know where to ask questions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a note, if you have these in your individual repository, they will override whatever is in the &lt;code&gt;.github&lt;/code&gt; repository in your organization, if that’s configured.&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; put some of these at the root of your repository for easy visibility (like &lt;code&gt;CONTRIBUTING.md&lt;/code&gt;), but either way, GitHub will surface those contents in the repo sidebar in a nice UI for folks to find.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration files
&lt;/h3&gt;

&lt;p&gt;These configure features or bots for you repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;dependabot.yml&lt;/code&gt;: Configures &lt;a href="https://docs.github.com/code-security/dependabot" rel="noopener noreferrer"&gt;Dependabot&lt;/a&gt; to keep your dependencies up-to-date&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CODEOWNERS&lt;/code&gt;: Define who owns certain files or paths. When someone opens a PR that touches those files, GitHub will automatically request a review from the listed people.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GitHub Copilot custom instructions and agents
&lt;/h3&gt;

&lt;p&gt;GitHub Copilot’s configuration settings are newest in the list so far, and help with code completion and guardrails for AI tools working in your repos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;copilot-instructions.md&lt;/code&gt;: Instructions here are automatically included in all Copilot requests for your repo across supported IDEs and platforms. This sets your coding standards, preferred libraries, name conventions, etc. &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/copilot/how-tos/configure-custom-instructions/add-repository-instructions#creating-repository-wide-custom-instructions-3" rel="noopener noreferrer"&gt;Docs here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;instructions/&lt;/code&gt;: Every file in here should be named &lt;code&gt;*.instructions.md&lt;/code&gt; (replace &lt;code&gt;*&lt;/code&gt; with the file name). This is for storing multiple, file-specific, or directory-specific instruction files. Each file in here can describe rules for a particular feature, language, file type, or folder. &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/copilot/how-tos/configure-custom-instructions/add-repository-instructions#creating-path-specific-custom-instructions-3" rel="noopener noreferrer"&gt;Docs here&lt;/a&gt; for what your syntax should look like, and &lt;a href="https://github.com/github/awesome-copilot/tree/main/instructions" rel="noopener noreferrer"&gt;here’s some good examples&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agents/&lt;/code&gt;: Similar to &lt;code&gt;.instructions&lt;/code&gt;, every file in here should be named &lt;code&gt;*.agent.md&lt;/code&gt;. This is for configuring the Github Copilot coding agent to do specific things. &lt;a href="https://github.com/github/awesome-copilot/tree/main/agents" rel="noopener noreferrer"&gt;Here’s a repo of a bunch of example custom agents you can use&lt;/a&gt;.

&lt;ul&gt;
&lt;li&gt;I literally learned while writing this post that you can make a &lt;code&gt;.github-private&lt;/code&gt; repository in your organization specifically for configuring default custom agents. Who knew? Don’t tell my boss. Anyway, &lt;a href="https://github.com/docs/custom-agents-template" rel="noopener noreferrer"&gt;here’s a template repo for that&lt;/a&gt; and &lt;a href="https://docs.github.com/en/copilot/concepts/agents/coding-agent/about-custom-agents#agent-profile-format" rel="noopener noreferrer"&gt;docs about these in general&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;prompts/&lt;/code&gt;: Also similar to &lt;code&gt;.instructions&lt;/code&gt;! Every file should be named &lt;code&gt;*.prompt.md&lt;/code&gt;. This lets you add reusable commands to GitHub Copilot. &lt;a href="https://docs.github.com/en/copilot/tutorials/customization-library/prompt-files/your-first-prompt-file" rel="noopener noreferrer"&gt;Docs here&lt;/a&gt; and &lt;a href="https://github.com/github/awesome-copilot/tree/main/prompts" rel="noopener noreferrer"&gt;handy examples here&lt;/a&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Oh my word stop
&lt;/h2&gt;

&lt;p&gt;Okay I think that’s it. There’s so many things you can do. I’m exhausted. There’s actually more types of configurations you can add to the &lt;code&gt;.github&lt;/code&gt; folder depending on the &lt;a href="https://github.com/marketplace" rel="noopener noreferrer"&gt;apps&lt;/a&gt; and Actions you have configured in your repository (like &lt;a href="https://github.com/actions/labeler" rel="noopener noreferrer"&gt;this one for labeling PRs lets you add &lt;code&gt;labeler.yml&lt;/code&gt;&lt;/a&gt;, for example). But I’ll let you explore those on your own.&lt;/p&gt;

&lt;p&gt;I hope this was handy for you!&lt;/p&gt;

</description>
      <category>github</category>
    </item>
  </channel>
</rss>
