<?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: JavaScript Joel</title>
    <description>The latest articles on DEV Community by JavaScript Joel (@joelnet).</description>
    <link>https://dev.to/joelnet</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%2F2416%2Fba54e7d3-3e6d-494c-95a8-6721d250a6de.jpg</url>
      <title>DEV Community: JavaScript Joel</title>
      <link>https://dev.to/joelnet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joelnet"/>
    <language>en</language>
    <item>
      <title>Dungeon Sweep: Knight -- devlog 001</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Tue, 25 Apr 2023 22:27:29 +0000</pubDate>
      <link>https://dev.to/joelnet/dungeon-sweep-knight-devlog-001-3d7g</link>
      <guid>https://dev.to/joelnet/dungeon-sweep-knight-devlog-001-3d7g</guid>
      <description>&lt;p&gt;I recently decided I wanted to make an indie game. I have had this idea for a while and I think it's about time.&lt;/p&gt;

&lt;p&gt;The idea is a variation of Minesweeper with RPG elements. I'm thinking about calling it &lt;strong&gt;Dungeon Sweep: Knight&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Art
&lt;/h2&gt;

&lt;p&gt;I can't art, so I decided to go hunting for a ready-to-use tileset. A quick google search brought me to a &lt;a href="https://0x72.itch.io/16x16-dungeon-tileset"&gt;16x16-dungeon-tileset&lt;/a&gt; with a style that I can only describe as perfect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CYXduLRf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjjssqv60kwqjwtl99uq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CYXduLRf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjjssqv60kwqjwtl99uq.png" alt="Dungeon Map" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Game Engine
&lt;/h2&gt;

&lt;p&gt;After barely doing any research, I landed on &lt;a href="https://phaser.io/"&gt;PhaserJS&lt;/a&gt;. My decision primarily was it still being in active development and not abandoned yet like all the others. So let's give it a try!&lt;/p&gt;

&lt;p&gt;I know I can use &lt;a href="https://cordova.apache.org/"&gt;Apache Cordova&lt;/a&gt; to turn this into native Android and iOS. I don't know how well that process works, but that's a problem for Future Joel, not Today Joel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating a Dungeon
&lt;/h2&gt;

&lt;p&gt;Now that I have the perfect tileset in hand, it's time to create a dungeon. This ended up being a lot harder than I thought it would be. My initial plan was to hand-create dungeons using plain text files. Run that through a function and bam, dungeon!&lt;/p&gt;

&lt;p&gt;Example early dungeon map (that didn't work):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#########################
#     #    x        P   #
#     #        x        #
#     ############      #
#   x       x       x   #
#########################
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had a lot of difficulties with this. The first is I am using &lt;code&gt;#&lt;/code&gt; to draw a top wall, left wall, right wall, and bottom wall. The graphics were different for each wall. This was going to be difficult.&lt;/p&gt;

&lt;p&gt;So I decided to run these problems through ChatGPT. Let ChatGPT solve this so I can get on with the fun stuff. Unfortunately, ChatGPT was TERRIBLE at this. Even worse than me. So that wasn't gonna work.&lt;/p&gt;

&lt;p&gt;After realizing how difficult a problem I gave myself, I stepped back and did a search on NPM for dungeon generators. There were MANY on there, but one stuck out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c9eHVqCw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgcq58aetox9d20oqalh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c9eHVqCw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tgcq58aetox9d20oqalh.png" alt="Open Source Dungeon Generator" width="776" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@halftheopposite/dungeon"&gt;@halftheopposite/dungeon&lt;/a&gt; was exactly what I was looking for. It was configurable and I was confident I could make it work.&lt;/p&gt;

&lt;p&gt;I ended up abandoning my custom dungeon generator for this one.&lt;/p&gt;

&lt;p&gt;The dungeon generator used a different tileset, so I tweaked it until my tileset would work with it. This ended up being a little more difficult than I had anticipated since each dungeon tile returned was a number. So I had to map each number to a graphic. This was tedious but once it was done I fired up the game and it generated this beautiful map!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_1n8V117--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0dz5qa5tqlr6xrt3f2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_1n8V117--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0dz5qa5tqlr6xrt3f2h.png" alt="Beautiful Map" width="564" height="840"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm trying to keep the game as a 9:16 portrait ratio so mobile view works well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I have a solid base for my game, engine, graphics, random dungeons that look great. Next I'll be adding the gameplay mechanics. I'll have to drop down some enemies, lay a fog of war on top.&lt;/p&gt;

&lt;p&gt;I think I'll have the Knight run around chopping at everything, I think that could also be fun.&lt;/p&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

</description>
      <category>indie</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Creating a TypeWriter Effect in Phaser.js v3</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Mon, 24 Apr 2023 18:30:02 +0000</pubDate>
      <link>https://dev.to/joelnet/creating-a-typewriter-effect-in-phaserjs-v3-4e66</link>
      <guid>https://dev.to/joelnet/creating-a-typewriter-effect-in-phaserjs-v3-4e66</guid>
      <description>&lt;p&gt;I recently added some dialog options for my indie game, &lt;strong&gt;Dungeon Sweeper: A Knights Adventure&lt;/strong&gt; and wanted to create a TypeWriter effect for the dialog text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hVBXF0Me--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zwyaqf6hrwt4z6z1e51d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hVBXF0Me--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zwyaqf6hrwt4z6z1e51d.gif" alt="Dungeon Sweeper: A Knights Adventure dialog animation" width="320" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This technique works well for monospaced fonts and may not work for variable-width fonts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failed Attempts
&lt;/h2&gt;

&lt;p&gt;My first attempt was to write out text one letter at a time. But this didn't work with text that wasn't aligned to the left or text that wrapped.&lt;/p&gt;

&lt;p&gt;My second attempt was to use a non-space white space to replace all characters. This would help with the non-left text and word-wrapped text, but then I learned not all white space is created equal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Figure Space
&lt;/h2&gt;

&lt;p&gt;I found &lt;a href="https://qwerty.dev/whitespace/"&gt;an amazing webpage&lt;/a&gt; that helped me find the correct white space to use. The space I need is called a Figure Space and is the same width as a character.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code
&lt;/h2&gt;

&lt;p&gt;I wanted to be able to create a function that accepts a &lt;code&gt;Phaser.GameObjecte.Text&lt;/code&gt; and automatically applies the animation.&lt;/p&gt;

&lt;p&gt;The function would maintain the state needed to run the animation.&lt;/p&gt;

&lt;p&gt;The function would need to be awaitable, so the caller knows when the animation is complete.&lt;/p&gt;

&lt;p&gt;The function works by first resetting the &lt;code&gt;text&lt;/code&gt; to empty. Then every interval, it writes out the next letter. To maintain the same letter positions, the &lt;code&gt;text&lt;/code&gt; is kept the same length. The unseen characters are replaced with invisible characters.&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="cm"&gt;/**
 * Create typewriter animation for text
 * @param {Phaser.GameObjects.Text} target
 * @param {number} [speedInMs=25]
 * @returns {Promise&amp;lt;void&amp;gt;}
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;animateText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;speedInMs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// store original text&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;invisibleMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt; &lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// clear text on screen&lt;/span&gt;
  &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// mutable state for visible text&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;visibleText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// use a Promise to wait for the animation to complete&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEvent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;speedInMs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// if all characters are visible, stop the timer&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy&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;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// add next character to visible text&lt;/span&gt;
        &lt;span class="nx"&gt;visibleText&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;visibleText&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="c1"&gt;// right pad with invisibleText&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;invisibleText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;invisibleMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visibleText&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="c1"&gt;// update text on screen&lt;/span&gt;
        &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;visibleText&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;invisibleText&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="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I'm pretty happy with how the animation turned out and I am now calling this from within my dialog function.&lt;/p&gt;

&lt;p&gt;If you are interested in following the game's development, toss your email into the newsletter box on &lt;a href="http://joel.net"&gt;http://joel.net&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>javascript</category>
      <category>phaser</category>
    </item>
    <item>
      <title>🧠 I Code Differently Depending on These 5 Project Types</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Tue, 03 Nov 2020 17:54:29 +0000</pubDate>
      <link>https://dev.to/joelnet/i-code-differently-depending-on-these-5-project-types-apm</link>
      <guid>https://dev.to/joelnet/i-code-differently-depending-on-these-5-project-types-apm</guid>
      <description>&lt;p&gt;There are a lot of articles out there talking about best practices, patterns, principles, etc. When I say a lot, I really mean an overwhelming soul crushing amount of articles. But few of them talk about &lt;em&gt;when&lt;/em&gt; these practices should be applied.&lt;/p&gt;

&lt;p&gt;Even worse are the debates on social media about best practices and anti-patterns that are also without context.&lt;/p&gt;

&lt;p&gt;It's the context that is missing and is so important in making these decisions. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context is King!&lt;/strong&gt; 👑&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/olULbdwJ9rE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I Really Write Code Differently?
&lt;/h2&gt;

&lt;p&gt;Absolutely. There's a quote somewhere that goes something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A Junior Developer knows not of design patterns. A Senior Developer knows when to apply design patterns. A Master Developer knows when not to apply those design patterns." -- Unknown Author&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There isn't a single design pattern that has a rule that says it should be used in 100% of scenarios. But sometimes we treat them like they should be.&lt;/p&gt;

&lt;p&gt;With all codes, patterns, practices, use your best judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Types
&lt;/h2&gt;

&lt;p&gt;There are a few ways I classify the projects that I work on. The project type usually determines how I design the software.&lt;/p&gt;

&lt;p&gt;This is by no means an exhaustive list and may include overlap. Your list may be different.&lt;/p&gt;

&lt;h4&gt;
  
  
  Proof of Concept
&lt;/h4&gt;

&lt;p&gt;A Proof of Concept (PoC) project's priority is &lt;strong&gt;development time&lt;/strong&gt;. A PoC project should be created as fast as possible.&lt;/p&gt;

&lt;p&gt;You may be tempted to write the code in a way that could be re-used if the project moves out of the PoC phase, but you would be sacrificing the main priority, which is speed of development.&lt;/p&gt;

&lt;p&gt;Do you struggle with flex grid when you could bang out a &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; in 3 seconds? Okay, use a &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Would setting up React take too long when you could do the same in jQuery in a minute? Okay, then use jQuery!&lt;/p&gt;

&lt;p&gt;Redux vs a Global? Okay... you get it now.&lt;/p&gt;

&lt;p&gt;Testing, Logging, Metrics, Monitoring, Performance, Scaling? Not in the PoC. Just make it work.&lt;/p&gt;

&lt;p&gt;Whether it is successful or not, this code should be mostly discarded.&lt;/p&gt;

&lt;h4&gt;
  
  
  Personal (Pet Projects)
&lt;/h4&gt;

&lt;p&gt;This is my favorite type of project because &lt;strong&gt;there are no rules&lt;/strong&gt;. The project's priority is me! Do I want to go with a functional (FP) design? I'm gonna go for it. Do I want to learn a new technology? Hell ya!&lt;/p&gt;

&lt;p&gt;This is usually where I explore. I find some new technology and I explore it as much as I can in my own personal pet projects.&lt;/p&gt;

&lt;p&gt;I typically apply more care for readability (compared to a PoC) in my Personal projects because I tend to pick them up again after years and still want to be able to understand them.&lt;/p&gt;

&lt;p&gt;I don't care too much about testing or design patterns. I'm usually just exploring here.&lt;/p&gt;

&lt;p&gt;I also like to include a &lt;code&gt;README.md&lt;/code&gt; to remind me how to start/debug/deploy the project. This has saved my ass more than once.&lt;/p&gt;

&lt;h4&gt;
  
  
  Open Source
&lt;/h4&gt;

&lt;p&gt;The priority of an Open Source project should be &lt;strong&gt;readability&lt;/strong&gt;. The audience of this project is people who will use the code as well as people who will read the code.&lt;/p&gt;

&lt;p&gt;You will be judged by the quality of your source, so keep it tight, clean, and well documented.&lt;/p&gt;

&lt;p&gt;The higher the code coverage the better on an Open Source project. Give contributors the confidence of seeing green tests to know they didn't break anything. Also give yourself confidence to merge requests.&lt;/p&gt;

&lt;p&gt;It's good to have some design patterns and practices laid out in a &lt;code&gt;CONTRIBUTORS.md&lt;/code&gt;. This will clear up how contributors should write code and give you something to point to when a merge request deviates from the standard.&lt;/p&gt;

&lt;p&gt;Code should be crafted with consideration, care, and impact.&lt;/p&gt;

&lt;h4&gt;
  
  
  Libraries
&lt;/h4&gt;

&lt;p&gt;Library code should &lt;strong&gt;focus on the developer experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The focus should be on creating documentation and example code. The projects I love all have great documentation.&lt;/p&gt;

&lt;p&gt;I also spend a little extra time to focus on input validation and verbose Error messages. You don't know what values a developer is going to pass into your code. So a little extra attention at this step can go a long way.&lt;/p&gt;

&lt;p&gt;The focus on input validation can be the difference between good errors and bad errors.&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="c1"&gt;// ❌ Error: Cannot read property 'toString' of undefined&lt;/span&gt;
&lt;span class="c1"&gt;// ✅ Error: Options must include a 'url' property. more info: https://&amp;lt;url-to-docs&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I try to optimize the code since I do not know how or where the code will be used and don't want to be the bottleneck in someone's application.&lt;/p&gt;

&lt;p&gt;I also consider supporting TypeScript types. It's nice when you type dot and the editor will IntelliSense complete your code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enterprise Applications
&lt;/h4&gt;

&lt;p&gt;The main focus of an enterprise application is &lt;strong&gt;uptime and performance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Extra time needs to be spent to catch bugs before reaching production. This means unit tests, integration tests, cicd, etc.&lt;/p&gt;

&lt;p&gt;Logging, Metrics, Monitoring, and Alerting all become critical to identify and debug issues.&lt;/p&gt;

&lt;p&gt;Care must be taken when handling API keys and other secrets which could be leaked from source code.&lt;/p&gt;

&lt;p&gt;Deployments tend to be slower due to the coordination and QA involved. So it's nice to be able to change configuration values without redeploying the application.&lt;/p&gt;

&lt;p&gt;There is a lot of care that goes into an enterprise application to make sure it's always up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;It can be overwhelming reading and navigating tech articles today. Take them all with a grain of salt and context. There are times to use them, there are also times to not.&lt;/p&gt;

&lt;p&gt;There is no one size fits all. It all depends on the context.&lt;/p&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Join my 📰 &lt;a href="https://joel.net/newsletter"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Subscribe to my 📺 YouTube, &lt;a href="https://www.youtube.com/c/JoelCodes?sub_confirmation=1"&gt;JoelCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Say hi to me on Twitter &lt;a href="https://twitter.com/joelnet"&gt;@joelnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@markusspiske?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Markus Spiske&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/different?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>patterns</category>
      <category>projects</category>
      <category>programmer</category>
    </item>
    <item>
      <title>FREE JamStack / Static Site Hosting with Keybase.io</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Mon, 26 Oct 2020 18:10:33 +0000</pubDate>
      <link>https://dev.to/joelnet/free-jamstack-static-site-hosting-with-keybase-io-3127</link>
      <guid>https://dev.to/joelnet/free-jamstack-static-site-hosting-with-keybase-io-3127</guid>
      <description>&lt;p&gt;&lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase&lt;/a&gt; offers secure messaging and file sharing. Included in the file sharing offering is &lt;strong&gt;250GB of storage which can also be used to host public JamStack / Static Websites&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/GzhhG5ItwY8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Keybase
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keybase Sites&lt;/strong&gt; are accessed through their software so you'll have to head over to &lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase.io&lt;/a&gt; and follow the directions for your operating system to install.&lt;/p&gt;

&lt;p&gt;After installing the &lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase&lt;/a&gt; client, navigate to the &lt;strong&gt;Files&lt;/strong&gt; tab. You should see a screen similar to this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1603410494221%2FEPird1Mn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1603410494221%2FEPird1Mn4.png" alt="keybase.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the directions to &lt;strong&gt;Enable Keybase&lt;/strong&gt; for the file system for your operating system. This will give you native file system access to your &lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase&lt;/a&gt; secure file share.&lt;/p&gt;

&lt;p&gt;Once the &lt;strong&gt;Keybase File System&lt;/strong&gt; has been installed you should be able to access your files at &lt;code&gt;/keybase&lt;/code&gt; for Mac/Linux and &lt;code&gt;K:\&lt;/code&gt; on Windows.&lt;/p&gt;

&lt;p&gt;If everything is setup correctly, under &lt;code&gt;/keybase&lt;/code&gt; you should see three directories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/keybase
    /private
    /public
    /team
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Keybase Subdomain
&lt;/h2&gt;

&lt;p&gt;All &lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase&lt;/a&gt; accounts are given a subdomain with the format &lt;code&gt;&amp;lt;username&amp;gt;.keybase.pub&lt;/code&gt;. For example, my username is &lt;code&gt;joelnet&lt;/code&gt;, so my subdomain is &lt;a href="https://joelnet.keybase.pub" rel="noopener noreferrer"&gt;joelnet.keybase.pub&lt;/a&gt;. This is where my static files will live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copying Files to Keybase
&lt;/h2&gt;

&lt;p&gt;Files can be added to the &lt;strong&gt;Keybase Subdomain&lt;/strong&gt; by copying them into &lt;code&gt;/keybase/public/joelnet&lt;/code&gt; (&lt;code&gt;K:\public\joelnet&lt;/code&gt; on Windows). All files copied here are &lt;strong&gt;PUBLIC&lt;/strong&gt; and everyone has &lt;strong&gt;read&lt;/strong&gt; access to them.&lt;/p&gt;

&lt;p&gt;I have prepared a Gatsby site that I am going to copy to &lt;code&gt;/keybase/public/joelnet&lt;/code&gt;  (&lt;code&gt;K:\public\joelnet&lt;/code&gt; on Windows).&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1603412507383%2FugCFyuqtG.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1603412507383%2FugCFyuqtG.gif" alt="copy-files-to-keybase.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your website has been deployed! Open up a browser and visit your new site. My site is now up and visible on &lt;a href="https://joelnet.keybase.pub" rel="noopener noreferrer"&gt;joelnet.keybase.pub&lt;/a&gt; 🔥&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Domain Names
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase&lt;/a&gt; also supports custom domain names, but the process is a little different.&lt;/p&gt;

&lt;p&gt;The site needs to be deployed under &lt;code&gt;/keybase/private/&amp;lt;username&amp;gt;,kbpbot/&amp;lt;site&amp;gt;&lt;/code&gt; (&lt;code&gt;K:\private\&amp;lt;username&amp;gt;,kbpbot/&amp;lt;site&amp;gt;&lt;/code&gt; on Windows). &lt;code&gt;&amp;lt;site&amp;gt;&lt;/code&gt; can be any name. This gives you the flexibility to host multiple sites on &lt;a href="https://keybase.io" rel="noopener noreferrer"&gt;Keybase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The next step is setting up the DNS.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;CNAME&lt;/code&gt; to point to &lt;code&gt;kbp.keybaseapi.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next create a &lt;code&gt;TXT&lt;/code&gt; record. If your site is at &lt;code&gt;my-site.example.com&lt;/code&gt;, then prefix the record with &lt;code&gt;_keybase_pages.&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is what my DNS records look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1603413846461%2Fqpclb_3J8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1603413846461%2Fqpclb_3J8.png" alt="dns.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After copying your files, your website should be accessible on your custom domain!&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;More information about &lt;a href="https://book.keybase.io/sites" rel="noopener noreferrer"&gt;Keybase Sites&lt;/a&gt; can be found &lt;a href="https://book.keybase.io/sites" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Join my 📰 &lt;a href="https://joel.net/newsletter" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Subscribe to my 📺 YouTube, &lt;a href="https://www.youtube.com/c/JoelCodes?sub_confirmation=1" rel="noopener noreferrer"&gt;JoelCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Say hi to me on Twitter &lt;a href="https://twitter.com/joelnet" rel="noopener noreferrer"&gt;@joelnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://www.pexels.com/@killian-eon-1185568" rel="noopener noreferrer"&gt;Killian Eon&lt;/a&gt; from &lt;a href="https://www.pexels.com/photo/blue-metal-tool-2635595" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>hosting</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Custom Array Sort Algorithms in JavaScript</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Thu, 22 Oct 2020 21:05:22 +0000</pubDate>
      <link>https://dev.to/joelnet/custom-array-sort-algorithms-in-javascript-56g9</link>
      <guid>https://dev.to/joelnet/custom-array-sort-algorithms-in-javascript-56g9</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-S8b_j5XBV0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript's Default Array Sort
&lt;/h2&gt;

&lt;p&gt;JavaScript's &lt;code&gt;Array.sort&lt;/code&gt; defaults to a &lt;code&gt;String&lt;/code&gt; sort. This catches many people off guard when attempting to sort an &lt;code&gt;Array&lt;/code&gt; of type &lt;code&gt;Number&lt;/code&gt;.&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="c1"&gt;// ❌ Default search is a String search&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&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;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// [ 1, 10, 15, 3 ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, each &lt;code&gt;Number&lt;/code&gt; is converted to a &lt;code&gt;String&lt;/code&gt; and then sorted using a &lt;code&gt;String&lt;/code&gt; sort.&lt;/p&gt;

&lt;p&gt;At first, this can seem like a WTF JavaScript moment, but this happens because an &lt;code&gt;Array&lt;/code&gt; can contain mixed elements and JavaScript doesn't know how it should sort. So &lt;code&gt;sort&lt;/code&gt; defaults to a &lt;code&gt;String&lt;/code&gt; sort.&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;const&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Joel&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we want something other than a &lt;code&gt;String&lt;/code&gt; sort, we have to be explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Sort Compare Function
&lt;/h2&gt;

&lt;p&gt;Creating a custom sort compare function is pretty easy. The function takes two elements, then we return &lt;code&gt;-1&lt;/code&gt; if the first is lower and &lt;code&gt;1&lt;/code&gt; if it's higher. &lt;code&gt;0&lt;/code&gt; for the same.&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;const&lt;/span&gt; &lt;span class="nx"&gt;compareFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Pseudo Code&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;less&lt;/span&gt; &lt;span class="nx"&gt;than&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;more&lt;/span&gt; &lt;span class="nx"&gt;than&lt;/span&gt; &lt;span class="nx"&gt;b&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;1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then pass that function to the &lt;code&gt;sort&lt;/code&gt; method.&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="nx"&gt;myArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compareFunction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This flexibility will allow us to be creative with our sorting algorithms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Number Sort
&lt;/h2&gt;

&lt;p&gt;To sort a &lt;code&gt;Number&lt;/code&gt; &lt;code&gt;Array&lt;/code&gt; we could create a custom &lt;code&gt;compareNumbers&lt;/code&gt; function and pass that into &lt;code&gt;Array.sort&lt;/code&gt;.&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;const&lt;/span&gt; &lt;span class="nx"&gt;compareNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&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;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compareNumbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// [ 1, 3, 10, 15 ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Object Sort
&lt;/h2&gt;

&lt;p&gt;Let's say we had some data that looks like this:&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;const&lt;/span&gt; &lt;span class="nx"&gt;customers&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="na"&gt;id&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="na"&gt;orders&lt;/span&gt;&lt;span class="p"&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;a-1000&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;x-2000&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;c-8000&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;id&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="na"&gt;orders&lt;/span&gt;&lt;span class="p"&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;a-1010&lt;/span&gt;&lt;span class="dl"&gt;'&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="na"&gt;id&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="na"&gt;orders&lt;/span&gt;&lt;span class="p"&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;a-1040&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;c-8050&lt;/span&gt;&lt;span class="dl"&gt;'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our requirement is to sort by the number (&lt;code&gt;length&lt;/code&gt;) of &lt;code&gt;orders&lt;/code&gt;. So the order should be &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can do that with a custom &lt;code&gt;compareOrderLength&lt;/code&gt; function that will sort by &lt;code&gt;customer.orders.length&lt;/code&gt;.&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;const&lt;/span&gt; &lt;span class="nx"&gt;compareOrderLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;

&lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compareOrderLength&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="cm"&gt;/**
 * [
 *   { id: 2, orders: [ 'a-1010' ] }, 
 *   { id: 3, orders: [ 'a-1040', 'c-8050' ] }, 
 *   { id: 1, orders: [ 'a-1000', 'x-2000', 'c-8000' ] }
 * ]
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Complex Custom Sorting
&lt;/h2&gt;

&lt;p&gt;I recently had a use case where an API was returning data that looked like this.&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="c1"&gt;// API Response&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&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="s2"&gt;10&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="s2"&gt;2&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="s2"&gt;BLA&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="s2"&gt;BLA2&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="s2"&gt;3&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;The &lt;code&gt;Array&lt;/code&gt; contained all &lt;code&gt;String&lt;/code&gt; items, but the business wanted the items to display like "1, 2, 3, 10, BLA, BLA2".&lt;/p&gt;

&lt;p&gt;That meant, I had to detect when the &lt;code&gt;String&lt;/code&gt; was a &lt;code&gt;Number&lt;/code&gt; and Sort the "numbers" first and the text after.&lt;/p&gt;

&lt;p&gt;As complex as that sounds, the sort algorithm wasn't too bad.&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;const&lt;/span&gt; &lt;span class="nx"&gt;isNumeric&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customCompare&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&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;1&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isNumeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&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;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// [ '1', '2', '3', '10', 'BLA', 'BLA2' ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;So just remember the default &lt;code&gt;Array&lt;/code&gt; sort is a &lt;code&gt;String&lt;/code&gt; sort. To sort by anything else, you must create a compare function and pass that into sort.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check out my 📰 &lt;a href="https://joel.net/newsletter"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Subscribe to my 📺 YouTube, &lt;a href="https://www.youtube.com/c/JoelCodes?sub_confirmation=1"&gt;JoelCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Say hi to me on Twitter &lt;a href="https://twitter.com/joelnet"&gt;@joelnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

&lt;p&gt;&lt;span&gt;&lt;a href="https://unsplash.com/photos/-nz-GTuvyBw"&gt;Photo&lt;/a&gt; by &lt;a href="https://unsplash.com/@kellysikkema?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Kelly Sikkema&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/organize?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>sort</category>
    </item>
    <item>
      <title>This Week in JavaScript by Joel 2020-10-16</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Fri, 16 Oct 2020 17:46:24 +0000</pubDate>
      <link>https://dev.to/joelnet/this-week-in-javascript-by-joel-2020-10-16-id3</link>
      <guid>https://dev.to/joelnet/this-week-in-javascript-by-joel-2020-10-16-id3</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZtyHrzOjJZE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602810831640%2FjE5JcsvHm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602810831640%2FjE5JcsvHm.png" alt="TailwindCSS Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/swyx/why-tailwind-css-2o8f"&gt;Why Tailwind CSS&lt;/a&gt; is an interesting piece by &lt;a href="http://twitter.com/swyx" rel="noopener noreferrer"&gt;swyx&lt;/a&gt; making the case for Tailwind.&lt;/p&gt;

&lt;p&gt;What makes this article interesting is that he started as a non-believer even making such remarks against it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tailwind caused ugly unreadable classname soup and said zero-runtime CSS-in-JS could do more with a lower learning curve. -- &lt;a href="https://dev.to/swyx/why-tailwind-css-2o8f"&gt;swyx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After shipping a few projects with Tailwind, he's now done a full 180.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I was wrong on 2 counts: Tailwind is easier to learn than I thought, and CSSinJS's flexibility can be a negative. -- &lt;a href="https://dev.to/swyx/why-tailwind-css-2o8f"&gt;swyx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From naysayer to believer, it's an interesting read if you are on the fence with Tailwind.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/swyx/why-tailwind-css-2o8f"&gt;Why Tailwind CSS&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Non-Exported Functions in JavaScript
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/samanthaming/testing-non-exported-functions-in-javascript-29le"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--tTe9QDUV--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1e0c3ph55sg3plrc6pz9.jpg" alt="Testing Non-Exported Functions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/samanthaming/testing-non-exported-functions-in-javascript-29le"&gt;Testing Non-Exported Functions in JavaScript&lt;/a&gt; by &lt;a href="https://twitter.com/samantha_ming" rel="noopener noreferrer"&gt;samantha_ming&lt;/a&gt; solves the problem of testing non-exported functions.&lt;/p&gt;

&lt;p&gt;Typically these function either go untested or become exported just for testing.&lt;/p&gt;

&lt;p&gt;Now you can leave those functions un-exported and still run your test suite against them.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/samanthaming/testing-non-exported-functions-in-javascript-29le"&gt;Testing Non-Exported Functions in JavaScript&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RSLint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://rslint.org" rel="noopener noreferrer"&gt;RSLint&lt;/a&gt; is an extremely fast JavaScript linter written in Rust focusing on ease of use, customizability, and speed.&lt;/p&gt;

&lt;p&gt;RSLint is still a Work in Process and &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; is still the recommended linter for JavaScript, but this is still an interesting project that I'm tracking.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="http://rslint.org" rel="noopener noreferrer"&gt;RSLint&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Amplibox
&lt;/h2&gt;

&lt;p&gt;Amplibox is a Self Hosted File Storage App with AWS Amplify also by &lt;a href="http://twitter.com/swyx" rel="noopener noreferrer"&gt;swyx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--u_7orSSp--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_66%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F94xwh0o7wv8f2ovesmgs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--u_7orSSp--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_66%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F94xwh0o7wv8f2ovesmgs.gif" alt="AmpliBox"&gt;&lt;/a&gt;]((&lt;a href="https://dev.to/swyx/amplibox-a-self-hosted-file-storage-app-with-aws-amplify-1f6g"&gt;https://dev.to/swyx/amplibox-a-self-hosted-file-storage-app-with-aws-amplify-1f6g&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The demo looks incredible and it's pretty easy to setup.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/swyx/amplibox-a-self-hosted-file-storage-app-with-aws-amplify-1f6g"&gt;Amplibox&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remix
&lt;/h2&gt;

&lt;p&gt;Remix is at it again! This time with a coding tutorial from &lt;a href="https://twitter.com/ryanflorence" rel="noopener noreferrer"&gt;Ryan Florence&lt;/a&gt; on caching.&lt;/p&gt;

&lt;p&gt;If you were ever curious about what an &lt;code&gt;etag&lt;/code&gt; is, &lt;code&gt;cache-control&lt;/code&gt; headers and how the browser reacts to these. Then I I would highly recommend watching this:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/3XkU_DXcgl0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://remix.run" rel="noopener noreferrer"&gt;Remix&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Shout Out
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://devslike.us" rel="noopener noreferrer"&gt;Devs Like Us&lt;/a&gt; is a brand spanking new YouTube channel with only 80 subscribers so far!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/channel/UCOQaCm4q93rCUtTMI-YsaLg" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602810071372%2Fg8QV1e05i.png" alt="Screenshot of Devs Like Us YouTube Channel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They have got a bunch of Podcast style content and discuss topics like &lt;a href="https://www.youtube.com/watch?v=czdf84eD0OY" rel="noopener noreferrer"&gt;Work Life Balance&lt;/a&gt;, &lt;a href="https://www.youtube.com/watch?v=Bm77Hdzdd7k" rel="noopener noreferrer"&gt;Self-Taught vs Bootcamps vs College&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;Their content is fantastic and &lt;strong&gt;they deserve way more than 80 subs&lt;/strong&gt;. So head over to their YouTube and hit that &lt;a href="https://www.youtube.com/channel/UCOQaCm4q93rCUtTMI-YsaLg?sub_confirmation=1" rel="noopener noreferrer"&gt;SUBSCRIBE&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;📺 &lt;a href="https://www.youtube.com/channel/UCOQaCm4q93rCUtTMI-YsaLg" rel="noopener noreferrer"&gt;Devs Like Us YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;a href="https://devslike.us" rel="noopener noreferrer"&gt;https://devslike.us&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check out my 📰 &lt;a href="https://joel.net/newsletter" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Subscribe to my 📺 YouTube, &lt;a href="https://www.youtube.com/c/JoelCodes?sub_confirmation=1" rel="noopener noreferrer"&gt;JoelCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Say hi to me on Twitter &lt;a href="https://twitter.com/joelnet" rel="noopener noreferrer"&gt;@joelnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Simulated Function Overloading in JavaScript</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Thu, 15 Oct 2020 05:54:29 +0000</pubDate>
      <link>https://dev.to/joelnet/simulated-function-overloading-in-javascript-1l0o</link>
      <guid>https://dev.to/joelnet/simulated-function-overloading-in-javascript-1l0o</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/9w3zojKzuts"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;JavaScript may not support Function Overloading, but we can simulate the behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Function Overloading
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;function overloading or method overloading is the ability to create multiple functions of the same name with different implementations. -- &lt;a href="https://en.wikipedia.org/wiki/Function_overloading"&gt;Function overloading&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Other Languages
&lt;/h2&gt;

&lt;p&gt;In other languages, an overloaded function can be created by adding another function with the same name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// C#&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"int x"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"string y"&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;This can't be done in JavaScript because the 2nd function will overwrite the 1st function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulate the Behavior of Function Overloading
&lt;/h2&gt;

&lt;p&gt;What I would like to do is to have a named argument function, but also support traditional arguments. So I would like to be able to call my function both of the following ways and have it work.&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="c1"&gt;// Traditional&lt;/span&gt;
&lt;span class="nx"&gt;doThing&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="c1"&gt;// Named Arguments&lt;/span&gt;
&lt;span class="nx"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&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="na"&gt;y&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One method of simulation this behavior is to detect the function argument types.&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;function&lt;/span&gt; &lt;span class="nx"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// detect named argument object&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&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;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Now both styles work!&lt;/span&gt;
&lt;span class="nx"&gt;doThing&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;doThing&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&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="na"&gt;y&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the first argument &lt;code&gt;x&lt;/code&gt; is tested to see if it is of type &lt;code&gt;object&lt;/code&gt;. If it matches, the the function is called with the parameters pulled from &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended Behavior
&lt;/h2&gt;

&lt;p&gt;Because JavaScript doesn't natively support Function Overloading, it is usually recommended to create two separate functions and not attempt to overload functions.&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="c1"&gt;// Sometimes it is better to create two separate functions.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* code */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;readFileContents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* code */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But because I just want to support named arguments as well as maintain backward compatibility with traditional arguments. So in this instance, I find the Simulated Function Overloading above an acceptable solution too.&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;JavaScript doesn't natively support Function Overloading, but we can simulate this by checking the parameter types. Prefer creating two separate functions for the different behaviors. But in some cases, Simulated Function Overloading is also a good solution.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check out my 📰 &lt;a href="https://joel.net/newsletter"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Subscribe to my 📺 YouTube, &lt;a href="https://www.youtube.com/c/JoelCodes?sub_confirmation=1"&gt;JoelCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Say hi to me on Twitter &lt;a href="https://twitter.com/joelnet"&gt;@joelnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@othentikisra?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;israel palacio&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/electricity?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
    </item>
    <item>
      <title>How I Setup My Own Personal CDN using Cloudflare and S3</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Tue, 13 Oct 2020 00:49:01 +0000</pubDate>
      <link>https://dev.to/joelnet/how-i-setup-my-own-personal-cdn-3h06</link>
      <guid>https://dev.to/joelnet/how-i-setup-my-own-personal-cdn-3h06</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KnlB52S9P3Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a CDN?
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://www.cloudflare.com" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt; a CDN is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A content delivery network (CDN) refers to a geographically distributed group of servers which work together to provide fast delivery of Internet content.&lt;/p&gt;

&lt;p&gt;A CDN allows for the quick transfer of assets needed for loading Internet content including HTML pages, javascript files, stylesheets, images, and videos. The popularity of CDN services continues to grow, and today the majority of web traffic is served through CDNs, including traffic from major sites like Facebook, Netflix, and Amazon.&lt;/p&gt;

&lt;p&gt;A properly configured CDN may also help protect websites against some common malicious attacks, such as &lt;a href="https://www.cloudflare.com/learning/ddos/what-is-a-ddos-attack" rel="noopener noreferrer"&gt;Distributed Denial of Service (DDOS) attacks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;-- &lt;a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn" rel="noopener noreferrer"&gt;What is a CDN?&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; A CDN is a network of computers around the world that deliver content efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can a CDN Provide?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt; to reduce the load on my webserver&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geographic Distribution&lt;/strong&gt; for speedy delivery regardless of where you are&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DDoS Protection&lt;/strong&gt; from sudden spikes in traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://support.cloudflare.com/hc/en-us/articles/200168396-What-will-Cloudflare-compress-" rel="noopener noreferrer"&gt;Compression&lt;/a&gt;&lt;/strong&gt; of files for faster delivery for user on slow internet&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Did I Want a CDN?
&lt;/h2&gt;

&lt;p&gt;I often find myself needing to host public static files. I want to do so in a way that is fast, efficient, reliable, and scalable.&lt;/p&gt;

&lt;p&gt;Recently &lt;a href="https://joel.net/how-one-guy-ruined-hacktoberfest2020-drama" rel="noopener noreferrer"&gt;an article of mine&lt;/a&gt; hit #1 on the HN main page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602300938742%2Ffd_sdlg84.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602300938742%2Ffd_sdlg84.jpeg" alt="Screenshot_20201001-222913__01.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also found out it was trending on Reddit and who knows where else. So long story short. My domain had a load of traffic in the blink of an eye.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602300888496%2FY20cgUcEP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602300888496%2FY20cgUcEP.png" alt="joelnet-article-screenshot.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was lucky enough to have recently moved &lt;a href="https://joel.net" rel="noopener noreferrer"&gt;joel.net&lt;/a&gt; to &lt;a href="https://hashnode.com/" rel="noopener noreferrer"&gt;Hashnode&lt;/a&gt; just weeks earlier. My previous web host would not have been able to handle that amount of traffic. Even during this blast of traffic &lt;a href="https://joel.net" rel="noopener noreferrer"&gt;joel.net&lt;/a&gt; was online the entire time.&lt;/p&gt;

&lt;p&gt;Since I also host other files, I better be prepared. So I plan on going full CDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloudflare
&lt;/h2&gt;

&lt;p&gt;This is where &lt;a href="https://www.cloudflare.com" rel="noopener noreferrer"&gt;Cloudflare&lt;/a&gt; comes in. I use them to host the DNS for &lt;a href="https://joel.net" rel="noopener noreferrer"&gt;joel.net&lt;/a&gt;. Cloudflare will provide these CDN features &lt;a href="https://support.cloudflare.com/hc/en-us/articles/200172516-Understanding-Cloudflare-s-CDN" rel="noopener noreferrer"&gt;by default&lt;/a&gt; through their DNS offering, which is also FREE. 🔥&lt;/p&gt;

&lt;p&gt;Now all I need is a place to host static files.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Simple Cloud Storage (S3)
&lt;/h2&gt;

&lt;p&gt;You could use any static web host, but I'm choosing S3 for this because it's what I am already familiar with.&lt;/p&gt;

&lt;p&gt;It just needs to be online and also allow a custom domain name.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up My S3 Bucket
&lt;/h2&gt;

&lt;p&gt;The S3 bucket name must match the domain name. In this case, I am using &lt;code&gt;cdn.joel.net&lt;/code&gt; for my bucket name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602360775740%2FZHTB89nWc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602360775740%2FZHTB89nWc.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Next a bunch of times until you see this screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602362636851%2Fxd1FlAz6W.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602362636851%2Fxd1FlAz6W.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Be sure to uncheck &lt;strong&gt;Block &lt;em&gt;all&lt;/em&gt; public access&lt;/strong&gt;. Then check the acknowledge popup above.&lt;/p&gt;

&lt;p&gt;Keep clicking Next until you can click &lt;strong&gt;Create Bucket&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now I need to configure this bucket for Public access. So I head over to Permissions, then Bucket Policy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361011238%2FKbHGtw-3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361011238%2FKbHGtw-3f.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I insert my bucket name, &lt;code&gt;cdn.joel.net&lt;/code&gt;, into &lt;code&gt;Resource&lt;/code&gt; and then paste this into the &lt;strong&gt;Bucket policy editor&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&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;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PublicReadGetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::cdn.joel.net/*"&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;Next, I setup &lt;strong&gt;Static website hosting&lt;/strong&gt; under &lt;strong&gt;Properties&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361285085%2F5XFEA2lxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361285085%2F5XFEA2lxn.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I check &lt;strong&gt;Use this bucket to host a website&lt;/strong&gt; and set up my &lt;code&gt;index.html&lt;/code&gt; and also my &lt;strong&gt;404/404.html&lt;/strong&gt;. I will create a directory for my 404 so that I can host assets related to the 404 in there as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361412745%2F0hy_JNvCL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361412745%2F0hy_JNvCL.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I can upload a file and make sure it works by accessing the &lt;strong&gt;Endpoint&lt;/strong&gt; from this page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Cloudflare
&lt;/h2&gt;

&lt;p&gt;The last step is to set up my Cloudflare DNS to point to my freshly created S3 bucket.&lt;/p&gt;

&lt;p&gt;I do this by adding a new &lt;strong&gt;CNAME&lt;/strong&gt; record with the name &lt;code&gt;cdn&lt;/code&gt; and the target set as the domain for the S3 bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361799964%2FMWGTqoBDm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602361799964%2FMWGTqoBDm.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I should be able to access my bucket using my custom domain name. So let's test my 404 page &lt;a href="http://cdn.joel.net" rel="noopener noreferrer"&gt;http://cdn.joel.net&lt;/a&gt;. Looks like it's working!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602362009026%2FUgpk2P7jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602362009026%2FUgpk2P7jh.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now just to check one last thing, I open the Developer Console, click the &lt;strong&gt;Network&lt;/strong&gt; tab, click the request &lt;code&gt;cdn.joel.net&lt;/code&gt; and go to &lt;strong&gt;Headers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here I can see &lt;code&gt;content-encoding: br&lt;/code&gt;. That means the HTML was compressed using the Brotli compression algorithm all automatically for me by Cloudflare.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602362074330%2FSXlRVf6aL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1602362074330%2FSXlRVf6aL.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  End
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Check out my 📰 &lt;a href="https://joel.net/newsletter" rel="noopener noreferrer"&gt;Newsletter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Subscribe to my 📺 YouTube, &lt;a href="https://www.youtube.com/c/JoelCodes?sub_confirmation=1" rel="noopener noreferrer"&gt;JoelCodes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Say hi to me on Twitter &lt;a href="https://twitter.com/joelnet" rel="noopener noreferrer"&gt;@joelnet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

</description>
      <category>aws</category>
      <category>hosting</category>
      <category>cdn</category>
      <category>webhosting</category>
    </item>
    <item>
      <title>This Week in JavaScript by Joel 2020-10-08</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Sat, 10 Oct 2020 21:28:34 +0000</pubDate>
      <link>https://dev.to/joelnet/this-week-in-javascript-by-joel-2020-10-08-452b</link>
      <guid>https://dev.to/joelnet/this-week-in-javascript-by-joel-2020-10-08-452b</guid>
      <description>&lt;p&gt;&lt;strong&gt;This Week in JavaScript&lt;/strong&gt; I talk about the things I found interesting.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mhzXAA1gW-U"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Hacktoberfest 2020
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FDVDeL8S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602094939558/wochppybQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FDVDeL8S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602094939558/wochppybQ.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hacktoberfest has started. Well, it actually started a week ago. Just in case you have been under a rock and don't know what Hacktoberfest is...&lt;/p&gt;

&lt;p&gt;Hacktoberfest is an annual event held every October held by &lt;a href="https://www.digitalocean.com"&gt;Digital Ocean&lt;/a&gt; where developers are rewarded for making Open-Source contributions. While Hacktoberfest 2020 has been &lt;a href="https://joel.net/how-one-guy-ruined-hacktoberfest2020-drama"&gt;Full of Drama&lt;/a&gt;, I would still recommend giving it a go.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://hacktoberfest.digitalocean.com"&gt;https://hacktoberfest.digitalocean.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How To Contribute To Open-Source Projects As A Beginner
&lt;/h2&gt;

&lt;p&gt;Do you want to contribute to Open-Source but aren't sure where to start? Getting that first step can be intimidating if you have never made a contribution before.&lt;/p&gt;

&lt;p&gt;@&lt;a href="https://dev.to@Catalinpit"&gt;Catalin Pit&lt;/a&gt; has created a step-by-step guide for creating that first Open-Source contribution. Follow this guide and become an Open-Source contributor!&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/dailydotdev/how-to-contribute-to-open-source-projects-as-a-beginner-2h43"&gt;How To Contribute To Open-Source Projects As A Beginner&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remix
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RiBNXInR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602095772345/2Maea3M9T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RiBNXInR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602095772345/2Maea3M9T.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are all looking forward to the launch of Remix, a new React Framework by the creators of &lt;a href="https://reactrouter.com"&gt;react-router&lt;/a&gt;, &lt;a href="https://twitter.com/ryanflorence"&gt;Ryan Florence&lt;/a&gt; and &lt;a href="https://twitter.com/mjackson"&gt;Michael Jackson&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It looks so simplify React Apps with features like File Routing and improved async with React Suspense.&lt;/p&gt;

&lt;p&gt;Follow the &lt;a href="https://blog.remix.run"&gt;blog&lt;/a&gt; to keep up to date with the development of Remix.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://remix.run"&gt;https://remix.run&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mocky
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--njwb92ZU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602096776509/1hdTL8dyu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--njwb92ZU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602096776509/1hdTL8dyu.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mocky makes the claim of being "The world easiest &amp;amp; fastest tool belts to mock your APIs" and they might just be right.&lt;/p&gt;

&lt;p&gt;When creating an application, sometimes the APIs we need aren't ready but we need something now. Mocky can be used to create an instant mock API. No signup. Free. Unlimited.&lt;/p&gt;

&lt;p&gt;No need to create mocks in your app or spin up a local mock API. Try Mocky!&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://designer.mocky.io"&gt;https://designer.mocky.io&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I can't write a for loop and it does not matter
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://twitter.com/sebastienlorber"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3n0hUHW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602101196537/6A6NQsXfs.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/sebastienlorber"&gt;Sebastien Lorber&lt;/a&gt; says &lt;em&gt;he can't write a for loop and it doesn't matter&lt;/em&gt;. He goes on to say...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've been using JavaScript daily for 7 years, and I'm not able to remember the syntax of a JavaScript for loop.&lt;/p&gt;

&lt;p&gt;Despite this fact, I'm a rather successful freelance developer. - &lt;a href="https://twitter.com/sebastienlorber"&gt;Sebastien Lorber&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I often find the main argument against functional programming being "it's too difficult compared to non-functional code". I believe this argument to be flat out wrong, instead it is &lt;em&gt;unfamiliar&lt;/em&gt; code that you find difficult.&lt;/p&gt;

&lt;p&gt;If you happened to learn functional programming first, you would find it &lt;em&gt;equally difficult&lt;/em&gt; to learn non-functional code. That is exactly what &lt;a href="https://twitter.com/sebastienlorber"&gt;Sebastien Lorber&lt;/a&gt; articulates in his article.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/sebastienlorber/i-can-t-write-a-javascript-for-loop-and-it-does-not-matter-11jb"&gt;I can't write a for loop and it does not matter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Shout Out
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gK3cex3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602105272637/rjUhMJqa_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gK3cex3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1602105272637/rjUhMJqa_.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shout out to Software Engineer, Content Creator, Teacher, Certified Nerdy Girl, &lt;a href="https://www.sidneybuckner.com"&gt;Sidney Buckner&lt;/a&gt; and the weekly tech content on her blog and YouTube.&lt;/p&gt;

&lt;p&gt;Recommended subscribe 👍&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔗 YouTube: &lt;a href="https://www.youtube.com/c/SidneyBuckner"&gt;SidneyBuckner&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 Twitter: &lt;a href="https://twitter.com/sidneybuckner18"&gt;@sidneybuckner18&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 Web: &lt;a href="https://www.sidneybuckner.com"&gt;https://www.sidneybuckner.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Connect with Me
&lt;/h2&gt;

&lt;p&gt;📧 Subscribe to my mailing list at the top of the page&lt;/p&gt;

&lt;p&gt;📺 Check out my YouTube, &lt;a href="https://www.youtube.com/JoelCodes"&gt;Joel Codes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💭 Chat with me me on Twitter &lt;a href="https://twitter.com/joelnet"&gt;@joelnet&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>#SadJavaScript Comics Are Now Open Source!</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Fri, 09 Oct 2020 18:03:10 +0000</pubDate>
      <link>https://dev.to/joelnet/sadjavascript-comics-are-now-open-source-4ll0</link>
      <guid>https://dev.to/joelnet/sadjavascript-comics-are-now-open-source-4ll0</guid>
      <description>&lt;p&gt;Recently I had tweeted out a handful of &lt;a href="https://twitter.com/search?q=from%3Ajoelnet%20%23sadjavascript&amp;amp;src=typed_query&amp;amp;f=live" rel="noopener noreferrer"&gt;#SadJavaScript&lt;/a&gt; comics.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1304064587684179968-975" src="https://platform.twitter.com/embed/Tweet.html?id=1304064587684179968"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1304064587684179968-975');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1304064587684179968&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The flow of the &lt;a href="https://twitter.com/search?q=from%3Ajoelnet%20%23sadjavascript&amp;amp;src=typed_query&amp;amp;f=live" rel="noopener noreferrer"&gt;#SadJavaScript&lt;/a&gt; comic has two coffee cups are laughing at JavaScript's quirks. The next panel reveals a sad JavaScript, trying to explain how they are misunderstood.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1304426974824235008-174" src="https://platform.twitter.com/embed/Tweet.html?id=1304426974824235008"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1304426974824235008-174');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1304426974824235008&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I thought this would be a fun and cute way to talk about some of the parts of JavaScript that people often lulz at.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1305514138064494597-21" src="https://platform.twitter.com/embed/Tweet.html?id=1305514138064494597"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1305514138064494597-21');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1305514138064494597&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I was also trying to point out some things like how &lt;code&gt;0.1 + 0.2 == 0.30000000000000004&lt;/code&gt; is not a bug but the correct behavior.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1305876525154066433-302" src="https://platform.twitter.com/embed/Tweet.html?id=1305876525154066433"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1305876525154066433-302');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1305876525154066433&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I had a lot of fun making these and I hope you enjoyed reading them.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1306238914554859521-690" src="https://platform.twitter.com/embed/Tweet.html?id=1306238914554859521"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1306238914554859521-690');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1306238914554859521&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Today, I am leaving a blank comic up for you to download, modify and make your own!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1306963690407694336-491" src="https://platform.twitter.com/embed/Tweet.html?id=1306963690407694336"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1306963690407694336-491');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1306963690407694336&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  The #SadJavaScript Comic Template
&lt;/h2&gt;

&lt;p&gt;So go at it and make your own! Remember to tag me so I can see what you've made. Cheers 🍻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cdn.joel.net/joel.net/images/sad-javascript-template.png" rel="noopener noreferrer"&gt;https://cdn.joel.net/joel.net/images/sad-javascript-template.png&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.joel.net%2Fjoel.net%2Fimages%2Fsad-javascript-template.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.joel.net%2Fjoel.net%2Fimages%2Fsad-javascript-template.png" alt="#SadJavaScript template"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How One Guy Ruined #Hacktoberfest2020 #Drama</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Tue, 06 Oct 2020 16:19:22 +0000</pubDate>
      <link>https://dev.to/joelnet/how-one-guy-ruined-hacktoberfest2020-drama-1200</link>
      <guid>https://dev.to/joelnet/how-one-guy-ruined-hacktoberfest2020-drama-1200</guid>
      <description>&lt;h2&gt;
  
  
  Hacktoberfest
&lt;/h2&gt;

&lt;p&gt;If you aren't familar, Hacktoberfest is an annual event that occurs every October. It is held by &lt;a href="https://www.digitalocean.com" rel="noopener noreferrer"&gt;Digital Ocean&lt;/a&gt; and encourages developers to submit Pull Requests to Open Source repositories and as a reward you get a T-Shirt.&lt;/p&gt;

&lt;p&gt;There's almost no limits, so if your request is merged into &lt;em&gt;any&lt;/em&gt; Open Source repository, you qualify. Amazing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fallout
&lt;/h2&gt;

&lt;p&gt;Twitter starts going nuts. Not soon after October begins, we see many popular open source maintainers taking to Twitter complaining about low quality PRs bordering on SPAM.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311751160517341192-753" src="https://platform.twitter.com/embed/Tweet.html?id=1311751160517341192"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311751160517341192-753');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311751160517341192&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311646233128181760-389" src="https://platform.twitter.com/embed/Tweet.html?id=1311646233128181760"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311646233128181760-389');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311646233128181760&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Some more honest than others&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311794527750049792-381" src="https://platform.twitter.com/embed/Tweet.html?id=1311794527750049792"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311794527750049792-381');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311794527750049792&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311618846986469376-805" src="https://platform.twitter.com/embed/Tweet.html?id=1311618846986469376"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311618846986469376-805');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311618846986469376&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Even a Covid19Tracking Repo is under attack&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311731378392768512-156" src="https://platform.twitter.com/embed/Tweet.html?id=1311731378392768512"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311731378392768512-156');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311731378392768512&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;A whole new Twitter account &lt;a href="https://twitter.com/shitoberfest" rel="noopener noreferrer"&gt;@shitoberfest&lt;/a&gt; was created to track this&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cause
&lt;/h2&gt;

&lt;p&gt;This flood of low quality PR spam appears to come from a YouTuber with an audience of 672K where he demonstrates how easy it is to make a Pull Request to a repo.&lt;/p&gt;

&lt;p&gt;Where he went wrong was demonstrating a low quality PR, thus setting the bar low for his viewers who went on to copy exactly what he did.&lt;/p&gt;

&lt;p&gt;To avoid linking to his YouTube and giving him views, I'll link to this Twitter of the action moment:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311773094856454144-281" src="https://platform.twitter.com/embed/Tweet.html?id=1311773094856454144"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311773094856454144-281');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311773094856454144&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  The Response
&lt;/h2&gt;

&lt;p&gt;The response from CodeWithHarry was weak at best. It offered no apology and instead links to many instances where he avoids responsibility by linking to areas in the video where he encourages quality PRs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A humble request to everyone to not open spam pull requests on GitHub repositories!&lt;br&gt;
Some people think that I am hurting the open source community. &lt;br&gt;
The purpose of this video was to encourage participation in the events encouraging open source participation and to teach people what a pull request is and how a pull request works!&lt;br&gt;
People understanding Hindi can watch the video but for people who are non Hindi speakers and for some reason think that I am requesting people to open spam pull requests, all I have told throughout the video is to make legit contributions to the open source.&lt;br&gt;
I have said nowhere in the video to open spam pull requests.&lt;br&gt;
I have made it clear in the video several times (for instance in the video at 00:55 - that you have to earn it by making contributions that count, 07:51 - Make legit contributions, 10:58, 11:10, etc). &lt;br&gt;
Also at 05:33 - I avoided an actively maintained project and instead opened pull request on a project which was not being maintained just to demonstrate how contributing to an open source repository actually works. &lt;br&gt;
I have not encouraged spam pull requests in bulk!&lt;br&gt;
I also agree with the fact that events like hacktoberfest can be made better by making only the legit merged pull requests count. But that has been a topic of debate since years when hacktoberfest was launched. &lt;br&gt;
I would also like to mention that many people opened their GitHub account, learned to make pull requests and made some amazing legit contributions to the open source too! I am proud of them and would like the entire developer community to act in a responsible manner.&lt;/p&gt;

&lt;p&gt;Thanks,&lt;br&gt;
Harry 🙏&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But this pinned comment is the &lt;strong&gt;least amount of effort&lt;/strong&gt; he could have done to slow this shit storm.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do You Know CodeWithHarry Was Really The Cause?
&lt;/h2&gt;

&lt;p&gt;Here's a screenshot of some pull requests from the repo &lt;a href="https://github.com/xraymemory/micromtn/pulls" rel="noopener noreferrer"&gt;micromtn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601597438809%2Fm5hnyO6ES.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601597438809%2Fm5hnyO6ES.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every request looks something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601597539107%2F1_YA5Yrm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601597539107%2F1_YA5Yrm9.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This looks remarkably similar to the PR that was demonstrated in the video.&lt;/p&gt;

&lt;p&gt;A search for "improve docs" shows 319,251 issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601598060512%2FwghezEhwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601598060512%2FwghezEhwj.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A search for "Amazing Project" is now showing 21,177 issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601597896975%2FSsiwsgrL3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601597896975%2FSsiwsgrL3.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CodeWithHarry
&lt;/h2&gt;

&lt;p&gt;CodeWithHarry is not a bad guy, I don't want to cancel or shame him personally. After all, we're all human. With a following that big, he's definitely helped a lot of people. But he made a mistake here and he's going to have to be responsible for the outcome, which so far isn't looking great.&lt;/p&gt;

&lt;p&gt;At the moment of this writing, his &lt;a href="https://github.com/CodeWithHarry" rel="noopener noreferrer"&gt;GitHub is 404&lt;/a&gt;. Was it taken down? Made private? Renamed?&lt;/p&gt;

&lt;p&gt;It's only day 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Digital Ocean
&lt;/h2&gt;

&lt;p&gt;Even Digital Ocean &lt;a href="https://hacktoberfest.digitalocean.com/hacktoberfest-update" rel="noopener noreferrer"&gt;has chimed&lt;/a&gt; in on this fiasco.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We’ve traced the majority of this year’s spammy contributions back to a participant with a large online audience who openly encouraged their community to take part in spammy activities, including ideas on how to game the system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Wait and See
&lt;/h2&gt;

&lt;p&gt;So Lots of drama today. I guess all we can do is wait and see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello HN 👋
&lt;/h2&gt;

&lt;p&gt;This article hit #1 on HN. Go read the comments there for more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://news.ycombinator.com/item?id=24658052" rel="noopener noreferrer"&gt;https://news.ycombinator.com/item?id=24658052&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me
&lt;/h2&gt;

&lt;p&gt;Subscribe to my newsletter on &lt;a href="https://joel.net" rel="noopener noreferrer"&gt;joel.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find me on Twitter &lt;a href="https://twitter.com/joelnet" rel="noopener noreferrer"&gt;@joelnet&lt;/a&gt; or YouTube &lt;a href="https://www.youtube.com/JoelCodes" rel="noopener noreferrer"&gt;JoelCodes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;p&gt;Response from GitHub:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1311772722234560517-543" src="https://platform.twitter.com/embed/Tweet.html?id=1311772722234560517"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1311772722234560517-543');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1311772722234560517&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Response from Digital Ocean:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1312221208667185153-403" src="https://platform.twitter.com/embed/Tweet.html?id=1312221208667185153"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1312221208667185153-403');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1312221208667185153&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
    </item>
    <item>
      <title>This Week in JavaScript by Joel 9/30/2020</title>
      <dc:creator>JavaScript Joel</dc:creator>
      <pubDate>Thu, 01 Oct 2020 16:32:17 +0000</pubDate>
      <link>https://dev.to/joelnet/this-week-in-javascript-by-joel-9-30-2020-9p5</link>
      <guid>https://dev.to/joelnet/this-week-in-javascript-by-joel-9-30-2020-9p5</guid>
      <description>&lt;p&gt;During this week in JavaScript, I found some Epic React training, a React framework for CloudFlare Workers, a replacement for Redux, my YouTube hit 1,000, and a special shout out to a tech community member.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/utUhte8-gX0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Epic React Training
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601424712659%2F7xyu9F4xZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601424712659%2F7xyu9F4xZ.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kentcdodds" rel="noopener noreferrer"&gt;Kent C. Dodds&lt;/a&gt; and team have released &lt;a href="http://epicreact.dev/" rel="noopener noreferrer"&gt;Epic React&lt;/a&gt; training.&lt;/p&gt;

&lt;p&gt;Epic React includes 19 hours of video training, workshop excercises, 10 hours of video conversations with React experts.&lt;/p&gt;

&lt;p&gt;Prices vary from $83 to $419. It's pricey, but considering the quality of &lt;a href="https://twitter.com/kentcdodds" rel="noopener noreferrer"&gt;Kent C. Dodds&lt;/a&gt;'s other content, it'll be worth every penny.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flareact
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601424905696%2FZ7uMltBbL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601424905696%2FZ7uMltBbL.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://flareact.com" rel="noopener noreferrer"&gt;Flareact&lt;/a&gt; is an edge-rendered React framework built for &lt;a href="https://workers.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare Workers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have been spending some free time exploring Cloudflare Workers and have even build a POC React framework for it. I am now considering throwing that all in the bin and replacing it with Flareact. I am very excited for this project!&lt;/p&gt;

&lt;h2&gt;
  
  
  Zustand
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601425244175%2F-GpWAltj6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601425244175%2F-GpWAltj6.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zustand.surge.sh/" rel="noopener noreferrer"&gt;Zustand&lt;/a&gt; is state management library for React and claim to have a &lt;em&gt;comfy api based on hooks&lt;/em&gt; and I would agree. The code looks incredibly simple and I am looking forward to replacing a bunch of my React boiler plate with this.&lt;/p&gt;

&lt;h2&gt;
  
  
  1,000 Subscribers 🎉
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601432630133%2FPWvHkqwJS.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1601432630133%2FPWvHkqwJS.jpeg" alt="Screenshot_20200928-181133.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My YouTube Channel, &lt;a href="https://www.youtube.com/JoelCodes" rel="noopener noreferrer"&gt;Joel Codes&lt;/a&gt;,  has reached 1,000 subscribers!&lt;/p&gt;

&lt;p&gt;Such a big milestone and I am so thankful for everyone who has subscribed. It means so much to me. So thanks again!&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Shout Out
&lt;/h2&gt;

&lt;p&gt;Congrats to &lt;a href="https://twitter.com/SimonHoiberg" rel="noopener noreferrer"&gt;@SimonHoiberg&lt;/a&gt; for his Twitter API Client making it to number 4 on the GitHub trending list for TypeScript.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1310895641648824321-104" src="https://platform.twitter.com/embed/Tweet.html?id=1310895641648824321"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1310895641648824321-104');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1310895641648824321&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow Me
&lt;/h2&gt;

&lt;p&gt;Subscribe to my newsletter on &lt;a href="https://joel.net" rel="noopener noreferrer"&gt;joel.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find me on Twitter &lt;a href="https://twitter.com/joelnet" rel="noopener noreferrer"&gt;@joelnet&lt;/a&gt; or YouTube &lt;a href="https://www.youtube.com/JoelCodes" rel="noopener noreferrer"&gt;JoelCodes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers 🍻&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
