<?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.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>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>
