<?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>DEV Community: Gunnari Auvinen</title>
    <description>The latest articles on DEV Community by Gunnari Auvinen (@cheerazar).</description>
    <link>https://dev.to/cheerazar</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3972627%2F1feff5c7-63ab-495c-9123-e95866b761df.jpg</url>
      <title>DEV Community: Gunnari Auvinen</title>
      <link>https://dev.to/cheerazar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cheerazar"/>
    <language>en</language>
    <item>
      <title>Print emojis to the terminal in C</title>
      <dc:creator>Gunnari Auvinen</dc:creator>
      <pubDate>Mon, 29 Jun 2026 12:54:00 +0000</pubDate>
      <link>https://dev.to/cheerazar/print-emojis-to-the-terminal-in-c-3dja</link>
      <guid>https://dev.to/cheerazar/print-emojis-to-the-terminal-in-c-3dja</guid>
      <description>&lt;p&gt;Recently I've started to work on building my own shell in C, which is one of the projects for the CSI class I'm taking. The first thing I had to decide is what would be the appearance of my shell. You may be asking yourself, "What would I want as part of my shell's appearance?" The answer should be obvious! Emojis are clearly the only correct answer 🚀&lt;/p&gt;

&lt;p&gt;For now, I'm going to call my shell unishell. I bet you've guessed which emoji will be part of prompt. If you guessed 🦄, you'd be correct! After I made this choice I realized that I wasn't entirely sure how I'd print out the emoji, as those clearly weren't covered in K&amp;amp;R.&lt;/p&gt;

&lt;p&gt;Looking online I was able to find the &lt;a href="https://home.unicode.org/" rel="noopener noreferrer"&gt;Unicode&lt;/a&gt; sequence for the unicorn, which is &lt;code&gt;U+1F984&lt;/code&gt;. I knew that I'd need an escape sequence to print it in C, but I wasn't sure exactly what it was. After a bit of searching I found out that there are two escape sequences, which are &lt;code&gt;\u&lt;/code&gt; and &lt;code&gt;\U&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;\u&lt;/code&gt; is used for unicode characters that can be encoded in four hex characters. On the other hand, &lt;code&gt;\U&lt;/code&gt; is used for unicode characters that are five or more hex characters long. Initially I didn't realize there was a &lt;code&gt;\U&lt;/code&gt; escape sequence, so I tried using &lt;code&gt;u1F984&lt;/code&gt;, which didn't turn out exactly as planned 😅 The code for the first attempt is below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// unishell.c&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\u1f984"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I ran the &lt;code&gt;emoji1&lt;/code&gt; executable file, I got this output 😬&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%2Fqpq4894sodpc8306ocby.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%2Fqpq4894sodpc8306ocby.png" alt="Terminal output with incorrect escape sequence" width="134" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first I was scratching my head for a moment, but then I realized it made sense. The unicorn emoji is five hex characters long and the translation on the screen is the first four characters translated to one character, with the leftover &lt;code&gt;4&lt;/code&gt; getting printed as a &lt;code&gt;4&lt;/code&gt;. It turns out that &lt;code&gt;U+1F98&lt;/code&gt; is the Greek capital letter &lt;a href="https://util.unicode.org/UnicodeJsps/character.jsp?a=1F98" rel="noopener noreferrer"&gt;Eta&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Following that incorrect solution, I tried to change the &lt;code&gt;\u1F984&lt;/code&gt; to a &lt;code&gt;\U1F984&lt;/code&gt;, but CLion showed that was an error. Unfortunately it didn't say what the error was 🤦🏼‍♂️ It turns out that you must pad the front of the Unicode characters with &lt;code&gt;0&lt;/code&gt;s until there are eight characters plus the escape sequence, which is &lt;code&gt;\U0001F984&lt;/code&gt;. With this update, I got the output below 🎉 &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%2Fo2ylb2gz2wu0ojbz5nab.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%2Fo2ylb2gz2wu0ojbz5nab.png" alt="Terminal output with correct escape sequence" width="139" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the final code for reference.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\U0001f984"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this solved, I can get onto the rest of the unishell implementation!&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>c</category>
    </item>
    <item>
      <title>Call vs. Apply in JavaScript</title>
      <dc:creator>Gunnari Auvinen</dc:creator>
      <pubDate>Mon, 22 Jun 2026 12:39:00 +0000</pubDate>
      <link>https://dev.to/cheerazar/call-vs-apply-in-javascript-1b4k</link>
      <guid>https://dev.to/cheerazar/call-vs-apply-in-javascript-1b4k</guid>
      <description>&lt;p&gt;Both &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; allow you to invoke a specific function and pass in a context, that will be &lt;code&gt;this&lt;/code&gt; within the function, as well as arguments. How you pass in the arguments for each method is different though and can certainly lead to frustration as you work to debug your code. Having spent some time debugging my own code due to this confusion, I figured it was worthwhile to write a blog post about it for reference, even if I'm the only one that refers to it in the future!&lt;/p&gt;

&lt;h3&gt;
  
  
  Call
&lt;/h3&gt;

&lt;p&gt;As stated previously &lt;code&gt;call&lt;/code&gt; allows you to invoke a function, pass in your desired context as the first argument, as well as your input arguments. In the case of the &lt;code&gt;call&lt;/code&gt; method, you pass in the arguments individually and separated by commas.&lt;/p&gt;

&lt;p&gt;One instance where it can be beneficial to use &lt;code&gt;call&lt;/code&gt; is when creating subclasses within JavaScript. Specifically if your subclass shares traits with your superclass, you can use call on the superclass to set the properties on the subclass. Here's a quick example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Business&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Restaurant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Business&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Restaurant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;Restaurant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Business&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;Restaurant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Restaurant&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;SupplyStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Business&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Supply Store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;SupplyStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Business&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;SupplyStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SupplyStore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;pizza&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Restaurant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;House of Slices&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your Neighborhood&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pizza&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;officeSupplies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SupplyStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;All Your Office Supply Needs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Next town over&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Office Supply Store&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another quick example of using &lt;code&gt;call&lt;/code&gt; is when you can use it to convert the arguments array of a function input from an array-like object to an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;addNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;previous&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;addNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply
&lt;/h3&gt;

&lt;p&gt;Now that I've discussed &lt;code&gt;call&lt;/code&gt;, you might wonder how &lt;code&gt;apply&lt;/code&gt; is any different, as they ostensibly do the same thing. &lt;code&gt;apply&lt;/code&gt; still takes a context as its first argument, but instead of taking individual arguments after that, &lt;code&gt;apply&lt;/code&gt; takes an array or array-like object instead.&lt;/p&gt;

&lt;p&gt;In this somewhat contrived example, if you wanted to print out the character code for each letter in an array of unknown length, you could use &lt;code&gt;apply&lt;/code&gt; to invoke that function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;testStringChars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello there!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;printCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;character code for "&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;" is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;printCharacters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;testStringChars&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Takeaway
&lt;/h3&gt;

&lt;p&gt;The main takeaway here is that both &lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; both allow you to invoke functions and supply the context that it should be invoked with. The fundamental difference between the two is how the input arguments are passed in when invoked. &lt;code&gt;call&lt;/code&gt; takes its input arguments as individual inputs, while &lt;code&gt;apply&lt;/code&gt; takes an array or array-like object. If you have a good example for &lt;code&gt;apply&lt;/code&gt; please let me know!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>software</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to undo a git rebase? Hint: git reflog and git reset</title>
      <dc:creator>Gunnari Auvinen</dc:creator>
      <pubDate>Mon, 15 Jun 2026 12:17:00 +0000</pubDate>
      <link>https://dev.to/cheerazar/how-to-undo-a-git-rebase-hint-git-reflog-and-git-reset-5gj</link>
      <guid>https://dev.to/cheerazar/how-to-undo-a-git-rebase-hint-git-reflog-and-git-reset-5gj</guid>
      <description>&lt;p&gt;The other day at work a group of us were asked if any of us were Git masters, at which point my ears perked up and I asked him to explain what exactly he needed help with at that moment. He then told me that a teammate had lost roughly a half-days worth of work after a bad git rebase and he wanted to know if it was possible to recover their lost work. Now while I'm not a Git master, I vaguely remembered something from a lecture and told him that I would look into it and get back to him in a few minutes.&lt;/p&gt;

&lt;p&gt;After a couple of minutes of searching I managed to find the information that I was searching for to "save the day." What I had discovered was that Git keeps track of the tips of branches and when they're changed and this information can be accessed via the &lt;code&gt;git reflog&lt;/code&gt; command. In this case the &lt;code&gt;git reflog&lt;/code&gt; command allowed us to find the reference to the commit that had been made prior to the bad &lt;code&gt;git rebase&lt;/code&gt;. The reflog had the various messages associated with the branch tip changes and in our case we looked for the last commit message that had been entered prior to the rebase, which had a reference similar to &lt;code&gt;HEAD@{7}&lt;/code&gt;. Having this reference allowed us to use the &lt;code&gt;git reset --hard HEAD@{7}&lt;/code&gt; command to go back to that specific commit. With a little bit of searching we fortunately saved hours worth of work!&lt;/p&gt;

&lt;p&gt;As this concept can be a little bit nebulous in just text I've provided an example below to help flush things out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of How to Undo a git rebase
&lt;/h3&gt;

&lt;p&gt;For this example I made a little git repository that uses master and the amazing-feature branch for us. Here is a printout of a &lt;code&gt;git log --oneline&lt;/code&gt; command before the &lt;code&gt;git rebase&lt;/code&gt; is done, while in the &lt;code&gt;amazing-feature&lt;/code&gt; branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;98008d5 Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
93c18de Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
abdc941 Add amazing-feature.
18244f8 Add the add &lt;span class="k"&gt;function &lt;/span&gt;to first-feature.
3a01fc1 Add the amazing first-feature.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  git-reflog-git-rebase-example git:&lt;span class="o"&gt;(&lt;/span&gt;amazing-feature&lt;span class="o"&gt;)&lt;/span&gt; git rebase master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, rewinding head to replay your work on top of it...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Applying: Add amazing-feature.
Applying: Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
Applying: Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
➜  git-reflog-git-rebase-example git:&lt;span class="o"&gt;(&lt;/span&gt;amazing-feature&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This added the other commits from master that this branch didn't have. Following that I did a &lt;code&gt;git log --oneline&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;b13c3f1 Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
4fdbc95 Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
085c6a5 Add amazing-feature.
2c0a30c Add the square &lt;span class="k"&gt;function &lt;/span&gt;to best-feature file.
18244f8 Add the add &lt;span class="k"&gt;function &lt;/span&gt;to first-feature.
3a01fc1 Add the amazing first-feature.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh no, we don't actually want that information from &lt;code&gt;master&lt;/code&gt; merged into the &lt;code&gt;amazing-feature&lt;/code&gt; branch! We need to figure out a way to undo that rebase. Fortunately we can look up the &lt;code&gt;HEAD&lt;/code&gt; reference that we want to go to by using the &lt;code&gt;git reflog&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;b13c3f1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;: rebase finished: returning to refs/heads/amazing-feature
b13c3f1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;: rebase: Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
4fdbc95 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;: rebase: Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
085c6a5 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3&lt;span class="o"&gt;}&lt;/span&gt;: rebase: Add amazing-feature.
2c0a30c HEAD@&lt;span class="o"&gt;{&lt;/span&gt;4&lt;span class="o"&gt;}&lt;/span&gt;: rebase: checkout master
98008d5 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;5&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
93c18de HEAD@&lt;span class="o"&gt;{&lt;/span&gt;6&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from master to amazing-feature
2c0a30c HEAD@&lt;span class="o"&gt;{&lt;/span&gt;7&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add the square &lt;span class="k"&gt;function &lt;/span&gt;to best-feature file.
18244f8 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;8&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from amazing-feature to master
93c18de HEAD@&lt;span class="o"&gt;{&lt;/span&gt;9&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
abdc941 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;10&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add amazing-feature.
18244f8 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;11&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from master to amazing-feature
18244f8 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;12&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add the add &lt;span class="k"&gt;function &lt;/span&gt;to first-feature.
3a01fc1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;13&lt;span class="o"&gt;}&lt;/span&gt;: commit &lt;span class="o"&gt;(&lt;/span&gt;initial&lt;span class="o"&gt;)&lt;/span&gt;: Add the amazing first-feature.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at the reflog printout, I know that to undo the &lt;code&gt;git rebase&lt;/code&gt; that I need to go to the reference &lt;code&gt;HEAD@{5}&lt;/code&gt; when I do a &lt;code&gt;git reset&lt;/code&gt;, as that reference is the last time the &lt;code&gt;HEAD&lt;/code&gt; pointed to the proper place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  git-reflog-git-rebase-example git:&lt;span class="o"&gt;(&lt;/span&gt;amazing-feature&lt;span class="o"&gt;)&lt;/span&gt; git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD@&lt;span class="o"&gt;{&lt;/span&gt;5&lt;span class="o"&gt;}&lt;/span&gt;
HEAD is now at 98008d5 Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
➜  git-reflog-git-rebase-example git:&lt;span class="o"&gt;(&lt;/span&gt;amazing-feature&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One last &lt;code&gt;git log --oneline&lt;/code&gt; to make sure that the rebase has been undone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;98008d5 Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
93c18de Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
abdc941 Add amazing-feature.
18244f8 Add the add &lt;span class="k"&gt;function &lt;/span&gt;to first-feature.
3a01fc1 Add the amazing first-feature.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phew it has been fixed! Here's what &lt;code&gt;git reflog&lt;/code&gt; shows after the &lt;code&gt;git reset&lt;/code&gt; command from immediately prior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;98008d5 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;: reset: moving to HEAD@&lt;span class="o"&gt;{&lt;/span&gt;5&lt;span class="o"&gt;}&lt;/span&gt;
b13c3f1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;1&lt;span class="o"&gt;}&lt;/span&gt;: rebase finished: returning to refs/heads/amazing-feature
b13c3f1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}&lt;/span&gt;: rebase: Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
4fdbc95 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;3&lt;span class="o"&gt;}&lt;/span&gt;: rebase: Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
085c6a5 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;4&lt;span class="o"&gt;}&lt;/span&gt;: rebase: Add amazing-feature.
2c0a30c HEAD@&lt;span class="o"&gt;{&lt;/span&gt;5&lt;span class="o"&gt;}&lt;/span&gt;: rebase: checkout master
98008d5 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;6&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add the divide &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
93c18de HEAD@&lt;span class="o"&gt;{&lt;/span&gt;7&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from master to amazing-feature
2c0a30c HEAD@&lt;span class="o"&gt;{&lt;/span&gt;8&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add the square &lt;span class="k"&gt;function &lt;/span&gt;to best-feature file.
18244f8 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;9&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from amazing-feature to master
93c18de HEAD@&lt;span class="o"&gt;{&lt;/span&gt;10&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add multiply &lt;span class="k"&gt;function &lt;/span&gt;to amazing-feature.
abdc941 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;11&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add amazing-feature.
18244f8 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;12&lt;span class="o"&gt;}&lt;/span&gt;: checkout: moving from master to amazing-feature
18244f8 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;13&lt;span class="o"&gt;}&lt;/span&gt;: commit: Add the add &lt;span class="k"&gt;function &lt;/span&gt;to first-feature.
3a01fc1 HEAD@&lt;span class="o"&gt;{&lt;/span&gt;14&lt;span class="o"&gt;}&lt;/span&gt;: commit &lt;span class="o"&gt;(&lt;/span&gt;initial&lt;span class="o"&gt;)&lt;/span&gt;: Add the amazing first-feature.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the reflog shows the &lt;code&gt;HEAD&lt;/code&gt; pointer moves back to the reference that was at &lt;code&gt;HEAD@{5}&lt;/code&gt; and is now at &lt;code&gt;HEAD@{6}&lt;/code&gt; in the last reflog printout.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always Push to Your Remote Prior to a git rebase
&lt;/h3&gt;

&lt;p&gt;While I was able to find a solution to the student's problem and we were able to save a half-days worth of work, there is an additional takeaway from this experience. My recommendation is that prior to performing a &lt;code&gt;git rebase&lt;/code&gt; always push your work up to a remote if you haven't already. This way even if your git local git history gets messed up, you can always just clone down the remote again.&lt;/p&gt;

&lt;p&gt;It really is great to know that you can go back in time and fix those seemingly unfixable mistakes with a few key strokes!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building Days Since Last</title>
      <dc:creator>Gunnari Auvinen</dc:creator>
      <pubDate>Wed, 10 Jun 2026 23:45:10 +0000</pubDate>
      <link>https://dev.to/cheerazar/building-days-since-last-41jd</link>
      <guid>https://dev.to/cheerazar/building-days-since-last-41jd</guid>
      <description>&lt;p&gt;I've been watching the NBA Finals with one eye on the series and the other on an idea that's been kicking around in my mind. Somewhere out there a Knicks fan is explaining to a group chat exactly how many days it has been since their last title. What if there were a site that just showed that number for every team across a variety of sports? A giant scoreboard counter for every championship drought, ticking up in real time. That idea turned into &lt;a href="https://dayssincelast.app" rel="noopener noreferrer"&gt;Days Since Last&lt;/a&gt;, and this post covers the decisions that went into building 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%2Fbkoutoaue02l8k2vxt9d.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%2Fbkoutoaue02l8k2vxt9d.png" alt="The Days Since Last homepage with the Arizona Cardinals' 28,654 day counter up top, live banners for three championship series, and drought boards for each league below" width="800" height="769"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The best API is no API
&lt;/h2&gt;

&lt;p&gt;My first instinct was probably the same one you have right now, which was to go find a sports API and start comparing free tiers. Then I did the math on what the site actually needs. At the absolute minimum, a drought counter needs exactly one fact per team, the date of their last title-clinching game. That dataset changes once per year per league, and it changes on a night that everyone knows about well in advance.&lt;/p&gt;

&lt;p&gt;Given that, there's no API. Instead, each league is a JSON file in the repo, and every date was pulled from box scores. The whole "backend" is a curated dataset, a static site generator, and a GitHub Action. There are no monthly costs and no rate limits, which is perfect for a little side project. When a champion is crowned in any of the leagues, updating the site is a simple one-line JSON edit. I cannot overstate how nice it is to maintain a "live" site that has no moving parts 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Astro, because the counter is the only JavaScript
&lt;/h2&gt;

&lt;p&gt;The site is almost entirely static content with exactly one interactive element, which is the ticking counter. That made the framework decision easy. Astro ships zero JavaScript by default, and the counter is a few KB of vanilla JS that computes the elapsed time from the clinching date on every tick. The number is always correct no matter when the site was last built. It's expected that most people will open these links from group chats on their phones, and that cold mobile load is exactly where shipping a tiny script instead of a framework runtime pays off.&lt;/p&gt;

&lt;h2&gt;
  
  
  The jumbotron
&lt;/h2&gt;

&lt;p&gt;For the design I wanted an arena scoreboard, not an analytics dashboard. The counters use &lt;a href="https://github.com/keshikan/DSEG" rel="noopener noreferrer"&gt;DSEG&lt;/a&gt;, a gorgeous open-source seven-segment font, with a dim ghost layer of 8s behind the digits so it reads like an LED panel with all of the segments faintly visible. Each team's page glows in its real colors. My favorite design problem in the whole project was light mode. A dozen teams have accent colors that simply vanish on a white page, like the Nets' white and the Lakers' gold. Each of those teams carries an alternate accent from its official palette that swaps in with the theme.&lt;/p&gt;

&lt;p&gt;What is sports fandom without a little bit or a whole lot of pain and disappointment? With this in mind, I thought that it would be fun to include some tidbits of events that have happened since a team last won a championship. This helps to really drive home how long some teams' droughts are at this point. Fortunately both the Red Sox and Cubs have won championships recently, otherwise the counter might not function properly 😬&lt;/p&gt;

&lt;p&gt;Below each team's counter are the facts that I think will make people want to send the link to their friends, families, and coworkers. For example, let's take a look at the Sacramento Kings. The Kings last won a title before the Moon landing, the iPhone, and ChatGPT. Fourteen presidencies have started since then. When they last won, Michael Jordan wouldn't be born for another twelve years. None of that is hardcoded. It all falls out of one date and a small list of reference events.&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%2Fou7e59j44ivexte0900p.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%2Fou7e59j44ivexte0900p.png" alt="The Sacramento Kings page with a giant purple seven-segment counter at 27,444 days and the list of things that have happened since their last title" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Share cards with a freshness problem
&lt;/h2&gt;

&lt;p&gt;Every team gets an Open Graph image rendered at build time with Satori in the same jumbotron style, so pasting a link into a chat unfurls into that team's number. Most people who see a shared link never click it, which means the unfurl is the site for them. Baking a day count into pixels also means the image goes stale at midnight. The fix is delightfully dumb. A GitHub Actions cron hits a deploy hook every night and rebuilds the whole site. The counters tick live in the browser, and the images never drift more than a day.&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%2Fukq41rdmbjlmkfeaj2uv.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%2Fukq41rdmbjlmkfeaj2uv.png" alt="The generated share card for the Sacramento Kings, a 1200 by 630 image of their drought counter in the jumbotron style" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trust, but verify every single date
&lt;/h2&gt;

&lt;p&gt;The thing that makes or breaks a site like this is whether the numbers are right, and championship history is full of traps. Does Oklahoma City carry Seattle's 1979 title? Officially yes. Do the Vikings count their 1969 NFL Championship? They don't, because the Super Bowl decided that season, which is why Vikings fans are still waiting. Did today's Hornets exist before 2002? Officially yes, since the NBA retconned their history back to 1988 in a deal made in 2014.&lt;/p&gt;

&lt;p&gt;I leaned on Claude Code agents for this in two passes. One set of agents built each league's dataset from box scores, and a second set was told to assume the first set made mistakes and to go find them. Across 193 teams and eight leagues, the adversarial pass found exactly one factual error. In the MLS, FC Dallas had been credited with a Supporters' Shield that D.C. United actually won. One error, in a footnote, across every clinching date in American sports history. I'll take it!&lt;/p&gt;

&lt;h2&gt;
  
  
  One JSON file per league
&lt;/h2&gt;

&lt;p&gt;The site launched as an NBA-only board, but the architecture never assumed that. Leagues load from a glob over the data directory, so adding the NFL meant adding a file. The nav link, the league board, the team pages, and the share cards all appear on the next build. There are eight leagues on the board now, from the NFL down to the brand-new PWHL, whose Montréal Victoire lifted the Walter Cup just three weeks ago. The all-sports view surfaces the heavyweight, the Arizona Cardinals, whose last championship came in 1947. That counter has five digits 😬&lt;/p&gt;

&lt;p&gt;As I write this, the Knicks and the Spurs are playing in the Finals, and the Hurricanes and the Golden Knights are tied in the Stanley Cup Final. Two of the longest waits on the site might reset to zero within the week. That's the thing I love most about this project. It's a static site with a built-in season finale.&lt;/p&gt;

&lt;p&gt;Check it out at &lt;a href="https://dayssincelast.app" rel="noopener noreferrer"&gt;dayssincelast.app&lt;/a&gt;, and the code is &lt;a href="https://github.com/cheerazar/days-since-last" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;. If your team's counter hurts to look at, I'm sorry. The clock doesn't lie 😅&lt;/p&gt;

</description>
      <category>astro</category>
      <category>typescript</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>What is Semantic Versioning?</title>
      <dc:creator>Gunnari Auvinen</dc:creator>
      <pubDate>Mon, 08 Jun 2026 12:43:00 +0000</pubDate>
      <link>https://dev.to/cheerazar/what-is-semantic-versioning-3151</link>
      <guid>https://dev.to/cheerazar/what-is-semantic-versioning-3151</guid>
      <description>&lt;h3&gt;
  
  
  Versioning and Software Development
&lt;/h3&gt;

&lt;p&gt;As you've probably seen while writing your own software, your code can change a little bit from version to version, or it can change quite a bit, or it can be completely overhauled. As you write code and go from version to version, are you using a versioning system to keep track of the types of changes from build to build? If so are you following a defined system? To my understanding there is currently no universally adopted specification for software versioning, but one specification that many people use is called &lt;a href="http://SemVer.org/" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; specification or SemVer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Semantic Versioning?
&lt;/h3&gt;

&lt;p&gt;Alright now that you know about the SemVer specification, what exactly is it and how is it defined? SemVer uses the following three categories: major, minor, and patch. These map to the x.y.z numbering system, eg 1.2.3 would be major version 1, minor version 2, and patch version 3.&lt;/p&gt;

&lt;p&gt;Ok... what exactly do major, minor, and patch mean with respect to software versions? The following information has been taken directly from the &lt;a href="http://SemVer.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt; website:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;MAJOR version when you make incompatible API changes,&lt;/li&gt;
&lt;li&gt;MINOR version when you add functionality in a backwards-compatible manner, and&lt;/li&gt;
&lt;li&gt;PATCH version when you make backwards-compatible bug fixes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are a couple of main takeaways from this information. The first being that you should always review what changed in a piece of software when they update the major version number. Specifically due to the fact that certain aspects of the API may or may not have changed. The documentation should be examined to ensure that either the changes allow continued functionality of your own project or that your project will need to be refactored due to the changes. On the other hand upgrading a dependency when the minor or patch version is updated, is less concerning, as all of these changes are expected to backwards compatible. Armed with this information you now know when it is possible to upgrade a dependency without fear of likely breaking anything and when you will need to review the new software to see if you will need to change any of your own code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is This Important?
&lt;/h3&gt;

&lt;p&gt;Well all of that is great information, but why should you care? As you develop software you want to avoid something coined "dependency hell". Specifically you don't want to be put into a position where changes in your dependencies will break your entire system or leave it in a state where you cannot easily make changes. The Semantic Versioning specification assists you in avoiding that unenviable position. This is made possible by the ability to determine whether or not when a dependency is updated whether or not it is backwards compatible. If the update is either minor or a patch in nature, you will be confident in updating that dependency, as by the SemVer definitions the public API of that dependency will still function the same as it was previously defined. While on the other hand if changes in a dependency result in incompatibility you can require that your software uses a specific version of the software, such that you ensure continued functionality.&lt;/p&gt;

&lt;p&gt;When you work on your next project work on implementing the SemVer specification as your versioning system. There's additional thoughts and points behind SemVer on the specifications &lt;a href="http://SemVer.org/" rel="noopener noreferrer"&gt;website&lt;/a&gt;. This will make all of our lives as developers that much easier and fruitful!&lt;/p&gt;

</description>
      <category>software</category>
      <category>programming</category>
    </item>
    <item>
      <title>What Do the ~, ^, and * Mean in package.json?</title>
      <dc:creator>Gunnari Auvinen</dc:creator>
      <pubDate>Sun, 07 Jun 2026 15:04:00 +0000</pubDate>
      <link>https://dev.to/cheerazar/what-do-the-and-mean-in-packagejson-3jd2</link>
      <guid>https://dev.to/cheerazar/what-do-the-and-mean-in-packagejson-3jd2</guid>
      <description>&lt;h3&gt;
  
  
  ~, ^, and * in package.json... wat?
&lt;/h3&gt;

&lt;p&gt;The first time you open up a package.json file you're greeted by a lot of information about that project. That one file can include a lot of information about the project: the author's name and email, the project title, where the project is hosted, where to submit bugs, startup scripts, and more. The parts that I'm going to discuss in this post are found within the &lt;code&gt;dependencies&lt;/code&gt; and &lt;code&gt;devDependencies&lt;/code&gt; sections.&lt;/p&gt;

&lt;p&gt;Frequently you will see module version numbers prefixed with a &lt;code&gt;~&lt;/code&gt; or &lt;code&gt;^&lt;/code&gt; and sometimes you'll even see just a &lt;code&gt;*&lt;/code&gt;. What exactly do these characters correlate with respect to version numbers? When you run &lt;code&gt;npm install&lt;/code&gt;, the &lt;code&gt;~&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;, and &lt;code&gt;*&lt;/code&gt; tell npm what versions of the dependencies to install for the project. So how do those characters relate to version numbers at all?&lt;/p&gt;

&lt;p&gt;The numbers listed there certainly make sense, but what do the other characters mean? After all you know what version of software you wanted when you required the module, why would you want or need anything else? Well these characters help provide flexibility on what versions of dependencies are installed when the &lt;code&gt;npm install&lt;/code&gt; command is run. Let's take a look at what each one does and why that functionality is useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Semantic Versioning Breakout
&lt;/h3&gt;

&lt;p&gt;Real quick before we dive into the what the characters do, let me first give a brief overview of the software versioning system that npm modules use. They follow the &lt;a href="http://SemVer.org" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt;, or SemVer, specification. These map to a x.y.z numbering system, eg 1.2.3 would be major version 1, minor version 2, and patch version 3.&lt;/p&gt;

&lt;p&gt;What exactly do major, minor, and patch mean with respect to software versions? The following information has been taken directly from the &lt;a href="http://SemVer.org/" rel="noopener noreferrer"&gt;SemVer&lt;/a&gt; website:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;MAJOR version when you make incompatible API changes,&lt;/li&gt;
&lt;li&gt;MINOR version when you add functionality in a backwards-compatible manner, and&lt;/li&gt;
&lt;li&gt;PATCH version when you make backwards-compatible bug fixes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For an expanded look at semantic versioning, I wrote a previous post about the subject that can be found &lt;a href="https://dev.to/what-is-semantic-versioning/"&gt;here&lt;/a&gt;. Alright let's jump back into the the examination of the &lt;code&gt;~&lt;/code&gt;, &lt;code&gt;^&lt;/code&gt;, and &lt;code&gt;*&lt;/code&gt; characters!&lt;/p&gt;

&lt;h3&gt;
  
  
  ~, ^, and *? Oh I see what they do now...
&lt;/h3&gt;

&lt;p&gt;Let's start by looking at the &lt;code&gt;~&lt;/code&gt;. The &lt;code&gt;~&lt;/code&gt; character fixes both the major and minor version numbers, while matching any patch number. e.g. if the version dependency was defined as &lt;code&gt;~2.3.1&lt;/code&gt;, npm would match all versions greater than or equal to &lt;code&gt;2.3.1&lt;/code&gt; and less than &lt;code&gt;2.4.0&lt;/code&gt; for that dependency.&lt;/p&gt;

&lt;p&gt;Next up is the &lt;code&gt;^&lt;/code&gt;, which locks down the major version number, but leaves the minor and patch versions to be more flexible. When installing a dependency that is listed with the version of &lt;code&gt;^2.2.3&lt;/code&gt;, npm will match any version that is greater than or equal to &lt;code&gt;2.2.3&lt;/code&gt; and also less than &lt;code&gt;3.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally there is the &lt;code&gt;*&lt;/code&gt;, which while available, isn't used as often. The primary reason for its less frequent use is the fact that it acts as a stand in for either the major, minor, or patch number and catches any version number for the place that it represents. For example a dependency with a version of &lt;code&gt;*&lt;/code&gt; would equate to any version that was greater than or equal to &lt;code&gt;0.0.0&lt;/code&gt;, while &lt;code&gt;1.*&lt;/code&gt; would allow versions greater than or equal to &lt;code&gt;1.0.0&lt;/code&gt; and less than &lt;code&gt;2.0.0&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importance of Dependency Versions
&lt;/h3&gt;

&lt;p&gt;Gaining a greater understanding how the versioning system works in the &lt;code&gt;package.json&lt;/code&gt; file will hopefully help you to avoid dependency hell down the line. Take a little bit of time now to familiarize yourself with the system that the &lt;code&gt;package.json&lt;/code&gt; file uses, so you can avoid headaches later. Also take some time to review the SemVer specification, so you can properly version your own software in the future!&lt;/p&gt;

</description>
      <category>software</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
