<?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: Sunny Golovine</title>
    <description>The latest articles on DEV Community by Sunny Golovine (@sgolovine).</description>
    <link>https://dev.to/sgolovine</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%2F99252%2F3f1839eb-34fd-4b4d-a96b-23807e39522f.png</url>
      <title>DEV Community: Sunny Golovine</title>
      <link>https://dev.to/sgolovine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sgolovine"/>
    <language>en</language>
    <item>
      <title>The best way to use SVG icons in React.</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Fri, 25 Jun 2021 16:03:51 +0000</pubDate>
      <link>https://dev.to/sgolovine/the-best-way-to-use-svg-icons-in-react-3ckm</link>
      <guid>https://dev.to/sgolovine/the-best-way-to-use-svg-icons-in-react-3ckm</guid>
      <description>&lt;p&gt;When I first started working with React, I used libraries like &lt;a href="https://react-icons.github.io/react-icons/" rel="noopener noreferrer"&gt;React Icons&lt;/a&gt; or &lt;a href="https://www.npmjs.com/package/bootstrap-icons" rel="noopener noreferrer"&gt;Bootstrap Icons&lt;/a&gt; to manage my icons. &lt;/p&gt;

&lt;p&gt;But problems quickly emerged, the first problem is not all of these packages support &lt;em&gt;tree shaking&lt;/em&gt;. Without tree shaking, when you build your site, all the icons from the library will be included with your build rather than just the ones you use.&lt;/p&gt;

&lt;p&gt;The second problem is these libraries can be hard to setup and manage. So what's a better way? Let me show you. If you're new to React you might not know this but in fact you can use &lt;em&gt;svg icons directly as React components&lt;/em&gt;. So how would we do that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Component
&lt;/h2&gt;

&lt;p&gt;Take this SVG icon (via &lt;a href="https://heroicons.com/" rel="noopener noreferrer"&gt;Hero Icons&lt;/a&gt;)&lt;/p&gt;

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

&lt;p&gt;This SVG icon has the following code:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="nx"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h-6 w-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 24 24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currentColor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M12 14l9-5-9-5-9 5 9 5z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linecap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linejoin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&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="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M12 14l9-5-9-5-9 5 9 5zm0 0l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14zm-4 6v-7.5l4-2.222&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing you will want to do is remove the &lt;code&gt;xmlns&lt;/code&gt; attribute, as it's not used by React when rendering the SVG. Additionally you need to replace the &lt;code&gt;class&lt;/code&gt; attribute with &lt;code&gt;className&lt;/code&gt; to make it compliant with React. Your SVG will now look 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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;svg&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h-6 w-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;viewBox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 0 24 24&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currentColor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M12 14l9-5-9-5-9 5 9 5z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linecap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;linejoin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;round&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&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="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;M12 14l9-5-9-5-9 5 9 5zm0 0l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14zm-4 6v-7.5l4-2.222&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/svg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you're ready to create a React component. I suggest creating a functional component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AcademicIcon&lt;/span&gt; &lt;span class="o"&gt;=&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-6 w-6"&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"currentColor"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 14l9-5-9-5-9 5 9 5z"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
        &lt;span class="na"&gt;stroke-linecap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
        &lt;span class="na"&gt;stroke-linejoin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
        &lt;span class="na"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;
        &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 14l9-5-9-5-9 5 9 5zm0 0l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14zm-4 6v-7.5l4-2.222"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;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;At this point you're ready to use the component! You can use it as is in other react components like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AcademicIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./AcademicIcon.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AcademicIcon&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;
  
  
  Adding Props
&lt;/h2&gt;

&lt;p&gt;One benefit of using SVG's as React components is you can add props to it just like you would to any other component. Lets add some props to our &lt;code&gt;AcademicIcon&lt;/code&gt; component to make it more flexible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AcademicIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h-6 w-6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stroke&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currentColor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stokeWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;viewBox&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0 0 24 24"&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;stroke&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 14l9-5-9-5-9 5 9 5z"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 14l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14z"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
        &lt;span class="na"&gt;stroke-linecap&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
        &lt;span class="na"&gt;stroke-linejoin&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;
        &lt;span class="na"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;strokeWidth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"M12 14l9-5-9-5-9 5 9 5zm0 0l6.16-3.422a12.083 12.083 0 01.665 6.479A11.952 11.952 0 0012 20.055a11.952 11.952 0 00-6.824-2.998 12.078 12.078 0 01.665-6.479L12 14zm-4 6v-7.5l4-2.222"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Now in this final version we moved &lt;code&gt;className&lt;/code&gt;, &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;stroke&lt;/code&gt; and &lt;code&gt;strokeWidth&lt;/code&gt; to a prop and gave it a default of the original value. Now you can call your icon with props:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AcademicIcon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./AcademicIcon.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&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;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AcademicIcon&lt;/span&gt;
         &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"h-12 w-12"&lt;/span&gt;
         &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt;
         &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Because all the props have defaults, you can declare the icon with all the props, some of them or none of them! With this method you are also only loading the icons you are using, no wasteful extra code at build time!&lt;/p&gt;




&lt;p&gt;If you enjoyed this post check out my other posts on &lt;a href="https://sunny.gg/post" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;. You should also check out my latest project: &lt;a href="https://awesomedevtools.com?utm_source=blog_post" rel="noopener noreferrer"&gt;Awesome Devtools&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>10 UI Frameworks for your Next React Project</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Wed, 16 Jun 2021 14:38:41 +0000</pubDate>
      <link>https://dev.to/sgolovine/10-ui-frameworks-for-your-next-react-project-o6k</link>
      <guid>https://dev.to/sgolovine/10-ui-frameworks-for-your-next-react-project-o6k</guid>
      <description>&lt;p&gt;I'm a developer, not a designer. This means that I use CSS frameworks in most of my side project to make sure they don't look like poop. Here are 10 CSS frameworks that you should consider for your next React project. Some of these are built specifically for react, others are general purpose frameworks that work well with React.&lt;/p&gt;




&lt;h2&gt;
  
  
  React UI Frameworks
&lt;/h2&gt;

&lt;p&gt;These are UI frameworks that are designed specifically for React. These are great if you are planning a big project or a full featured web app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Material UI
&lt;/h3&gt;

&lt;p&gt;Material UI is a full featured UI framework for React. It has support for every type of UI element from Material design and comes with it's own CSS-in-JS solution for writing CSS. Material UI currently has 68.9k stars on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mui-org/material-ui" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://material-ui.com/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Semantic UI React
&lt;/h3&gt;

&lt;p&gt;One of the oldest and most feature complete UI frameworks out there. If you need stability and best in class documentation, give Semantic UI a try. Semantic UI React has 12.3k stars on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Semantic-Org/Semantic-UI-React" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://react.semantic-ui.com/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  React Bootstrap
&lt;/h3&gt;

&lt;p&gt;React bootstrap is a rebuilt version of Bootstrap that is made for React. While it has fantastic component support in React, it's not up to version 5 yet. React Bootstrap has 19.5k stars on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/react-bootstrap/react-bootstrap" rel="noopener noreferrer"&gt;Github&lt;/a&gt; |  &lt;a href="https://react-bootstrap.github.io/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fluent UI React
&lt;/h3&gt;

&lt;p&gt;In recent years Microsoft has quietly sneaked into the React scene and converted Office, and most of their other web apps to React. With such heavy React development, Microsoft has also released a pretty comprehensive UI framework that includes React bindings. Fluent UI has 11.5k stars on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/fluentui#readme" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href=""&gt;Website&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  CSS Frameworks
&lt;/h2&gt;

&lt;p&gt;These are CSS frameworks not built specifically for React, but work extremely well inside a React project. These are great if you are building a landing page or a blog and don't need a comprehensive UI framework like you would in a web app, but still need something to lean on for building the pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bulma CSS
&lt;/h3&gt;

&lt;p&gt;Bulma is a highly customizable CSS frameworks that gives you components for building responsive web pages. BulmaCSS has 43.7k stars on Github as of this writing so it's also safe to say it's a very popular framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jgthms/bulma" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://bulma.io" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind CSS
&lt;/h3&gt;

&lt;p&gt;TailwindCSS is a utility first CSS framework that is packed with classes to build just about anything. While TailwindCSS is not a React specific UI framework, it integrates very nicely with React.  TailwindCSS has 42.9k stars on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tailwindlabs/tailwindcss" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bootstrap
&lt;/h3&gt;

&lt;p&gt;The official version of bootstrap. Not much else to be said here, bootstrap is a legendary CSS framework and just about every front-end dev will touch it as some point. Bootstrap has an impressive 151k stars on Github.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/twbs/bootstrap" rel="noopener noreferrer"&gt;Github&lt;/a&gt; |  &lt;a href="https://getbootstrap.com" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Minimal CSS Frameworks
&lt;/h2&gt;

&lt;p&gt;While these are still CSS frameworks, I decided to put them into a different category because they serve a different purpose. If you want to put a webpage up with speed or just want to build and MVP without investing too much time, these minimal UI frameworks will help you get there.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVP.css
&lt;/h3&gt;

&lt;p&gt;A classless CSS framework that gives you some reasonable defaults to get started with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andybrewer/mvp/" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://andybrewer.github.io/mvp/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  W3 Core Styles
&lt;/h3&gt;

&lt;p&gt;If you prefer to get your CSS styles directly from the source, look no further. While not the prettiest styles, these certainly work for some types of sites and you can bet that they will work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/StyleSheets/Core/Overview" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bamboo CSS
&lt;/h3&gt;

&lt;p&gt;A classless CSS library that adds nice defaults to HTML elements, and uses normalize.css and sanitize.css under the hood for a consistent experience and supports dark mode with automatic theme detection out of the box&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rilwis/bamboo" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://rilwis.github.io/bamboo/demo/" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Water CSS
&lt;/h3&gt;

&lt;p&gt;Water CSS is another classless CSS framework that gives you dark mode out of the box, gives you way better form elements and improves typography. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kognise/water.css" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://watercss.kognise.dev/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you liked this post you should check out &lt;a href="https://awesomedevtools.com" rel="noopener noreferrer"&gt;Awesome Devtools&lt;/a&gt;. A larger collection of devtools for web developers.&lt;/p&gt;

&lt;p&gt;​ &lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>vue</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a blog with Gatsby from scratch</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Mon, 14 Jun 2021 15:59:52 +0000</pubDate>
      <link>https://dev.to/sgolovine/building-a-blog-with-gatsby-from-scratch-52c3</link>
      <guid>https://dev.to/sgolovine/building-a-blog-with-gatsby-from-scratch-52c3</guid>
      <description>&lt;p&gt;Gatsby is a static site generator and is one of the most popular JS frameworks out there, running on top of React. Most guides you will read here will point you to building a Gatsby site by starting with &lt;code&gt;gatsby new ...&lt;/code&gt;, while I think that this is a great starting point, In this post I want to explain how to build a Gatsby blog completely from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Everything Up
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before we get going make sure that you have NodeJS and Yarn both installed on your system. I suggest using &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM&lt;/a&gt; to install Node.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initializing the Project
&lt;/h3&gt;

&lt;p&gt;To start create a new folder for your project. Inside the folder, run &lt;code&gt;yarn init -y&lt;/code&gt; to initialize it as a Javascript project. Then run &lt;code&gt;yarn&lt;/code&gt; to generate a &lt;code&gt;yarn.lock&lt;/code&gt; file and a &lt;code&gt;node_modules&lt;/code&gt; folder. The next step is to add the dependencies that we will need.&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;yarn&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dom&lt;/span&gt; &lt;span class="nx"&gt;gatsby&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly you will want to create our Gatsby configurations, to start create a file called &lt;code&gt;gatsby-config.js&lt;/code&gt; and populate it with the following:&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;// gatsby-config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&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;h3&gt;
  
  
  Setup the Scripts
&lt;/h3&gt;

&lt;p&gt;Once we have out dependencies installed, the next step is to create a few scripts for us to control Gatsby. Add the following items to the "scripts" section of your &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gatsby develop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gatsby build"&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;h3&gt;
  
  
  Setup the Files
&lt;/h3&gt;

&lt;p&gt;The last little bit we will need before we can run the site is to generate a page for Gatsby to render. To do this, create a &lt;code&gt;src&lt;/code&gt; folder with a &lt;code&gt;pages&lt;/code&gt; folder inside, then create a file inside called &lt;code&gt;index.js&lt;/code&gt; and populate it with the following:&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;// src/pages/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;World&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have everything setup, run &lt;code&gt;yarn&lt;/code&gt; and then &lt;code&gt;yarn start&lt;/code&gt; and then to go &lt;code&gt;http://localhost:8000&lt;/code&gt; to see your site.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Setting up the Blog
&lt;/h2&gt;

&lt;p&gt;Now that we have the basic site up and running, it's time to setup the blog. To start, create a folder in the root of your project called &lt;code&gt;static&lt;/code&gt; and create another folder inside called &lt;code&gt;posts&lt;/code&gt;. Create several markdown files inside, the filenames do not matter however they should be formatted using &lt;a href="https://jekyllrb.com/docs/front-matter/" rel="noopener noreferrer"&gt;frontmatter&lt;/a&gt;. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
title: My First Post
slug: first-post
date: June 14, 2021
---

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam a ex suscipit, tincidunt nisi dapibus, porta augue. Nam quam quam, consectetur in iaculis sit amet, fermentum a tortor. Duis eget ex nisi. Quisque ac nunc in ipsum luctus cursus vitae eget nisl. Quisque et faucibus leo. Suspendisse potenti. Quisque sed arcu nulla.

Vivamus vestibulum aliquet mi. In consectetur euismod risus molestie viverra. Nulla aliquam molestie quam a mattis. Cras nec purus sollicitudin, fringilla odio ut, eleifend ipsum. Morbi imperdiet velit vel ligula euismod accumsan. Vivamus at lorem ac nulla porttitor euismod. Proin molestie, neque ut molestie elementum, nisi sapien tincidunt nisi, at ullamcorper justo mi eu nunc. Aenean in dolor volutpat, pulvinar magna eget, consequat urna.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installing Dependencies
&lt;/h3&gt;

&lt;p&gt;When we run &lt;code&gt;gatsby develop&lt;/code&gt;, we want Gatsby to look in our static folder, find any blog posts, and create a page for each post. There are two ways to fetch markdown data in Gatsby, we can either use Gatsby Remark or we can use MDX. In this guide we will use MDX. To start, install the following packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @mdx-js/react @mdx-js/mdx gatsby-plugin-mdx gatsby-source-filesystem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Gatsby to get our Data
&lt;/h3&gt;

&lt;p&gt;By default, Gatsby is not aware of the existence of our &lt;code&gt;static&lt;/code&gt; folder, we need to expose this folder to Gatsby so we can query the contents using GraphQL. To expose this folder, add an instance of &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; to &lt;code&gt;gatsby-config.js&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;// gatsby-config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// This tells gatsby about the directory&lt;/span&gt;
    &lt;span class="c1"&gt;// And to source files from the directory&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-source-filesystem`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`posts`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;static&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;posts&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="c1"&gt;// This plugin will help gatsby handle markdown files that it finds in `static/posts`&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-plugin-mdx`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;extensions&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;.md&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="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;Now if you start the dev server and go to &lt;code&gt;https://localhost:8000/__graphql&lt;/code&gt;, and then execute this query, you will see that it returns the markdown file you have created&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MyQuery&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;allMdx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;nodes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;frontmatter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"allMdx"&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;"nodes"&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;"frontmatter"&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;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first-post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My First Post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"June 14, 2021"&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;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;"extensions"&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;Fantastic, we have the data being fed to Gatsby now, at this point we now need to create a template to store this data, and then tell Gatsby to fetch the data when we build the site and display it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Template
&lt;/h3&gt;

&lt;p&gt;Once we get the data from the filesystem, we need to tell Gatsby how to render it. For this we will need to create a template page for our posts. Start off by creating a file called &lt;code&gt;template.js&lt;/code&gt; in your &lt;code&gt;src&lt;/code&gt; folder.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MDXRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-mdx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;


&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PostTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Here pageContext is passed in at build time by gatsby-node.js&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pageContext&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** Header to our post */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** Post Body */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MDXRenderer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/MDXRenderer&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;PostTemplate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in this template, &lt;code&gt;frontmatter&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt; are both props we are passing to this template from out &lt;code&gt;gatsby-node.js&lt;/code&gt; script, which we will setup in the next section. Also &lt;code&gt;&amp;lt;MDXRenderer&amp;gt;&lt;/code&gt; is handling everything related to our rendering. You can control the rendering very granularly if you dig into the configuration, but this is the most basic version that we will need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up Gatsby Node API
&lt;/h3&gt;

&lt;p&gt;The next step in setting up a blog is to route our data from GraphQL and render it onto the page. We do this inside &lt;code&gt;gatsby-node.js&lt;/code&gt;. To start create a file in the root of your project called &lt;code&gt;gatsby-node.js&lt;/code&gt; and populate it with the following:&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createPages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actions&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;// This is the query we will use to fetch data from GraphQL&lt;/span&gt;
  &lt;span class="c1"&gt;// This query will look for markdown files that have `/posts/` in&lt;/span&gt;
  &lt;span class="c1"&gt;// Their absolute path. If you keep your posts in another place you will&lt;/span&gt;
  &lt;span class="c1"&gt;// Need to change this&lt;/span&gt;
  &lt;span class="c1"&gt;// Inside each file we need the title, date, slug and the posts body&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    query Posts {
      allMdx(filter: { fileAbsolutePath: { regex: "/posts/" } }) {
        edges {
          node {
            id
            frontmatter {
              date
              title
              slug
            }
            body
          }
        }
      }
    }
  `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


  &lt;span class="c1"&gt;// Check for any errors in the query&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;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Get the posts and put them into a nice object&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allMdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;

  &lt;span class="c1"&gt;// Fetch the post template we created in teh previous step&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&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;template.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Iterate over every post we queried, then for every post call&lt;/span&gt;
  &lt;span class="c1"&gt;// actions.createPage() to build a page with the data and template&lt;/span&gt;
  &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;

    &lt;span class="c1"&gt;// This is the post path. We use a combo of the slug in a string&lt;/span&gt;
    &lt;span class="c1"&gt;// Template prefixed with /post. You can change this to be anything you want&lt;/span&gt;
    &lt;span class="c1"&gt;// So long as the path does not collide with another path&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/post/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;


    &lt;span class="c1"&gt;// Now we finally create the page&lt;/span&gt;
    &lt;span class="c1"&gt;// We assign every page the path we just created and build it&lt;/span&gt;
    &lt;span class="c1"&gt;// Using our postTemplate component. We also pass in some context about the post&lt;/span&gt;
    &lt;span class="c1"&gt;// Which will be used by the template via pageProps&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;postTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;body&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;p&gt;There's quite a lot to unpack in this script, I suggest reading over the comments to try and understand everything that is going on. But this is pretty much it. Now if you run your development server and go to &lt;code&gt;http://localhost:8000/post/first-post&lt;/code&gt;, you should see your post being rendered.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Setting up a Post List
&lt;/h2&gt;

&lt;p&gt;The last step is to setup your home page to display your posts. To do this we will reuse the query we created for our &lt;code&gt;gatsby-node.js&lt;/code&gt; script. Except this time we will be putting it in our &lt;code&gt;index.js&lt;/code&gt; page as a static query. In &lt;code&gt;src/index.js&lt;/code&gt;, add the following code static query&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;// src/pages/index.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// This query will get all of your posts&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
    query {
      allMdx(filter: {fileAbsolutePath: {regex: "/posts/"}}) {
        edges {
          node {
            frontmatter {
              date
              title
              slug
            }
          }
        }
      }
    }
  `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt; &lt;span class="nx"&gt;World&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** This will render each title out on the page. And lets you click on the link to view the post*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allMdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;edges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;edge&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&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;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/post/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;path&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="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With that you should now have a functioning Gatsby blog. From here you can now go on to add image support, styling the blog and adding tags. This post was meant to show how you can get a minimum viable blog going in Gatsby.&lt;/p&gt;

&lt;p&gt;If you enjoyed this post, check out some of my other posts &lt;a href="https://sunny.gg/post" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gatsby</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Roll your own URL shortener using Netlify Redirects.</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Fri, 11 Jun 2021 14:12:52 +0000</pubDate>
      <link>https://dev.to/sgolovine/roll-your-own-url-shortener-using-netlify-redirects-3k3h</link>
      <guid>https://dev.to/sgolovine/roll-your-own-url-shortener-using-netlify-redirects-3k3h</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: I am not affiliated with Netlify&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Earlier this week I had a problem. I had just spun a self hosted instance of Plausible Analytics and I wanted to create some campaigns for my personal website to track where users were coming from on the internet, whether clicking on links in my post, social media bio's, etc. The problem is in creating my campaigns, my URL's all ended up looking something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://mydomain.com?utm_source=dev.to&amp;amp;utm_medium=post&amp;amp;utm_campaign=post-click-throughs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not a great look if the service doesn't shorten the URL's. I wanted a solution where I wasn't reliant on other services to clean up my URL's.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;What I needed here was a URL shortened that would shorten that hideously long looking URL into a shorter one, I had some spare domain names that were redirecting to my main domain so I decided to take &lt;code&gt;sunny.gg&lt;/code&gt; and convert it into a URL shortener.&lt;/p&gt;

&lt;p&gt;In my case I wasn't shortening URL's all the time so having a static solution where you couldn't create new URL's on the fly was acceptable, all I needed was the ability to shorten a set of long URL's into pretty short ones, and then share those around.&lt;/p&gt;

&lt;p&gt;To achieve this I used Netlify and their redirects ability. Create a project that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app/index.html
/netlify.toml
/package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can populate your &lt;code&gt;/app/index.html&lt;/code&gt; as you see fit, it doesn't really matter in this case, just a bare HTML file will do. The netlify.toml file is where things get interesting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[build]&lt;/span&gt;
  &lt;span class="py"&gt;base&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;
  &lt;span class="py"&gt;publish&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"app/"&lt;/span&gt;
  &lt;span class="py"&gt;build&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"echo 'no build command'"&lt;/span&gt;


&lt;span class="c"&gt;# Primary redirect&lt;/span&gt;
&lt;span class="nn"&gt;[[ redirects ]]&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/"&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://yourmainwebsite.com"&lt;/span&gt;
  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt;

&lt;span class="c"&gt;# Add as many of these as needed&lt;/span&gt;
&lt;span class="nn"&gt;[[ redirects ]]&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/some-pretty-url"&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"https://mydomain.com?utm_source=dev.to&amp;amp;utm_medium=post&amp;amp;utm_campaign&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;post-click-throughs&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt;

&lt;span class="nn"&gt;[[ redirects ]]&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/foo"&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"https://mydomain.com/bar?utm_source=dev.to&amp;amp;utm_campaign&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;bar&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thought somewhat of a crude solution, though I found it to work quite well, you can see it in action with my post footer on this post.&lt;/p&gt;




&lt;p&gt;If you like this post, check out some of my other posts on &lt;a href="https://sunny.sh/post" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>netlify</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Removing secrets from a git repo</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Sat, 05 Jun 2021 01:23:26 +0000</pubDate>
      <link>https://dev.to/sgolovine/removing-secrets-from-a-git-repo-1ljf</link>
      <guid>https://dev.to/sgolovine/removing-secrets-from-a-git-repo-1ljf</guid>
      <description>&lt;p&gt;Working on &lt;a href="https://awesomedevtools.com" rel="noopener noreferrer"&gt;Awesome Devtools&lt;/a&gt; this past week, I decided to make the repo public so others could contribute to it. I had one slight problem though, I had committed my &lt;code&gt;.env&lt;/code&gt; file which contained secrets I would rather the world not know.&lt;/p&gt;

&lt;p&gt;So how would you delete a file like this? Well standard logic says just....delete it. But with git it's not that simple, when you delete something, even though the latest version of your code no longer has this thing, the previous version of your code still do. Simply deleting the file would not work.&lt;/p&gt;

&lt;p&gt;There are two ways of deleting a file entirely in git. One way where you preserve your git history, and one where you do not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delete while preserving git history
&lt;/h2&gt;

&lt;p&gt;If you want to delete a file while still preserving your git history, you can do so with a neat recipe from Github.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Delete the file&lt;/span&gt;
git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; &amp;lt;your_file&amp;gt;

&lt;span class="c"&gt;# Commit the change&lt;/span&gt;
git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;-CHEAD&lt;/span&gt;

&lt;span class="c"&gt;# Push the commit&lt;/span&gt;
git push

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Delete the file and nuke git history
&lt;/h2&gt;

&lt;p&gt;If you're like me and don't really care about your git history for a particular project, you can do it the way I did it and just nuke the file and all the history leading to the file.&lt;/p&gt;

&lt;p&gt;First run &lt;code&gt;git remote -v&lt;/code&gt; to get your current remote.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
➜ git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
origin  git@github.com:sgolovine/awesome-devtools.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin  git@github.com:sgolovine/awesome-devtools.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now delete your the file and also delete the &lt;code&gt;.git&lt;/code&gt; folder. Once you've deleted the file, recreate the git repository locally&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
git init
git add &lt;span class="nt"&gt;-A&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial Commit"&lt;/span&gt;
git remote add origin &amp;lt;url from step 1&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally do a force push to your remote to overwrite the previous history with &lt;code&gt;git push -f&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it! If you know of a better way to delete a file from git history, leave a comment below and I will update the article. You can find more of my article here and on my &lt;a href="https://sunnygolovine.com/blog" rel="noopener noreferrer"&gt;blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Persisting useReducer with a custom React Hook</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Wed, 28 Apr 2021 13:45:14 +0000</pubDate>
      <link>https://dev.to/sgolovine/persisting-usereducer-with-a-custom-react-hook-1j27</link>
      <guid>https://dev.to/sgolovine/persisting-usereducer-with-a-custom-react-hook-1j27</guid>
      <description>&lt;p&gt;&lt;em&gt;google "reducer" if you're confused by the cover image&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I was building &lt;a href="https://gistmarks.io" rel="noopener noreferrer"&gt;gistmarks&lt;/a&gt;, I needed to store users data and pass it around to various parts of the app. For this I typically use Redux combined with Redux Persist. This approach is tried and true but does involve quite a bit of boilerplate code so I wanted to try something new.&lt;/p&gt;

&lt;p&gt;I quickly learned that &lt;code&gt;useReducer&lt;/code&gt; is a highly competent alternative to Redux and typing it (adding typescript types) is much more straightforward than it is with Redux. There was however one thing missing: Persistence.&lt;/p&gt;

&lt;p&gt;For me, being able to persist a users state is crucial to my app functioning so having a way of persisting data with the &lt;code&gt;useReducer&lt;/code&gt; hook was essential. With Redux I would always use &lt;a href="https://github.com/rt2zz/redux-persist" rel="noopener noreferrer"&gt;redux-persist&lt;/a&gt; however there didn't seem to be any formal way of doing it with &lt;code&gt;useReducer&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;As a result I created my own hook that persists the reducers data to localStorage. Here's that hook:&lt;/p&gt;

&lt;p&gt;Javascript Version:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;deepEqual&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fast-deep-equal/es6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePrevious&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./usePrevious&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;usePersistedReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;storageKey&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;init&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;prevState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePrevious&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&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;stringState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storageKey&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;stringState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stringState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;initialState&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;initialState&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;stateEqual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;stateEqual&lt;/span&gt;&lt;span class="p"&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;stringifiedState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stringifiedState&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&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;Typescript Version:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useReducer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;deepEqual&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fast-deep-equal/es6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;usePrevious&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./usePrevious&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;usePersistedReducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Action&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;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;init&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;prevState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePrevious&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;State&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;stringState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storageKey&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;stringState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stringState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;initialState&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;initialState&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;stateEqual&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;stateEqual&lt;/span&gt;&lt;span class="p"&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;stringifiedState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stringifiedState&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&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;For this hook you will also need a companion hook called &lt;code&gt;usePrevious&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Typescript Version:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Given any value&lt;/span&gt;
&lt;span class="c1"&gt;// This hook will return the previous value&lt;/span&gt;
&lt;span class="c1"&gt;// Whenever the current value changes&lt;/span&gt;

&lt;span class="c1"&gt;// eslint-disable-next-line @typescript-eslint/no-explicit-any&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;usePrevious&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&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;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Javascript Version:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Given any value&lt;/span&gt;
&lt;span class="c1"&gt;// This hook will return the previous value&lt;/span&gt;
&lt;span class="c1"&gt;// Whenever the current value changes&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;usePrevious&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&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;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The hook manages syncing state internally. Whenever you issue a dispatch, an effect within the hook checks the previous state of the reducer and if the state changed, it will backup that state to localStorage.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;Using this hook is super easy.&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;initialState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&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;storageKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MY_STORAGE_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePersistedReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// use state and dispatch as you normally would.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's pretty much it. If you think I could improve this hook leave a comment and I'll update the article. If you liked this article check out some of my other posts &lt;a href="https://sunnygolovine.com/blog" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>javascript</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Awesome Git Shortcuts</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Fri, 23 Apr 2021 16:00:33 +0000</pubDate>
      <link>https://dev.to/sgolovine/awesome-git-shortcuts-2bpd</link>
      <guid>https://dev.to/sgolovine/awesome-git-shortcuts-2bpd</guid>
      <description>&lt;p&gt;Besides VSCode, git is probably the most used tool in my toolbox. Over the years I've learned that there are a few common git commands that I always repeat, so I created some sensible aliases to help me move faster. I wanted to share these aliases with any folks here that might find them helpful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Status&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By far the most frequently used alias is my alias to &lt;code&gt;git status&lt;/code&gt;. I aliased &lt;code&gt;git status&lt;/code&gt; to &lt;code&gt;gst&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Add&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The normal command for staging files for a commit is &lt;code&gt;git add -A&lt;/code&gt; or &lt;code&gt;git add .&lt;/code&gt; or &lt;code&gt;git add some/file/name.ts&lt;/code&gt;. I created an alias for it simply to &lt;code&gt;ga&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Commit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simmilarly to git add, I also created an alias for git commit. The typical command is &lt;code&gt;git commit&lt;/code&gt; or &lt;code&gt;git commit -m &amp;lt;COMMIT_MSG&amp;gt;&lt;/code&gt;, I aliased &lt;code&gt;git commit&lt;/code&gt; to &lt;code&gt;gc&lt;/code&gt; and &lt;code&gt;git commit -m&lt;/code&gt; to &lt;code&gt;gcm&lt;/code&gt;. Now you can type out a commit message like &lt;code&gt;gcm "some cool messsage"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Diff&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For git diff I added two aliases. First is &lt;code&gt;gd&lt;/code&gt; which is an alias to &lt;code&gt;git diff&lt;/code&gt;. However I also have &lt;code&gt;gdc&lt;/code&gt; which is aliased to &lt;code&gt;git diff --cached&lt;/code&gt;, for viewing diffs after you have staged your files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Push&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also aliased &lt;code&gt;git push&lt;/code&gt; to &lt;code&gt;gp&lt;/code&gt;. Not much more to say here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Checkout&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For quickly checking out branches I aliased &lt;code&gt;git checkout&lt;/code&gt; to &lt;code&gt;gco&lt;/code&gt;. For new branches I also created a &lt;code&gt;gcob&lt;/code&gt; alias that does &lt;code&gt;git checkout -b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git Branch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For quickly listing branches I aliased &lt;code&gt;git branch&lt;/code&gt; to &lt;code&gt;gb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Besides being much faster to type out, another benefit of these aliases is that you can still use flags like normally. Say you want to push a new branch to a remote. Without aliases it would look like this: &lt;code&gt;git push -u origin my_branch&lt;/code&gt;. But with aliases I can simply type &lt;code&gt;gp -u origin my_branch&lt;/code&gt;, not a significant savings but when you type the command out thousands of times, it starts to make a difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try them out yourself
&lt;/h2&gt;

&lt;p&gt;While there are many ways you can create a git alias, I did it in the most simple way by just adding an alias to my &lt;code&gt;.bashrc&lt;/code&gt;. Here are all the aliases I mentioned in this post&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git status'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;ga&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git add -A'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git commit'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gcm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git commit -m'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git diff'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gdc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git diff --cached'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git push'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gco&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git checkout'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gcob&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git checkout -b'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git branch'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to give these a test drive, paste this code block directly into your terminal and it will enable these aliases for the current session. If you like them you can then add it to your &lt;code&gt;.bashrc&lt;/code&gt; / &lt;code&gt;.zshrc&lt;/code&gt; / etc.&lt;/p&gt;




&lt;p&gt;If you liked this post check out some of my other writing &lt;a href="https://sunnygolovine.com/blog" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
      <category>react</category>
      <category>git</category>
    </item>
    <item>
      <title>Migrating from NPM to Yarn</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Sun, 18 Apr 2021 15:10:38 +0000</pubDate>
      <link>https://dev.to/sgolovine/migrating-from-npm-to-yarn-2ih3</link>
      <guid>https://dev.to/sgolovine/migrating-from-npm-to-yarn-2ih3</guid>
      <description>&lt;p&gt;Say you have a project that uses NPM for dependency management. How would you convert that project to use Yarn?&lt;/p&gt;

&lt;p&gt;For the longest time the way I did it was just deleting the &lt;code&gt;package-lock.json&lt;/code&gt; and running &lt;code&gt;yarn&lt;/code&gt; to generate a new lockfile. While this works well on small projects, dependency pinning is there for a reason and trying to do this on a larger project may land you in hot water. So how do you do it safely? It's simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
yarn import

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! When you run &lt;code&gt;yarn import&lt;/code&gt;, yarn will read your &lt;code&gt;package-lock.json&lt;/code&gt; and generate a &lt;code&gt;yarn.lock&lt;/code&gt; file based on it. It's a much safer way to migrate from one package manager to the other.&lt;/p&gt;

&lt;p&gt;If you enjoyed this post check out some of my &lt;a href="https://sunnygolovine.com/blog" rel="noopener noreferrer"&gt;other writing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>npm</category>
      <category>angular</category>
    </item>
    <item>
      <title>Opt your Netlify, Vercel or Github Pages site out of Google's FLoC Network</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Fri, 16 Apr 2021 13:52:19 +0000</pubDate>
      <link>https://dev.to/sgolovine/opt-your-netlify-vercel-or-github-pages-site-out-of-google-s-floc-network-3nhl</link>
      <guid>https://dev.to/sgolovine/opt-your-netlify-vercel-or-github-pages-site-out-of-google-s-floc-network-3nhl</guid>
      <description>&lt;p&gt;EDIT 3: &lt;a href="https://github.blog/changelog/2021-04-27-github-pages-permissions-policy-interest-cohort-header-added-to-all-pages-sites/" rel="noopener noreferrer"&gt;Github Announced&lt;/a&gt; yesterday that FLoC will be disabled on all Github Pages. If your site is hosted on Github Pages feel free to skip this article, Github has you covered.&lt;/p&gt;

&lt;p&gt;EDIT 2: Some readers have mentioned that the Github Pages solution does not work. Namely from &lt;a href="https://github.com/w3c/webappsec-permissions-policy/issues/55#issuecomment-412077633" rel="noopener noreferrer"&gt;this Github thread&lt;/a&gt; and &lt;a href="https://github.com/w3c/webappsec-permissions-policy/pull/313#discussion_r286820352" rel="noopener noreferrer"&gt;this one&lt;/a&gt;. My suggestion here is to move off of Github Pages if this is something you really care about. Both Netlify and Vercel are fantastic hosts and offer the ability to disable FLoC via headers.&lt;/p&gt;

&lt;p&gt;EDIT: One of the commenters pointed out that during the FLoC origin trial, FLoC is only loaded and computed when the site contains ads-related resources&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;During the FLoC origin trial, pages on websites that don't opt out will be included in the FLoC calculation if Chrome detects that they load ads-related resources or if they use document.interestCohort(). Pages served from private IP addresses, such as intranet pages, won't be part of the FLoC computation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means is that if you are not running Google Ads on your site, you will not be opted into FLoC during the origin trial. I would personally still recommend opting out as FLoC will likely be loaded on all sites after the trial period is over.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.chrome.com/blog/floc/#how-can-websites-opt-out-of-the-floc-computation" rel="noopener noreferrer"&gt;More Information (google.com)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Federated Learning of Cohorts (or simply FLoC) has made quite a stir in tech circles in the past few days. While I'm by no means expert enough to explain to you how it works, long story short it's a new way for Google to track users now that cookies have become persona non grata in the tech world.&lt;/p&gt;

&lt;p&gt;No one in the privacy space is happy about this. The EFF &lt;a href="https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea" rel="noopener noreferrer"&gt;wrote a scathing article on it&lt;/a&gt; and companies like DuckDuckGo and Brave have already taken steps to block it on their search engines and browsers.&lt;/p&gt;

&lt;p&gt;Plausible Analytics &lt;a href="https://plausible.io/blog/google-floc" rel="noopener noreferrer"&gt;wrote up a report&lt;/a&gt; on what FLoC means for developers and, like all things from Google, it's "opt-out" rather than "opt-in", meaning if you do not take action on your site, Google will opt your site into FLoC. We should probably tell Google not to do that. &lt;/p&gt;

&lt;p&gt;At it's core all you need to do is add this header to your websites response headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
Permissions-Policy: interest-cohort&lt;span class="o"&gt;=()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like many of you here I run a number of sites through Netlify, Vercel and Github Pages. Here is a quick breakdown of how to opt-out of FLoC on all 3 platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Netlify
&lt;/h2&gt;

&lt;p&gt;Headers in Netlify can be added either via &lt;code&gt;netlify.toml&lt;/code&gt; or your &lt;code&gt;_headers&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;
&lt;span class="c"&gt;# netlify.toml&lt;/span&gt;

&lt;span class="nn"&gt;[[headers]]&lt;/span&gt;
  &lt;span class="py"&gt;for&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/*"&lt;/span&gt;
  &lt;span class="nn"&gt;[headers.values]&lt;/span&gt;
    &lt;span class="py"&gt;Permissions-Policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"interest-cohort&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;()&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# _headers&lt;/span&gt;

/&lt;span class="k"&gt;*&lt;/span&gt;
  Permissions-Policy: interest-cohort&lt;span class="o"&gt;=()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Github Pages
&lt;/h2&gt;

&lt;p&gt;Unfortunately it seems that Github Pages &lt;a href="https://stackoverflow.com/questions/14798589/github-pages-http-headers" rel="noopener noreferrer"&gt;does not allow you to set your HTTP headers&lt;/a&gt;. Luckily we can implement a workaround by adding this to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of your root HTML document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Permissions-Policy"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"interest-cohort=()"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Vercel
&lt;/h2&gt;

&lt;p&gt;Like Netlify, Vercel lets you set response headers through a &lt;code&gt;vercel.json&lt;/code&gt; file. To do so add this to the &lt;code&gt;headers&lt;/code&gt; block in your &lt;code&gt;vercel.json&lt;/code&gt; file. You can read more about Vercel's configuration options &lt;a href="https://vercel.com/docs/configuration#project/headers" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&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="err"&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;"source"&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;"headers"&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;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Permissions-Policy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"interest-cohort=()"&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="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;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Part of being a professional and responsible web developer is making sure you are good steward of your users' data, even if you don't directly ask them for it. While major browsers block FLoC already, adding these response headers to your site will ensure that users that aren't using those browsers are still safe from tracking.&lt;/p&gt;

&lt;p&gt;If you enjoyed this post check out some of my &lt;a href="https://sunnygolovine.com/blog" rel="noopener noreferrer"&gt;other writing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>google</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Your "Awesome" list sucks. Make it better with GistMarks.</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Tue, 13 Apr 2021 15:06:32 +0000</pubDate>
      <link>https://dev.to/sgolovine/your-awesome-list-sucks-make-it-better-with-gistmarks-2n34</link>
      <guid>https://dev.to/sgolovine/your-awesome-list-sucks-make-it-better-with-gistmarks-2n34</guid>
      <description>&lt;p&gt;Awesome Lists are &lt;strong&gt;awesome&lt;/strong&gt;, but they also kind of suck, let me explain. While the idea behind the awesome list is great, the implementation is less than ideal. Here we have all these bookmarks, yet the best format we can come up with to store all of these bookmarks is: a README??&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Awesome Lists
&lt;/h2&gt;

&lt;p&gt;Say you create a huge list of resources to help someone build a React application, I spend all this time building an awesome list but in the end I hit a few limitations&lt;/p&gt;

&lt;p&gt;💥 You can't search them: Sure you could CTRL+F but that's less than ideal for searching a huge document&lt;/p&gt;

&lt;p&gt;💥 Categorization is hard: You can create categories in your list but there's no easy way for users to filter by those categories. A table of contents makes things a little easier but that means users will have to scroll all the way back up to the TOC to navigate to another section.&lt;/p&gt;

&lt;p&gt;💥 Mobile Support: Anyone can view your awesome list on their phone, but unless you're careful about formatting, they might just see a complete mess.&lt;/p&gt;

&lt;p&gt;💥 Inaccessible data format: Everyone format's their awesome lists a bit differently. This means that if you want to create  tool to aggregate them, you're going to be dealing with a ton of incompatible formats.&lt;/p&gt;

&lt;p&gt;The result of all of this is even though your awesome list may be packed with awesome resources, few will benefit from it because just finding the right stuff on that list is hard. And if you want to spend the time building an awesome list with good navigation, you're going to spend more time on formatting them you will on actually adding good content to the list. So what's the solution? &lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Gistmarks
&lt;/h2&gt;

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

&lt;p&gt;I built Gistmarks out of an internal need to share bookmark collections. My company has alot of disparate sites on our intranet and tracking them down means spending time tracking those links down, scrolling through slack messages and email threads. Gistmarks solves this problem by letting anyone create a bookmark collection and then sharing it with whoever they want. With Gistmarks every team was able to create their own collection of bookmarks, internal dashboards, code repositories, etc and then share it with other, drastically cutting down the time it took to find a link to that internal tool you needed.&lt;/p&gt;

&lt;p&gt;But as I was building Gistmarks I realized there are many more use cases for such a tool, namely Awesome Lists. Whenever you build an Awesome List with Gistmarks, your list is now sorted by category, searchable, has all the UI elements needed for good navigation and your data is stored in a consistent format that can be then used by others.&lt;/p&gt;

&lt;p&gt;Check out some awesome lists created with Gistmarks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.gistmarks.io/v/3fca793689a21f0bbef8279b9249b297" rel="noopener noreferrer"&gt;Workout Collection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.gistmarks.io/v/d9a1fb8f0f305e586f76856e88caadf4" rel="noopener noreferrer"&gt;Cooking Collection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.gistmarks.io/v/bdd7ae5cd6376591742e2fbb68ecfe24" rel="noopener noreferrer"&gt;Dev Team Collection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.gistmarks.io/v/74c4f084e6aba53feb92586eeb3cafae" rel="noopener noreferrer"&gt;React Resources Collection&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Make your awesome lists more awesome today.
&lt;/h2&gt;

&lt;p&gt;Gistmarks is free to use. Get started creating bookmark collections with GistMarks today.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gistmarks.io" rel="noopener noreferrer"&gt;Gistmarks&lt;/a&gt;&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>developers</category>
    </item>
    <item>
      <title>Create your own NFC business card.</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Sun, 13 Dec 2020 17:30:46 +0000</pubDate>
      <link>https://dev.to/sgolovine/create-your-own-nfc-business-card-1606</link>
      <guid>https://dev.to/sgolovine/create-your-own-nfc-business-card-1606</guid>
      <description>&lt;p&gt;If you've been on Instagram lately then you've probably seen ads for companies like &lt;a href="https://blue.social" rel="noopener noreferrer"&gt;Blue Social&lt;/a&gt; that advertise "smart" business cards, letting you share personal information with others simply by tapping this card on their device.&lt;/p&gt;

&lt;p&gt;While the concept is cool, I personally didn't like Blue Social. For one, their cards link out to a page on blue social, I wanted to link to my own site. Second, the price just wasn't right, at $34.99, it wasn't worth it to me at that price. &lt;/p&gt;

&lt;p&gt;But then it got me thinking, NFC smart cards aren't rocket science, I bet I could just make one myself. Usually when I do something like this it ends up being much harder than I previously anticipated, but in this case it was actually &lt;em&gt;way easier than I thought&lt;/em&gt;. So, you ready to make your own NFC smart cards? &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Buy the card
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsx36hsm32qb56mxexnoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsx36hsm32qb56mxexnoa.png" alt="nfc-cards-on-amazon" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step is to get some NFC smart cards. I would suggest just searching "NFC Cards" on Amazon or Ebay, you can usually get them for around $4.99 for 10 cards. There are many shapes and sizes of these cards and prices vary depending on quantity, it doesn't really matter which one you get.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Load data
&lt;/h2&gt;

&lt;p&gt;Once you get your NFC cards, the next step is to load data on your device. To load data on your device you will need a smartphone with NFC capabilities (most devices support NFC these days) and a free app (there are tons). I suggest NFC tools, you can find the iOS app &lt;a href="https://apps.apple.com/us/app/nfc-tools/id1252962749" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the Android app &lt;a href="https://play.google.com/store/apps/details?id=com.wakdev.wdnfc" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsmsyy61kuyq79t2cu3pb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsmsyy61kuyq79t2cu3pb.png" alt="nfc-tools" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One you open the app go ahead and click "read" and then tap your card to your device, it should read the card and show that there is no data on your card. Next go back and click on write and then add a some records. &lt;/p&gt;

&lt;p&gt;If you want to share contact info with iPhones you can either put your phone number or website and iPhones will read that, however if you add a contact, Android devices will read it but iPhones wont.&lt;/p&gt;

&lt;p&gt;Once you add your data, select "Write" and then tap your card to the device. After the data is written you should be able to just tap your card to your device and notification will show up to open your website/contact/phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;NFC Smart cards are really easy to make, while companies like Blue social give you a very user friendly way to make one, i prefer to save a few bucks and have fun doing it myself.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>nfc</category>
    </item>
    <item>
      <title>Github Actions for your Javascript Project: In less than 5 minutes.</title>
      <dc:creator>Sunny Golovine</dc:creator>
      <pubDate>Mon, 23 Nov 2020 17:50:30 +0000</pubDate>
      <link>https://dev.to/sgolovine/github-actions-for-your-javascript-project-in-less-than-5-minutes-54dc</link>
      <guid>https://dev.to/sgolovine/github-actions-for-your-javascript-project-in-less-than-5-minutes-54dc</guid>
      <description>&lt;p&gt;Setting up CI (Continuous Integration) to your project used to be a good bit of work. If you stored your code in Github, you would need to setup an account with Jenkins, CircleCI or others, and go through the arduous process of getting the two systems to talk to one another, in short, it was a bit of a pain in the a**.&lt;/p&gt;

&lt;p&gt;Github Actions came on the scene last year and what makes it so awesome is if you already have your code in Github, you can setup a pipeline in minutes, not hours. In this guide I'll show you how you can setup your own pipeline with Github actions in as little as 5 minutes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequsites
&lt;/h2&gt;

&lt;p&gt;This guide assumes that you have the following already setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Javascript project in Github&lt;/li&gt;
&lt;li&gt;Package Scripts to run linting, typechecking, testing, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that out of the way lets get started&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up your workflow file.
&lt;/h2&gt;

&lt;p&gt;Github actions runs off of a workflow file, this file will tell Github how to setup the CI machine and what to do after it's been setup. To get started, create a folder in the root of your directory called &lt;code&gt;.github&lt;/code&gt;. From there go inside that folder and create another folder called &lt;code&gt;workflows&lt;/code&gt;. Going inside that folder again, create a YAML file, it can be whatever name you want (I usually do something boring like &lt;code&gt;ci.yaml&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Once you've created the workflow file, paste this inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;closed&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;job-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;12.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Setup steps&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node-version }}&lt;/span&gt;
      &lt;span class="c1"&gt;# User defined steps&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sudo npm install -g yarn&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn lint&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;CI&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So let's break down what's going on in this file. First off at the top you have the name which you want to call the workflow. Again it can be anything you want. &lt;/p&gt;

&lt;p&gt;Below that you have the &lt;code&gt;on:&lt;/code&gt; block, this block defines &lt;em&gt;when&lt;/em&gt; the workflow is run on and on which branches. This workflow is meant to run on a pull request and runs whenever one is opened or closed, it's also restricting runs to PR's that are opened against the &lt;code&gt;main&lt;/code&gt; branch. If you have other branches like &lt;code&gt;develop&lt;/code&gt; or &lt;code&gt;release&lt;/code&gt;, you can add them into that block as well.&lt;/p&gt;

&lt;p&gt;Below the &lt;code&gt;on:&lt;/code&gt; block you have a &lt;code&gt;strategy:&lt;/code&gt; block. This defines which version of node you are using. In this case we are using a matrix and specifying that we want to run the jobs with a node version that is v12.x.x. &lt;/p&gt;

&lt;p&gt;Finally at the bottom is the meat and potatoes of the workflow, the &lt;code&gt;steps&lt;/code&gt; block. The first few steps are there to setup NodeJS but below that you can define your own steps. &lt;/p&gt;

&lt;p&gt;In this example, my project uses &lt;code&gt;yarn&lt;/code&gt; so the first step is to install that then to run the &lt;code&gt;lint&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; commands. You can add, remove and modify these steps according to what is in your &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Opening a PR.
&lt;/h2&gt;

&lt;p&gt;Once you have finished setting up the worflow file, commit your changes to a branch and then open a PR into your &lt;code&gt;main&lt;/code&gt; branch. When you do that, the CI will automatically kick off and start running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnfrxw3m7dljfkr7yckbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnfrxw3m7dljfkr7yckbr.png" alt="profit!" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this quick guide helps everyone in keeping their code more reliable. This is a pretty basic setup and will let you add functionality as you continue to grow your project.&lt;/p&gt;

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