<?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: Kavin Desi Valli</title>
    <description>The latest articles on DEV Community by Kavin Desi Valli (@kavinvalli).</description>
    <link>https://dev.to/kavinvalli</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%2F470582%2F0fc6098c-4517-4dfb-ad58-12c1ef2d0086.jpg</url>
      <title>DEV Community: Kavin Desi Valli</title>
      <link>https://dev.to/kavinvalli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kavinvalli"/>
    <language>en</language>
    <item>
      <title>Master NextJS 13 Data Fetching with this Step-by-Step Guide</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Mon, 27 Mar 2023 08:32:42 +0000</pubDate>
      <link>https://dev.to/kavinvalli/master-nextjs-13-data-fetching-with-this-step-by-step-guide-286i</link>
      <guid>https://dev.to/kavinvalli/master-nextjs-13-data-fetching-with-this-step-by-step-guide-286i</guid>
      <description>&lt;p&gt;The release of NextJS 13 brought about a plethora of new and impressive features, with one standout being the updated data fetching and management process. The fetch API replaced the more complicated functions, including &lt;code&gt;getServerSideProps&lt;/code&gt;, &lt;code&gt;getStaticProps&lt;/code&gt;, and &lt;code&gt;getInitialProps&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video
&lt;/h2&gt;

&lt;p&gt;If you prefer watching a video, you can check out the Youtube video posted on the same&lt;/p&gt;

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

&lt;h2&gt;
  
  
  fetch() API
&lt;/h2&gt;

&lt;p&gt;React recently introduces support for &lt;a href="https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md" rel="noopener noreferrer"&gt;async/await in Server Components&lt;/a&gt;. You can now write Server Components using standard JavaScript await syntax by defining your component as an async function and that is what turned out to be a big plus point for NextJS 13.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Components
&lt;/h2&gt;

&lt;p&gt;This is all you need to do to fetch data in NextJS now:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Post&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;@/lib/types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;Inter&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;next/font/google&lt;/span&gt;&lt;span class="dl"&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;inter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Inter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;subsets&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="s2"&gt;latin&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPosts&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&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;data&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/posts&lt;/span&gt;&lt;span class="dl"&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;posts&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Posts&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;posts&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;getPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&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="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;inter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Posts&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&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;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;The data is no more serialised so you can pass any type of data, including Dates, Maps, Sets, etc.&lt;/p&gt;

&lt;p&gt;Also, note the fact that you no longer need to do this on the page level, like if you did before using &lt;code&gt;getStaticProps&lt;/code&gt; or &lt;code&gt;getServerSideProps&lt;/code&gt;. You can do this inside any component&lt;/p&gt;

&lt;h2&gt;
  
  
  Client Components
&lt;/h2&gt;

&lt;p&gt;For now, if you need to fetch data in a Client Component, NextJS 13 recommends using a third-party library such as &lt;a href="https://swr.vercel.app/" rel="noopener noreferrer"&gt;SWR&lt;/a&gt; or &lt;a href="https://tanstack.com/query/v4" rel="noopener noreferrer"&gt;React Query&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;React also introduced the &lt;a href="https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#usepromise" rel="noopener noreferrer"&gt;&lt;code&gt;use&lt;/code&gt;&lt;/a&gt; hook that accepts a promise conceptually similar to await. use handles the promise returned by a function in a way that is compatible with components, hooks, and Suspense.&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;Post&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;@/lib/types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;Inter&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;next/font/google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;use&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="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Inter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;subsets&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="s2"&gt;latin&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPosts&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&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;data&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/posts&lt;/span&gt;&lt;span class="dl"&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;posts&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ClientPosts&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getPosts&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="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;inter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Posts&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&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;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;
  
  
  Static Data Fetching
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fetch&lt;/code&gt; by default caches the data. So, even if the data from the API changes, when you refresh the page, the site doesn't update the data. This works great for sites which have static data which seldom changes. The example above demonstrates how to do this because it is the same as doing&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/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="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;force-cache&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dynamic Data Fetching
&lt;/h2&gt;

&lt;p&gt;You can tell the &lt;code&gt;fetch&lt;/code&gt; API to never cache the data by changing &lt;code&gt;force-cache&lt;/code&gt; to &lt;code&gt;no-cache&lt;/code&gt; or &lt;code&gt;no-store&lt;/code&gt;(both signify the same in NextJS).&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/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="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-cache&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dynamic Params Data Fetching
&lt;/h2&gt;

&lt;p&gt;Say, you link all the posts to another page &lt;code&gt;/posts/[postId]&lt;/code&gt; and fetch the data here once you're in there. You'd do something like this:&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="c1"&gt;// app/posts/[postId]/page.tsx&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;Post&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;@/lib/types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;Inter&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;next/font/google&lt;/span&gt;&lt;span class="dl"&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;inter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Inter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;subsets&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="s2"&gt;latin&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="c1"&gt;// params: {&lt;/span&gt;
&lt;span class="c1"&gt;// postId: aksdjlkjasd&lt;/span&gt;
&lt;span class="c1"&gt;// }&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPost&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;id&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="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;data&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://jsonplaceholder.typicode.com/posts/&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="s2"&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;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;post&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PostPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;postId&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="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;postId&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="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;post&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;getPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postId&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="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;inter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Post ID: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;body&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;Now, this works great, but when you try to build it, look at the response:&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%2Froveljyq3xtpxuigqpq5.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%2Froveljyq3xtpxuigqpq5.png" alt="CLI Output for SSR of postId" width="629" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It says that &lt;code&gt;/posts/[postId]&lt;/code&gt; is server-side rendered at runtime even though &lt;code&gt;/posts&lt;/code&gt; is static. This is because NextJS doesn't know what all routes(postIds) exist. So, to enhance this further, you can add this function to the &lt;code&gt;/posts/[postId]/page.tsx&lt;/code&gt; page&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateStaticParams&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="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;data&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/posts&lt;/span&gt;&lt;span class="dl"&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;posts&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="na"&gt;post&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Post&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="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;postId&lt;/span&gt;&lt;span class="p"&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;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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;This now tells NextJS, that all these &lt;code&gt;postId&lt;/code&gt;s exist and we want it to statically generate them at build time if possible. Now, if we try rebuilding the app, this happens&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%2Fl8u8h8hajfb85fl8y004.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%2Fl8u8h8hajfb85fl8y004.png" alt="CLI Output for SSG of postId" width="708" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, see that &lt;code&gt;/posts/[postId]&lt;/code&gt; is static HTML + JSON! And, that would further optimise your app really well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Revalidating Data
&lt;/h2&gt;

&lt;p&gt;Say, your app is not fully dynamic but still sometimes the data does change, you can add this to your &lt;code&gt;/posts/[postId]/page.tsx&lt;/code&gt; page&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;revalidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// in seconds&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This will tell NextJS to revalidate the data every hour. And the interesting this is, you can do this on the page level as well as the layout level.&lt;/p&gt;

&lt;p&gt;You can also do this per fetch by tweaking the fetch call as follows&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://jsonplaceholder.typicode.com/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="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600&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;And that is it!&lt;/p&gt;

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

&lt;p&gt;It takes a while to wrap your head around all this, but this is what NextJS does so well and one of the biggest plus points about it, and once you get a hold of it, it's really powerful.&lt;/p&gt;

&lt;p&gt;You can find all the code over here&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kavinvalli/data-fetching-next13" rel="noopener noreferrer"&gt;https://github.com/kavinvalli/data-fetching-next13&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do give the video a look if you like that more, and stay tuned for more such posts!&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://beta.nextjs.org/docs" rel="noopener noreferrer"&gt;NextJS 13 Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbEt2ZTlmUXk4VFBWYzBZQWZlN1ZDZWFWX3ZHZ3xBQ3Jtc0tub3NFNmZoQ2tqc09SRUM0N2kwYnNQOEF0em4wSW52QzRhXzF5UDRKTTA1NmdjMUNfYTllekRMWHQwcEdoMkV6dk0zVU4wQ3VrWk1zME1nQzNNYlhKUTRRNUxOSXd6Qm9fUjFhbWJrZVUtUGp0cXRLQQ&amp;amp;q=https%3A%2F%2Fbeta.nextjs.org%2Fdocs%2Fdata-fetching%2Ffetching&amp;amp;v=CYCn1I_kvjc" rel="noopener noreferrer"&gt;NextJS 13 Data Fetching Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbk1xRWc3VFpONm1fQTl2b0lOXzNnNUswcVlSd3xBQ3Jtc0trZ0MyRnVvamZ0eDZzMlRHeExRTklYS2xDeU5pVDB4amZTVFQwR0lYUy13eERGcmVrMXNORzNGWVRMNTN0aE9IVjdiaUZaNko0S2tZR2pKUG1WUDJGSFR6MmtCNm05X3IxaU9FRUU3T2lNZFRsZktTcw&amp;amp;q=https%3A%2F%2Fgithub.com%2Facdlite%2Frfcs%2Fblob%2Ffirst-class-promises%2Ftext%2F0000-first-class-support-for-promises.md%23usepromise&amp;amp;v=CYCn1I_kvjc" rel="noopener noreferrer"&gt;&lt;code&gt;use&lt;/code&gt; hook in React&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbnEwZ1BvMjhuNjZDUXozbVc1Um9oSndjLTQyUXxBQ3Jtc0ttV1dWMFpkS2JXdGNCbXJDOTk3RWZDbG9Kb19hSWdLMnFLVjJEWXplcG1XTWUwZnNpN29jMDVPQVhpVGMzV2g4TTg0dWlXYkNaMlhaVEdmakJqODduc05LbFVQWG9MOGlOZVFkbVJTbXdheGkxWTRLRQ&amp;amp;q=https%3A%2F%2Fswr.vercel.app%2F&amp;amp;v=CYCn1I_kvjc" rel="noopener noreferrer"&gt;SWR&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.youtube.com/redirect?event=video_description&amp;amp;redir_token=QUFFLUhqbjlFdGVLVGpvZkUzQk9LRkc3cHZCRWxSZmlkZ3xBQ3Jtc0tuNWFfNWwyaEdHTk5nNk9zZWJwd0Fnd193ajh0dWlVODB3ejd0R3NDRjFLZUxHbEEyU1ljTFEwWWRiTWZvVzRNbnZqQUZfeUVlZkU4RDVpNEVkWXpGbEhhTUJtSDA3VVZSanRCYm40RmFSMkJ4b29yUQ&amp;amp;q=https%3A%2F%2Ftanstack.com%2Fquery%2Fv4&amp;amp;v=CYCn1I_kvjc" rel="noopener noreferrer"&gt;React Query&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Typewind: The magic of Tailwind combined with the safety of Typescript</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Wed, 25 Jan 2023 13:10:20 +0000</pubDate>
      <link>https://dev.to/kavinvalli/typewind-the-magic-of-tailwind-combined-with-the-safety-of-typescript-3ejo</link>
      <guid>https://dev.to/kavinvalli/typewind-the-magic-of-tailwind-combined-with-the-safety-of-typescript-3ejo</guid>
      <description>&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%2Fssnw1yc8fmw5irylnn72.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%2Fssnw1yc8fmw5irylnn72.png" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, the people who've read my previous articles know how much I love type-safety, hence someone who loves the &lt;a href="https://dev.to/kavinvalli/why-i-think-the-t3-stack-is-the-next-big-thing-in-the-js-oh-wait-the-ts-ecosystem-1183"&gt;t3 stack&lt;/a&gt;. Here's &lt;a href="https://typewind.vercel.app" rel="noopener noreferrer"&gt;Typewind&lt;/a&gt;, a &lt;strong&gt;typesafe&lt;/strong&gt; and &lt;strong&gt;zero-runtime&lt;/strong&gt; version of Tailwind CSS, a utility-first CSS framework that can be composed to build any design, directly in your markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Origin
&lt;/h2&gt;

&lt;p&gt;The whole thing started with one tweet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/stolinski/status/1613699772111638530" rel="noopener noreferrer"&gt;https://twitter.com/stolinski/status/1613699772111638530&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%2F5p9wn6xta8djsdgrqt5k.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%2F5p9wn6xta8djsdgrqt5k.png" width="800" height="939"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then &lt;a href="https://twitter.com/colinhacks" rel="noopener noreferrer"&gt;Colin McDonnell&lt;/a&gt; tweeted on what tailwind with type safety and proper autocompletion would look like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/colinhacks/status/1615154756204523521" rel="noopener noreferrer"&gt;https://twitter.com/colinhacks/status/1615154756204523521&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%2F26r5btds9vpty2fi7rhg.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%2F26r5btds9vpty2fi7rhg.png" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mokshitjain.co" rel="noopener noreferrer"&gt;Mokshit&lt;/a&gt;, the creator of Typewind, sent me this tweet and both of us, at first look were having confused thoughts but the more and more we saw it, the more and more we started getting convinced of it. Looks like &lt;a href="https://twitter.com/t3dotgg/status/1615232346231558147?s=20&amp;amp;t=I5tEkOkmymKw31I4_7YT0A" rel="noopener noreferrer"&gt;Theo&lt;/a&gt; had similar thoughts.&lt;/p&gt;

&lt;p&gt;We discussed it for some time and he decided to start working on it. Overnight, he was done with the transpilation part and I was just hovering along with him, looking at the things which were being done understanding only 70% of the things happening.&lt;/p&gt;

&lt;p&gt;I started working on the docs and working a little on the tailwind transformers started getting me interested in build tools (probably something I want to give a try in the future).&lt;/p&gt;

&lt;p&gt;Fast forward to just a few days later, he was done building the package and I was done setting up the docs and the examples and decided to release. However, we had one issue. We couldn't think of a logo. After playing around for hours with different combinations, I thought of a wavy line under wind but said it looked bad and discarded it. Turns out only the font and the structure of the wavy line was bad cause the final version turned out way better.&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%2Fj6wwp8cneqgyzsgi4oo0.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%2Fj6wwp8cneqgyzsgi4oo0.png" alt="Typewind Logo" width="680" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He released it overnight and it got a lot more response than we had expected! So here's about Typewind, and how you can get started with it:&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Zero runtime&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type-safety and auto-completion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CSS docs based on your config&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply variants to multiple styles at once&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No need for additional editor extensions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Catches errors at compile time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typewind, generated type definitions on Tailwind classes custom to your app's &lt;code&gt;tailwind.config.js&lt;/code&gt; after running the &lt;code&gt;npx typewind generate&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Typewind has currently been tested to work with Vite (React) and Next.JS and you can find them in the &lt;a href="https://typewind.vercel.app/docs/examples/vite" rel="noopener noreferrer"&gt;examples&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://typewind.vercel.app/docs/installation" rel="noopener noreferrer"&gt;installation page in the docs&lt;/a&gt; is a very good place to start with Typewind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Install via your favourite package manager (npm/yarn/pnpm).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install typewind

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generate Type Definitions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx typewind generate

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

&lt;/div&gt;



&lt;p&gt;This will go through your &lt;code&gt;tailwind.config.js&lt;/code&gt; and generate types and css docs custom to your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup with Next.JS
&lt;/h3&gt;

&lt;p&gt;After setting up &lt;a href="https://tailwindcss.com/docs/installation" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt;, make the following changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;code&gt;.babelrc&lt;/code&gt; with the following contents:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "presets": ["next/babel"],
  "plugins": ["typewind/babel"]
}

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add transformer to your Tailwind Config
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { typewindTransforms } = require('typewind/transform');

/** @type {import('tailwindcss').Config} \*/
module.exports = {
  content: {
    files: ['./src/**/*.{js,jsx,ts,tsx}'],
    transform: typewindTransforms,
  },
};

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

&lt;/div&gt;



&lt;p&gt;And you're good to go! Just run &lt;code&gt;npm run dev&lt;/code&gt; next time and you should be able to use Typewind inside your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup with Vite
&lt;/h3&gt;

&lt;p&gt;Make the same change in the &lt;code&gt;tailwind.config.js&lt;/code&gt; file as mentioned in the NextJS example, but the babel change has to be done in the &lt;code&gt;vite.config.js&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react({ babel: { plugins: ['typewind/babel'] } })],
});

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

&lt;/div&gt;



&lt;p&gt;And, you'll be done setting up Typewind in your Vite application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;There are a few usage cases, just like in Tailwind and all of them can be found in detail in the documentation, and it would be redundant to write them again in this article. But here's just a trailer to show you what it's capable of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { tw } from 'typewind';

export default function App() {
  return (
    &amp;lt;div
      className={tw.flex.items_center.justify_center.h_screen.bg_white.text_["#333"].dark(tw.bg_black.text_white)}&amp;gt;
      &amp;lt;h1 className={tw.text_xl.sm(tw.text_3xl).md(tw.text_4xl).font_bold}&amp;gt;
        Hello World
      &amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;Hope this gets you interested in getting started with Typewind, and gets you to use it in your next project!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mokshit06/typewind" rel="noopener noreferrer"&gt;https://github.com/mokshit06/typewind&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typewind</category>
      <category>tailwindcss</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Discord bot which shows your private Advent of Code leaderboard</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Sat, 03 Dec 2022 12:31:22 +0000</pubDate>
      <link>https://dev.to/kavinvalli/discord-bot-which-shows-your-private-advent-of-code-leaderboard-58k</link>
      <guid>https://dev.to/kavinvalli/discord-bot-which-shows-your-private-advent-of-code-leaderboard-58k</guid>
      <description>&lt;p&gt;It is December! That means &lt;a href="https://adventofcode.com" rel="noopener noreferrer"&gt;Advent of Code&lt;/a&gt; is here! If you don't know what that is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Advent of Code&lt;/em&gt; is an &lt;a href="https://en.wikipedia.org/wiki/Advent_calendar" rel="noopener noreferrer"&gt;Advent calendar&lt;/a&gt; of small programming puzzles for a variety of skill sets and skill levels that can be solved in &lt;a href="https://github.com/search?q=advent+of+code" rel="noopener noreferrer"&gt;any&lt;/a&gt; programming language you like. People use them as &lt;a href="https://y3l2n.com/2018/05/09/interview-prep-advent-of-code/" rel="noopener noreferrer"&gt;interview&lt;/a&gt; &lt;a href="https://twitter.com/dznqbit/status/1037607793144938497" rel="noopener noreferrer"&gt;prep&lt;/a&gt;, &lt;a href="https://twitter.com/pgoultiaev/status/950805811583963137" rel="noopener noreferrer"&gt;company training&lt;/a&gt;, &lt;a href="https://gitlab.com/imhoffman/fa19b4-mat3006/wikis/home" rel="noopener noreferrer"&gt;university&lt;/a&gt; &lt;a href="https://gribblelab.org/teaching/scicomp2021/index.html" rel="noopener noreferrer"&gt;coursework&lt;/a&gt;, &lt;a href="https://twitter.com/mrdanielklein/status/936267621468483584" rel="noopener noreferrer"&gt;practice&lt;/a&gt; &lt;a href="https://comp215.blogs.rice.edu/" rel="noopener noreferrer"&gt;problems&lt;/a&gt;, a &lt;a href="https://adventofcode.com/leaderboard" rel="noopener noreferrer"&gt;speed contest&lt;/a&gt;, or to &lt;a href="https://www.reddit.com/r/adventofcode/search?q=flair%3Aupping&amp;amp;restrict_sr=on" rel="noopener noreferrer"&gt;challenge each other&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Idea Inspiration
&lt;/h2&gt;

&lt;p&gt;Now, Advent of Code has two kinds of leaderboards. One is the Global Leaderboard where you're competing against the whole world and the other is Private Leaderboards. You can create Private Leaderboards for your class, your club, or a group of friends!&lt;/p&gt;

&lt;p&gt;I am a part of a couple of Private Leaderboards and since all of us were on a discord server, I thought why not create a Discord Bot which shows the leaderboard right on the app? And so, I created &lt;a href="https://github.com/kavinvalli/aoc-private-lb-discord-bot" rel="noopener noreferrer"&gt;this discord bot.&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%2Fwtqs0ocmruzocpae3sh6.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%2Fwtqs0ocmruzocpae3sh6.png" width="658" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;The bot is very easy to set up and get up and running on your server. Follow the instructions on the &lt;a href="https://github.com/kavinvalli/aoc-private-lb-discord-bot#setup" rel="noopener noreferrer"&gt;GitHub README&lt;/a&gt; and you will be up and running in no time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;To deploy the app on an EC2, GCP Instance, etc. use &lt;a href="https://pm2.keymetrics.io/" rel="noopener noreferrer"&gt;pm2&lt;/a&gt; like mentioned &lt;a href="https://github.com/kavinvalli/aoc-private-lb-discord-bot#deployment" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/kavinvalli/aoc-private-lb-discord-bot" rel="noopener noreferrer"&gt;https://github.com/kavinvalli/aoc-private-lb-discord-bot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the GitHub Repository linked above and you will find all the instructions on how to get up and running with the bot.&lt;/p&gt;

&lt;p&gt;Feel free to also point out any &lt;a href="https://github.com/kavinvalli/aoc-private-lb-discord-bot/issues" rel="noopener noreferrer"&gt;issues&lt;/a&gt;, any &lt;a href="https://github.com/kavinvalli/aoc-private-lb-discord-bot/pulls" rel="noopener noreferrer"&gt;PRs&lt;/a&gt; are welcome and be sure to star the repo!&lt;/p&gt;

</description>
      <category>discord</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why I think the t3 stack is the next big thing in the JS... oh wait... the TS ecosystem?</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Sat, 26 Nov 2022 11:44:26 +0000</pubDate>
      <link>https://dev.to/kavinvalli/why-i-think-the-t3-stack-is-the-next-big-thing-in-the-js-oh-wait-the-ts-ecosystem-1183</link>
      <guid>https://dev.to/kavinvalli/why-i-think-the-t3-stack-is-the-next-big-thing-in-the-js-oh-wait-the-ts-ecosystem-1183</guid>
      <description>&lt;p&gt;There is this new stack in the open, the T3 stack, started by Theo, CEO of ping.gg and an ex-Twitch employee. I came across it when I was taking a look at tRPC and was amazed by how efficient, it made me while creating an app. First of all, what is tRPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the T3 Stack?
&lt;/h2&gt;

&lt;p&gt;Quoting the website, &lt;em&gt;"We made create-t3-app to do one thing: Streamline the setup of typesafe Next.js apps WITHOUT compromising modularity"&lt;/em&gt; which is so true. It is a stack which just works out of the box, but is yet so customisable. Just pick what you want to use and get up and running! It consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trpc.io" rel="noopener noreferrer"&gt;tRPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://next-auth.js.org/" rel="noopener noreferrer"&gt;NextAuth.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next.JS
&lt;/h2&gt;

&lt;p&gt;Ever since I gave Next.JS a try, it has been one of my favourite frameworks to use. I have given so many more React frameworks a try, but Next.JS just works for me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Next.js offers a lightly opinionated, heavily optimized approach to creating applications using React. From routing to API definitions to image rendering, we trust Next.js to lead developers toward good decisions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  tRPC
&lt;/h2&gt;

&lt;p&gt;tRPC is one of the best ways, in my opinion to create a fully typesafe API. API Routes allow us to build fullstack routes easier and faster. There are alternatives like GraphQL CodeGen but they essentially are a build step which generate types based on your GraphQL, which is kind of eh. tRPC just allows you to build it without an intermediate step. The following screenshot from the tRPC website just explains why tRPC.&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%2F1jmu2frwfw1itmcqw47l.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%2F1jmu2frwfw1itmcqw47l.png" alt="Why tRPC" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read more about tRPC at &lt;a href="https://trpc.io" rel="noopener noreferrer"&gt;trpc.io&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;For those, who don't know what Tailwind is, I have a blog post on it and how to get started with tailwind &lt;a href="https://livecode247.com/start-with-your-first-tailwind-css-project" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript
&lt;/h2&gt;

&lt;p&gt;TypeScript isn't optional in the T3 stack and it is probably one of the best things. Once you give TypeScript a try, you will not be able to go back to Javascript. You will blow your head off trying to find the right data to pass into a function, or trying to find why and where you have an error in your app because it is the wrong type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Typesafety makes you faster. If youre not convinced, &lt;a href="https://www.youtube.com/watch?v=RmGHnYUqQ4k" rel="noopener noreferrer"&gt;you might be using TypeScript wrong&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prisma
&lt;/h2&gt;

&lt;p&gt;Prisma is one of the best database adapters for TypeScript out there. It just makes it so easy to work with SQL. It generates all the types for you as well which is a big plus point, as it guarantees and continues the T3 Axiom of end-to-end typesafety from your database to your app. It also provides an awesome GUI called the Prisma Studio.&lt;/p&gt;

&lt;h2&gt;
  
  
  NextAuth
&lt;/h2&gt;

&lt;p&gt;Next Auth makes it very easy to plugin authentication into your NextJS application. It comes with many adapters which just work for you out of the box and is very simple to work with Prisma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I recommend the T3 stack?
&lt;/h2&gt;

&lt;p&gt;First of all, type safety. TypeScript was a huge revolution when it came out in 2012 because of this reason. It just make you so much faster and efficient if you start using it right. The autocompletes, the hover documents, the red squiggly lines just make it much much easier to write code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;create-t3-app&lt;/code&gt; makes it easier to manage the &lt;em&gt;modularity and simplivity&lt;/em&gt; in code while starting off. It just doesn't add everything.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everything added to create-t3-app should solve a specific problem that exists within the core technologies included. This means we wont add things like state libraries (zustand, redux) but we will add things like NextAuth.js and integrate Prisma and tRPC for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Resources to get started with the T3 stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://create.t3.gg/en/introduction" rel="noopener noreferrer"&gt;Create T3 App Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=PbjHxIuHduU" rel="noopener noreferrer"&gt;&lt;strong&gt;The BEST Stack For Your Next Project&lt;/strong&gt; Video&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=syEWlxVFUrY" rel="noopener noreferrer"&gt;&lt;strong&gt;Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma, Zod&lt;/strong&gt; Video&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://trpc.io/" rel="noopener noreferrer"&gt;trpc.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2LYM8gf184U" rel="noopener noreferrer"&gt;Chris Bautista: Making typesafe APIs easy with tRPC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/t3-oss/create-t3-app" rel="noopener noreferrer"&gt;create.t3.gg Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://create.t3.gg" rel="noopener noreferrer"&gt;create.t3.gg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>How to implement dark mode using TailwindCSS?</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Wed, 23 Mar 2022 02:41:31 +0000</pubDate>
      <link>https://dev.to/kavinvalli/how-to-implement-dark-mode-using-tailwindcss-2k3j</link>
      <guid>https://dev.to/kavinvalli/how-to-implement-dark-mode-using-tailwindcss-2k3j</guid>
      <description>&lt;p&gt;Dark mode is something which has gained a lot of popularity in the last few years. Many popular websites are also implementing a dark mode on their website. However, dark mode can be a pain to setup if your css isn't well structured. Tailwind makes it very easy and instinctive to implement it. In this article, I'm going to go over how you can implement dark mode using Tailwind CSS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You should have a basic knowledge of Tailwind CSS.&lt;/li&gt;
&lt;li&gt;You should know a little Javascript to understand how the theme toggle works.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Let's start by setting up a tailwind project. You also use bundlers like parcel, and this can also be used with any framework. Just setting up tailwind will be different and you can check that out &lt;a href="https://tailwindcss.com/docs/installation/framework-guides" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I will be using it using &lt;a href="https://npmjs.com" rel="noopener noreferrer"&gt;npm&lt;/a&gt; without any bundler and with just HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create folder
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir dark-mode-tailwindcss
cd dark-mode-tailwindcss
npm init -y

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

&lt;/div&gt;



&lt;p&gt;You will see something like this &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%2F9hrx7njvrrbndm9lnn1b.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%2F9hrx7njvrrbndm9lnn1b.png" alt="Npm Init Output" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Tailwind
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D tailwindcss

&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%2Fbmp50uvcreb7wb34tslx.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%2Fbmp50uvcreb7wb34tslx.png" alt="Install Tailwind" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup Tailwind
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tailwindcss init

&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%2Fsty3yag5rmbq6tuw1v0u.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%2Fsty3yag5rmbq6tuw1v0u.png" alt="Initialize Tailwind Config" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;tailwind.config.js&lt;/code&gt; and make the following change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- content: [],
+ content: ['./**/*.html'],

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

&lt;/div&gt;



&lt;p&gt;This will look for all html files and look for tailwind classes through them. Now, let's create an html file to start off with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch index.html

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to use Dark Mode?
&lt;/h3&gt;

&lt;p&gt;Now, tailwind supports two ways of using Dark Mode. One is &lt;code&gt;prefers-color-scheme&lt;/code&gt; and one is using &lt;code&gt;classes&lt;/code&gt;. So, the way the former works is, if the users system's preferred mode is dark mode then it'll use dark mode else will use light mode. In the class based mode, it will be applied when the &lt;code&gt;dark&lt;/code&gt; class is applied to any element before the current element in the tree. In this article, I'll be using classes just to demonstrate how to toggle between them, but feel free to use any. Not that &lt;code&gt;prefers-color-scheme&lt;/code&gt; mode is used by default. To use &lt;code&gt;class&lt;/code&gt; based mode you need to add the following line in &lt;code&gt;tailwind.config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
+ darkMode: 'class',
   ...
}

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup tailwind css file
&lt;/h3&gt;

&lt;p&gt;Create a src directory with the tailwind css file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p src/css
touch src/css/tailwind.css

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

&lt;/div&gt;



&lt;p&gt;and add the following contents to it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind utilities;
@tailwind components;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup css build commands
&lt;/h3&gt;

&lt;p&gt;In your package.json make the following changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
  "scripts": {
- "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1"
+ "css:build": "tailwindcss -i src/css/tailwind.css -o dist/css/tailwind.css",
+ "css:watch": "tailwindcss -i src/css/tailwind.css -o dist/css/tailwind.css --watch"
  },
...

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

&lt;/div&gt;



&lt;p&gt;And then run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run css:watch

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup html
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8" /&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&amp;gt;
    &amp;lt;link rel="stylesheet" href="./dist/css/tailwind.css" /&amp;gt;
    &amp;lt;title&amp;gt;Tailwind Dark Mode&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;

  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Now, this will be our starting point to the html. I've added the stylesheet which points to the compiled css generated by the Tailwind CLI.&lt;/p&gt;

&lt;p&gt;I'm gonna setup a basic html site like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  &amp;lt;body&amp;gt;
    &amp;lt;div
      class="h-screen w-full bg-gray-100 dark:bg-gray-800 flex justify-center items-center"
    &amp;gt;
      &amp;lt;div class="bg-white text-gray-800 rounded-lg p-4 text-center"&amp;gt;
        &amp;lt;h1 class="text-2xl font-bold"&amp;gt;Tailwind Dark Mode&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;This is a demo of Tailwind CSS Dark Mode.&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;button
        class="absolute bottom-5 right-5 w-10 h-10 rounded-full bg-gray-800 flex justify-center items-center text-white"
        id="theme-toggle"
      &amp;gt;
        &amp;lt;svg
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        &amp;gt;
          &amp;lt;path
            fill-rule="evenodd"
            clip-rule="evenodd"
            d="M12.2256 2.00253C9.59172 1.94346 6.93894 2.9189 4.92893 4.92891C1.02369 8.83415 1.02369 15.1658 4.92893 19.071C8.83418 22.9763 15.1658 22.9763 19.0711 19.071C21.0811 17.061 22.0565 14.4082 21.9975 11.7743C21.9796 10.9772 21.8669 10.1818 21.6595 9.40643C21.0933 9.9488 20.5078 10.4276 19.9163 10.8425C18.5649 11.7906 17.1826 12.4053 15.9301 12.6837C14.0241 13.1072 12.7156 12.7156 12 12C11.2844 11.2844 10.8928 9.97588 11.3163 8.0699C11.5947 6.81738 12.2094 5.43511 13.1575 4.08368C13.5724 3.49221 14.0512 2.90664 14.5935 2.34046C13.8182 2.13305 13.0228 2.02041 12.2256 2.00253ZM17.6569 17.6568C18.9081 16.4056 19.6582 14.8431 19.9072 13.2186C16.3611 15.2643 12.638 15.4664 10.5858 13.4142C8.53361 11.362 8.73568 7.63895 10.7814 4.09281C9.1569 4.34184 7.59434 5.09193 6.34315 6.34313C3.21895 9.46732 3.21895 14.5326 6.34315 17.6568C9.46734 20.781 14.5327 20.781 17.6569 17.6568Z"
            fill="currentColor"
          /&amp;gt;
        &amp;lt;/svg&amp;gt;
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;script src="./src/js/index.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Should show you something like this:&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%2Fkmxx8fpkrvm1ggmfq4mx.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%2Fkmxx8fpkrvm1ggmfq4mx.png" alt="Starting HTML" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm using the &lt;a href="https://npmjs.org/serve" rel="noopener noreferrer"&gt;serve&lt;/a&gt; package by &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; to serve my html. Just run &lt;code&gt;npx serve&lt;/code&gt; from your project directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Javascript
&lt;/h2&gt;

&lt;p&gt;We'll be needing a little bit of javascript to manage the dark mode. Add this in the &lt;code&gt;index.html&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
+ &amp;lt;script src="./src/js/index.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
...

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

&lt;/div&gt;



&lt;p&gt;Now, create an index.js file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir src/js
touch src/js/index.js

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

&lt;/div&gt;



&lt;p&gt;Add the following to the &lt;code&gt;index.js&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const themeToggleButton = document.getElementById("theme-toggle");

const MOON_SVG = `&amp;lt;svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"&amp;gt;&amp;lt;path fill-rule="evenodd" clip-rule="evenodd" d="M12.2256 2.00253C9.59172 1.94346 6.93894 2.9189 4.92893 4.92891C1.02369 8.83415 1.02369 15.1658 4.92893 19.071C8.83418 22.9763 15.1658 22.9763 19.0711 19.071C21.0811 17.061 22.0565 14.4082 21.9975 11.7743C21.9796 10.9772 21.8669 10.1818 21.6595 9.40643C21.0933 9.9488 20.5078 10.4276 19.9163 10.8425C18.5649 11.7906 17.1826 12.4053 15.9301 12.6837C14.0241 13.1072 12.7156 12.7156 12 12C11.2844 11.2844 10.8928 9.97588 11.3163 8.0699C11.5947 6.81738 12.2094 5.43511 13.1575 4.08368C13.5724 3.49221 14.0512 2.90664 14.5935 2.34046C13.8182 2.13305 13.0228 2.02041 12.2256 2.00253ZM17.6569 17.6568C18.9081 16.4056 19.6582 14.8431 19.9072 13.2186C16.3611 15.2643 12.638 15.4664 10.5858 13.4142C8.53361 11.362 8.73568 7.63895 10.7814 4.09281C9.1569 4.34184 7.59434 5.09193 6.34315 6.34313C3.21895 9.46732 3.21895 14.5326 6.34315 17.6568C9.46734 20.781 14.5327 20.781 17.6569 17.6568Z" fill="currentColor" /&amp;gt;&amp;lt;/svg&amp;gt;`;
const SUN_SVG = `&amp;lt;svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"&amp;gt;&amp;lt;path fill-rule="evenodd" clip-rule="evenodd" d="M12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16ZM12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18Z" fill="currentColor" /&amp;gt;&amp;lt;path fill-rule="evenodd" clip-rule="evenodd" d="M11 0H13V4.06189C12.6724 4.02104 12.3387 4 12 4C11.6613 4 11.3276 4.02104 11 4.06189V0ZM7.0943 5.68018L4.22173 2.80761L2.80752 4.22183L5.6801 7.09441C6.09071 6.56618 6.56608 6.0908 7.0943 5.68018ZM4.06189 11H0V13H4.06189C4.02104 12.6724 4 12.3387 4 12C4 11.6613 4.02104 11.3276 4.06189 11ZM5.6801 16.9056L2.80751 19.7782L4.22173 21.1924L7.0943 18.3198C6.56608 17.9092 6.09071 17.4338 5.6801 16.9056ZM11 19.9381V24H13V19.9381C12.6724 19.979 12.3387 20 12 20C11.6613 20 11.3276 19.979 11 19.9381ZM16.9056 18.3199L19.7781 21.1924L21.1923 19.7782L18.3198 16.9057C17.9092 17.4339 17.4338 17.9093 16.9056 18.3199ZM19.9381 13H24V11H19.9381C19.979 11.3276 20 11.6613 20 12C20 12.3387 19.979 12.6724 19.9381 13ZM18.3198 7.0943L21.1923 4.22183L19.7781 2.80762L16.9056 5.6801C17.4338 6.09071 17.9092 6.56608 18.3198 7.0943Z" fill="currentColor" /&amp;gt;&amp;lt;/svg&amp;gt;`;

let theme = localStorage.getItem("T_SITE_THEME") || "light";
theme === "light" ? setLightTheme() : setDarkTheme();

function setDarkTheme() {
  document.body.classList.add("dark");
  themeToggleButton.innerHTML = SUN_SVG;
  localStorage.setItem("T_SITE_THEME", "dark");
  theme = "dark";
}

function setLightTheme() {
  document.body.classList.remove("dark");
  themeToggleButton.innerHTML = MOON_SVG;
  localStorage.setItem("T_SITE_THEME", "light");
  theme = "light";
}

themeToggleButton.addEventListener("click", () =&amp;gt; {
  if (theme === "light") {
    setDarkTheme();
  } else {
    setLightTheme();
  }
});

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

&lt;/div&gt;



&lt;p&gt;Ok, so let's go over this file and what it is doing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On line 1 - We're querying the toggle theme button from the dom&lt;/li&gt;
&lt;li&gt;On line 3 and 4 - We're setting two constants which correspond to a Moon SVG and a Sun SVG. This will be shown inside the toggle button.&lt;/li&gt;
&lt;li&gt;On line 5 - I'm setting a theme variable. Now, I'm querying from the localStorage the site's theme. If it exists, that means the user has already visited the website before and they have some preference. If not, set it to light by default. You can use dark if you want.&lt;/li&gt;
&lt;li&gt;On line 6 - Based on the theme, i'm either setting dark mode or light mode.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;setDarkTheme&lt;/code&gt; function - I'm first of all, adding the &lt;code&gt;dark&lt;/code&gt; class to the body. This is essential for tailwind to understand that the user is using dark mode. Then, I'm changing the SVG inside the toggle button to that of a Sun. After that, we're resetting the value of our theme in the localStorage to dark and we're also resetting the value of the &lt;code&gt;theme&lt;/code&gt; variable to dark.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;setLightTheme&lt;/code&gt; function - We're doing everything opposite to that in the &lt;code&gt;setDarkTheme&lt;/code&gt; function.&lt;/li&gt;
&lt;li&gt;From lines 17 to 23 - We're handling the &lt;code&gt;click&lt;/code&gt; event on the toggle theme button and setting dark mode or light mode accordingly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tailwind &lt;code&gt;dark&lt;/code&gt; variant.
&lt;/h2&gt;

&lt;p&gt;Now, how do we tell Tailwind to use which class in dark mode and which class in light mode? We do that using the &lt;code&gt;dark&lt;/code&gt; variant which it provides us. For example, in the first div element on the page (just below the body tag), add this class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- &amp;lt;div class="h-screen w-full bg-gray-100 flex justify-center items-center"&amp;gt;
+ &amp;lt;div class="h-screen w-full bg-gray-100 dark:bg-gray-800 flex justify-center items-center"&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;And checkout what happens when you refresh the site on the browser and click on the toggle theme button!&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%2Fjgocgaclionjmohsbmdn.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%2Fjgocgaclionjmohsbmdn.png" alt="First view of dark mode" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The background color changes.&lt;/li&gt;
&lt;li&gt;If you inspect the body element, you will see a &lt;code&gt;dark&lt;/code&gt; class on it.&lt;/li&gt;
&lt;li&gt;The localStorage &lt;code&gt;T_SITE_THEME&lt;/code&gt; value changes to &lt;code&gt;dark&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The svg inside the toggle theme button changes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, click on the button again:&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%2F6l27xmlkgdxzy68zkp1u.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%2F6l27xmlkgdxzy68zkp1u.png" alt="Light Mode Again" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's make a few changes in out html now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- &amp;lt;div class="bg-white text-gray-800 rounded-lg p-4 text-center"&amp;gt;
+ &amp;lt;div class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 rounded-lg p-4 text-center"&amp;gt;


- &amp;lt;button class="absolute bottom-5 right-5 w-10 h-10 rounded-full bg-gray-800 flex justify-center items-center text-white" id="theme-toggle"&amp;gt;
+ &amp;lt;button class="absolute bottom-5 right-5 w-10 h-10 rounded-full bg-gray-800 dark:bg-gray-900 flex justify-center items-center text-white" id="theme-toggle"&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Now your html should look 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;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8" /&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&amp;gt;
    &amp;lt;link rel="stylesheet" href="dist/css/tailwind.css" /&amp;gt;
    &amp;lt;title&amp;gt;Tailwind Dark Mode&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div
      class="h-screen w-full bg-gray-100 dark:bg-gray-800 flex justify-center items-center"
    &amp;gt;
      &amp;lt;div
        class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 rounded-lg p-4 text-center"
      &amp;gt;
        &amp;lt;h1 class="text-2xl font-bold"&amp;gt;Tailwind Dark Mode&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;This is a demo of Tailwind CSS Dark Mode.&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;button
        class="absolute bottom-5 right-5 w-10 h-10 rounded-full bg-gray-800 dark:bg-gray-900 flex justify-center items-center text-white"
        id="theme-toggle"
      &amp;gt;
        &amp;lt;svg
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        &amp;gt;
          &amp;lt;path
            fill-rule="evenodd"
            clip-rule="evenodd"
            d="M12.2256 2.00253C9.59172 1.94346 6.93894 2.9189 4.92893 4.92891C1.02369 8.83415 1.02369 15.1658 4.92893 19.071C8.83418 22.9763 15.1658 22.9763 19.0711 19.071C21.0811 17.061 22.0565 14.4082 21.9975 11.7743C21.9796 10.9772 21.8669 10.1818 21.6595 9.40643C21.0933 9.9488 20.5078 10.4276 19.9163 10.8425C18.5649 11.7906 17.1826 12.4053 15.9301 12.6837C14.0241 13.1072 12.7156 12.7156 12 12C11.2844 11.2844 10.8928 9.97588 11.3163 8.0699C11.5947 6.81738 12.2094 5.43511 13.1575 4.08368C13.5724 3.49221 14.0512 2.90664 14.5935 2.34046C13.8182 2.13305 13.0228 2.02041 12.2256 2.00253ZM17.6569 17.6568C18.9081 16.4056 19.6582 14.8431 19.9072 13.2186C16.3611 15.2643 12.638 15.4664 10.5858 13.4142C8.53361 11.362 8.73568 7.63895 10.7814 4.09281C9.1569 4.34184 7.59434 5.09193 6.34315 6.34313C3.21895 9.46732 3.21895 14.5326 6.34315 17.6568C9.46734 20.781 14.5327 20.781 17.6569 17.6568Z"
            fill="currentColor"
          /&amp;gt;
        &amp;lt;/svg&amp;gt;
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;script src="./src/js/index.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;and the site like this:&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%2Ffz7zjetekjyhhpw8mazc.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%2Ffz7zjetekjyhhpw8mazc.png" alt="Final Dark Mode" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>tailwindcss</category>
      <category>darkmode</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Beginner's guide to useEffect hook in React</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Sun, 13 Mar 2022 09:35:33 +0000</pubDate>
      <link>https://dev.to/kavinvalli/beginners-guide-to-useeffect-hook-in-react-g53</link>
      <guid>https://dev.to/kavinvalli/beginners-guide-to-useeffect-hook-in-react-g53</guid>
      <description>&lt;p&gt;A few days ago, I wrote an &lt;a href="https://dev.to/kavinvalli/react-hooks-usestate-1i5d-temp-slug-8841584"&gt;article&lt;/a&gt; on how to use the &lt;code&gt;useState&lt;/code&gt; hook. Another important hook provided by React is the &lt;code&gt;useEffect&lt;/code&gt; hook. Now, if you've used React Class based Components, then useEffect will help you replace functions like &lt;code&gt;componentDidMount&lt;/code&gt;, &lt;code&gt;componentDidUpdate&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of ReactJS&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;useEffect&lt;/strong&gt; takes in two arguments. A function, and an array of dependencies like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(function, [dependencies])

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

&lt;/div&gt;



&lt;p&gt;Let's start with the function argument&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Argument
&lt;/h3&gt;

&lt;p&gt;Let's use the example I used in the &lt;a href="https://dev.to/kavinvalli/react-hooks-usestate-1i5d-temp-slug-8841584"&gt;&lt;code&gt;useState&lt;/code&gt; article.&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";

function App() {
  const [count, setCount] = useState(1);

  function incrementCount() {
    setCount(count + 1);
  }
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Hello, World&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={incrementCount}&amp;gt;Increase counter&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;

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

&lt;/div&gt;



&lt;p&gt;Will give you something like this: &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%2Fi7nuho202kxifmicucup.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%2Fi7nuho202kxifmicucup.png" alt="Starting App" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now make these code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- import { useState } from "react";
+ import { useState, useEffect } from "react";
...
    const [count, setCount] = useState(1);
+ useEffect(() =&amp;gt; {
+ console.log("useEffect running");
+ });
...

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

&lt;/div&gt;



&lt;p&gt;Now, go to the browser, refresh the page, open up dev tools and move to console window&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%2Fjjp0bso7zxlrg58oc4fq.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%2Fjjp0bso7zxlrg58oc4fq.png" alt="useEffect first" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks like it's working! But WAIT. Try clicking on the button and notice what happens:&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%2Fd5gwyjcw8rh1ge2hjoqw.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%2Fd5gwyjcw8rh1ge2hjoqw.png" alt="useEffect on re-render" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The useEffect ran again. This is because by default, useEffect runs on every single render. When you update the state, you're basically re-rendering the component, so the useEffect runs again. This might be useful in some cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Replacement for &lt;code&gt;componentDidMount&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;What if you want to run it only when the component mounts for the first time (like componentDidMount did). This is where the &lt;code&gt;dependency&lt;/code&gt; argument comes into play. Make this change&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- useEffect(() =&amp;gt; {
- console.log("useEffect running");
- });
+ useEffect(() =&amp;gt; {
+ console.log("useEffect running");
+ }, []);

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

&lt;/div&gt;



&lt;p&gt;You're passing in an empty array of dependencies. This basically means, run the useEffect loop only on first render.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is however still one difference between this and &lt;code&gt;componentDidMount&lt;/code&gt;. &lt;code&gt;useEffect(fn, [])&lt;/code&gt; runs after the first render to the DOM whereas &lt;code&gt;componentDidMount&lt;/code&gt; runs after "mounting" the component but before it is actually rendered(shown) in the DOM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Run depending on a value
&lt;/h3&gt;

&lt;p&gt;What if you want to run useEffect when a certain value changes. For eg. add this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const [count, setCount] = useState(1);
+ const [isDark, setIsDark] = useState(false);
...
   &amp;lt;button onClick={incrementCount}&amp;gt;Increase counter&amp;lt;/button&amp;gt;
+ &amp;lt;button onClick={() =&amp;gt; setIsDark(!isDark)}&amp;gt;Toggle isDark&amp;lt;/button&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Let's take that counter &lt;code&gt;p&lt;/code&gt; tag to a different component for demonstration purposes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Counter({count}) {
  return &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;;
}


...
&amp;lt;div&amp;gt;
   &amp;lt;h1&amp;gt;Hello, World&amp;lt;/h1&amp;gt;
- &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;
+ &amp;lt;Counter count={count} /&amp;gt;
...

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

&lt;/div&gt;



&lt;p&gt;Now say, on the &lt;code&gt;Counter&lt;/code&gt; function, you want to take the &lt;code&gt;isDark&lt;/code&gt; prop and every time it changes we want to send out a console.log saying that the &lt;code&gt;isDark&lt;/code&gt; prop has changed. First let's take the prop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- &amp;lt;Counter count={count} /&amp;gt;
+ &amp;lt;Counter count={count} isDark={isDark} /&amp;gt;
...
- function Counter({ count }) {
+ function Counter({ count, isDark }) {

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

&lt;/div&gt;



&lt;p&gt;Now, if we add a useEffect hook 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;  function Counter({ count, isDark }) {
+ useEffect(() =&amp;gt; {
+ console.log("isDark value changed")
+ }, [isDark])

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

&lt;/div&gt;



&lt;p&gt;Now, you will see a console.log everytime you click on the &lt;code&gt;Toggle isDark&lt;/code&gt; button but notice that if you click on &lt;code&gt;Increase Counter&lt;/code&gt;, you won't see a console.log because now the useEffect runs only when the isDark value changes and not on every render like we saw before!&lt;/p&gt;

&lt;p&gt;So, that's it for this article. Hope you take something back from this article. There's a little more to useEffect like cleaning up functions which you can read about &lt;a href="https://reactjs.org/docs/hooks-reference.html#cleaning-up-an-effect" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The final code for this is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";

function App() {
  const [count, setCount] = useState(1);
  const [isDark, setIsDark] = useState(false);

  useEffect(() =&amp;gt; {
    console.log("useEffect running");
  }, []);

  function incrementCount() {
    setCount(count + 1);
  }
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Hello, World&amp;lt;/h1&amp;gt;
      &amp;lt;Counter count={count} isDark={isDark} /&amp;gt;
      &amp;lt;button onClick={incrementCount}&amp;gt;Increase counter&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setIsDark(!isDark)}&amp;gt;Toggle isDark&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function Counter({ count, isDark }) {
  useEffect(() =&amp;gt; {
    console.log("isDark value changed");
  }, [isDark]);
  return &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;;
}

export default App;

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

&lt;/div&gt;



</description>
      <category>react</category>
      <category>hooks</category>
    </item>
    <item>
      <title>Beginner's guide to useState hook in React</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Thu, 10 Mar 2022 10:07:53 +0000</pubDate>
      <link>https://dev.to/kavinvalli/beginners-guide-to-usestate-hook-in-react-1fm2</link>
      <guid>https://dev.to/kavinvalli/beginners-guide-to-usestate-hook-in-react-1fm2</guid>
      <description>&lt;p&gt;A key component of a web application is the &lt;strong&gt;state&lt;/strong&gt;. Taken directly from the beta(new) version of the ReactJS Docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of state as the minimal set of changing data that your app needs to remember. For example, if you’re building a shopping list, you can store the items as an array in state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, how do we manage state inside a React Component? So, in this tutorial we'll be talking just about that!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of ReactJS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are React Hooks?
&lt;/h2&gt;

&lt;p&gt;First, let's start with what is a React Hook. The beta docs of ReactJS says the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Functions starting with use are called Hooks. useState is a built-in Hook provided by React. You can find other built-in Hooks in the &lt;a href="https://beta.reactjs.org/apis" rel="noopener noreferrer"&gt;React API reference&lt;/a&gt;. You can also write your own Hooks by combining the existing ones. Hooks are more restrictive than regular functions. You can only call Hooks at the top level of your components (or other Hooks). If you want to useState in a condition or a loop, extract a new component and put it there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So basically, if you know a little history about React, you would know that React used to be mainly comprised of something called Class-Based Components. But now, the community is starting to move to Function-Based Components. Now, React Hooks allow the functional components to have access to state and other React Features.&lt;/p&gt;

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

&lt;p&gt;Create a project using the following command&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="nx"&gt;npx&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&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;app&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;hooks&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;tutorial&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then edit your &lt;code&gt;src/App.js&lt;/code&gt; to look like this&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="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="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="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, World&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; // this will update based on the state after this tutorial
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increase counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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;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;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;useState&lt;/code&gt; hook
&lt;/h2&gt;

&lt;p&gt;Now, the way the &lt;code&gt;useState&lt;/code&gt; hook is used in React is very interesting. In a conventional, class based component you'd do something like this&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="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;and then access it via &lt;code&gt;this.state&lt;/code&gt;. But using the &lt;code&gt;useState&lt;/code&gt; hook you'd do something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ import { useState } from "react"
&lt;/span&gt;  function App() {
&lt;span class="gi"&gt;+ const [count, setCount] = useState(1);
&lt;/span&gt;    return (
&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the useState hook returns two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first variable is the actual state variable. For eg. &lt;strong&gt;count&lt;/strong&gt; in this case is &lt;strong&gt;1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setCount&lt;/code&gt; is a function which you can use to change the value of the &lt;code&gt;count&lt;/code&gt; state.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Using the count state variable to show data
&lt;/h2&gt;

&lt;p&gt;First, update the hardcoded value of 1 with the count variable like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;       &amp;lt;h1&amp;gt;Hello, World&amp;lt;/h1&amp;gt;
&lt;span class="gd"&gt;- &amp;lt;p&amp;gt;1&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;
&lt;/span&gt;       &amp;lt;button&amp;gt;Increase counter&amp;lt;/button&amp;gt;
&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using setCount to update state
&lt;/h2&gt;

&lt;p&gt;Now to make this work, let's make the click of the button increase the &lt;strong&gt;count&lt;/strong&gt; variable by 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;       &amp;lt;p&amp;gt;{count}&amp;lt;/p&amp;gt;
&lt;span class="gd"&gt;- &amp;lt;button&amp;gt;Increase counter&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increase counter&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using previous state to update state
&lt;/h3&gt;

&lt;p&gt;Now, let's try something. Change the button line to the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increase counter&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+ &amp;lt;button onClick={incrementCount}&amp;gt;Increase counter&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;  const [count, setCount] = useState(1);
&lt;span class="gi"&gt;+ function incrementCount() {
+ setCount(count + 1);
+ setCount(count + 1);
+ setCount(count + 1);
+ }
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this will give you an issue. Straight from the docs again (little modified according to our app):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is because calling the set function does not update the &lt;code&gt;count&lt;/code&gt; state variable in the already running code. So each &lt;code&gt;setCount(count + 1)&lt;/code&gt; call becomes &lt;code&gt;setCount(2)&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To fix this issue, you can reference the previous state and then update the current state using that. So change your code like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- function incrementCount() {
- setCount(count + 1);
- setCount(count + 1);
- setCount(count + 1);
- }
&lt;/span&gt;&lt;span class="gi"&gt;+ function incrementCount() {
+ setCount((prevCount) =&amp;gt; prevCount + 1);
+ setCount((prevCount) =&amp;gt; prevCount + 1);
+ setCount((prevCount) =&amp;gt; prevCount + 1);
+ }
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, you get the &lt;code&gt;prevCount&lt;/code&gt; argument and increment the current state according to that and this should work!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This is obviously not a real life scenario. To increment by 3, you'd probably do something like &lt;code&gt;setCount(count+3)&lt;/code&gt; but it's good to know when you can use the previous state variable as a reference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is it for this tutorial! You final code should look like this:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&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="p"&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;incrementCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevCount&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;prevCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevCount&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;prevCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevCount&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;prevCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="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="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, World&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Increase counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&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;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;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Deploying a static HTML and CSS site using Github Pages</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Mon, 07 Mar 2022 13:45:16 +0000</pubDate>
      <link>https://dev.to/kavinvalli/deploying-a-static-html-and-css-site-using-github-pages-1ldb</link>
      <guid>https://dev.to/kavinvalli/deploying-a-static-html-and-css-site-using-github-pages-1ldb</guid>
      <description>&lt;p&gt;The next step after creating a website, is deploying it to make it available to the whole world. If your site is static, and doesn't use any backend then it is pretty straightforward to deploy your app. In this article, I'm gonna talk about how to deploy a static HTML and CSS site using Github Pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Register at Github
&lt;/h2&gt;

&lt;p&gt;First of all create an account at &lt;a href="https://github.com" rel="noopener noreferrer"&gt;Github&lt;/a&gt;. Github is a Git repository hosting service which is owned by Microsoft. It provides a great feature called &lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;Github Pages&lt;/a&gt; and can be used to deploy static sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Github Repository
&lt;/h2&gt;

&lt;p&gt;After registering, click on the button which says &lt;strong&gt;New&lt;/strong&gt; on the top left of the page. &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%2Fz8ooxli3vtdtdfrmu8pb.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%2Fz8ooxli3vtdtdfrmu8pb.png" alt="Create Repository" width="318" height="107"&gt;&lt;/a&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%2Fyirt6j35qnzchjjk6lpx.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%2Fyirt6j35qnzchjjk6lpx.png" alt="Create repository input repo name" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Upload files
&lt;/h2&gt;

&lt;p&gt;If you know git, you're welcome to push your files to Github. Else, no worries, you can use Github's file upload feature like so:&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%2Fsx1ikvkj9kg51i5kjhpt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx1ikvkj9kg51i5kjhpt.gif" alt="Upload files to Github" width="600" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Last step is to enable Github Pages like so:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click on Settings &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%2F22e0ohyemzc2jz21w700.gif" alt="Enable Github Pages" width="600" height="321"&gt;
&lt;/li&gt;
&lt;li&gt;Click on Pages &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%2Fk9o6j9j0yv9t2l4glfam.png" alt="Screenshot 2022-03-07 at 19.12.05.png" width="356" height="688"&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Branch&lt;/strong&gt; and choose &lt;code&gt;master&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;This might be &lt;code&gt;main&lt;/code&gt; depending on the default branch you're working on&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Click on the button on the right of &lt;strong&gt;Branch&lt;/strong&gt; and choose &lt;code&gt;/ (root)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Save&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then wait for some time and then refresh. Wait till you see a banner which says something like this: &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%2Fer7oyq9dw5dha777sp6z.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%2Fer7oyq9dw5dha777sp6z.png" alt="Banner which says site's published" width="788" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there it is! You've deployed your site using Github Pages. For example, you can view the sample deployment &lt;a href="https://kavinvalli.github.io/gh-pages-tutorial/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;You can find the sample github repository in the example here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kavinvalli/gh-pages-tutorial" rel="noopener noreferrer"&gt;https://github.com/kavinvalli/gh-pages-tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>deployment</category>
    </item>
    <item>
      <title>I built a Link shortener using Remix and here's my experience!</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Sat, 05 Mar 2022 15:24:55 +0000</pubDate>
      <link>https://dev.to/kavinvalli/i-built-a-link-shortener-using-remix-and-heres-my-experience-52op</link>
      <guid>https://dev.to/kavinvalli/i-built-a-link-shortener-using-remix-and-heres-my-experience-52op</guid>
      <description>&lt;p&gt;A few days ago, I decided to try out &lt;a href="https://remix.run" rel="noopener noreferrer"&gt;RemixJS&lt;/a&gt; and tried building a link shortener using it... cause if I create one more Todo List app, I'll lose my mind. Here's my experience of using Remix till now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Remix?
&lt;/h2&gt;

&lt;p&gt;Well, let me start with what Remix is. If you've used ReactJS before, you'd most probably have come across &lt;a href="https://reactrouterdotcom.fly.dev/docs/en/v6" rel="noopener noreferrer"&gt;React Router&lt;/a&gt;. Around a couple years ago, the founders of React Router decided to create a React framework on top of React Router. It originally needed a license, but last year, they decided to go open source! So now, it is something anyone can access.&lt;/p&gt;

&lt;h2&gt;
  
  
  More about Remix?
&lt;/h2&gt;

&lt;p&gt;I started following &lt;a href="https://hashnode.com/@kentcdodds" rel="noopener noreferrer"&gt;Kent C. Dodds&lt;/a&gt;, who is a part of the remix team, and he has a lot of livestreams where he talks about remix, and has a couple videos which really pushed me to try out remix. I highly recommend subscribing to his &lt;a href="https://www.youtube.com/c/KentCDodds-vids" rel="noopener noreferrer"&gt;Youtube Channel&lt;/a&gt; and he has an amazing &lt;a href="https://kentcdodds.com" rel="noopener noreferrer"&gt;Website&lt;/a&gt; also built using remix. It's amazing if you go through it, and you can find a really good video on it by Kent &lt;a href="https://youtu.be/owOZMwNPAyc" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Link shortener
&lt;/h2&gt;

&lt;p&gt;I decided to try Remix out by creating a Link shortener, because that was something simple yet I could experiment with concepts like authentication, data fetching and all that fancy stuff. You can find the code &lt;a href="https://github.com/kavinvalli/remix-url-shortener" rel="noopener noreferrer"&gt;here&lt;/a&gt;. First, I went through the &lt;a href="https://remix.run/docs/en/v1/tutorials/blog" rel="noopener noreferrer"&gt;tutorials&lt;/a&gt; on Remix's docs which is a really good resource on starting with remix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;p&gt;Then, I started off and decided to use Github for authentication. Now, I didn't want to implement Github OAuth by myself and didn't want to go through the work of having to manage tokens in the app, so I decided to use &lt;a href="https://github.com/sergiodxa/remix-auth" rel="noopener noreferrer"&gt;Remix Auth&lt;/a&gt;. It works really really well with Remix and has &lt;a href="https://github.com/sergiodxa/remix-auth/discussions/111" rel="noopener noreferrer"&gt;support&lt;/a&gt; for a lot of strategies). It took me a little while to get started with it cause, it doesn't really have good docs at the time but the examples were helpful. Now, the docs have improved a lot and you should be good to go pretty soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Concepts
&lt;/h3&gt;

&lt;p&gt;The Jokes tutorial covered most of the concepts I needed to build the url shortener. So, it didn't take me too long to complete the app. All the concepts, including db interaction, data fetching, form validation and submission was already stuff I'd read about in the tutorial so I would recommend going through that to get started with Remix.&lt;/p&gt;

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

&lt;p&gt;In the end, I had a great time getting started with Remix and I think it's definitely something I'll use more in the future.&lt;/p&gt;

&lt;p&gt;Make sure to star the repo below and would love to know your experience with Remix after you give it a go in the comments! You're welcome to use the shortener for your use!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kavinvalli/remix-url-shortener" rel="noopener noreferrer"&gt;https://github.com/kavinvalli/remix-url-shortener&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Start a web server with Node.JS and Express</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Thu, 03 Mar 2022 04:48:55 +0000</pubDate>
      <link>https://dev.to/kavinvalli/start-a-web-server-with-nodejs-and-express-542l</link>
      <guid>https://dev.to/kavinvalli/start-a-web-server-with-nodejs-and-express-542l</guid>
      <description>&lt;p&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.JS&lt;/a&gt; and &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt; are two of the most used technologies in the web development world right now. It powers some big sites like Paypal, Wall Street Journal, Shutterstock and a lot more.&lt;/p&gt;

&lt;p&gt;Getting started with Node.JS and Express is very easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You should have Node.JS installed for this tutorial. If not, visit &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;https://nodejs.org/en/&lt;/a&gt; and download the &lt;strong&gt;LTS Version&lt;/strong&gt;. This will also install &lt;a href="https://nodejs.org/en/knowledge/getting-started/npm/what-is-npm/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; which is a widely used package manager for Node.JS.&lt;/li&gt;
&lt;li&gt;You're also expected to have a basic knowledge of Javascript and Node.JS.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;First, let's start off with creating a Node.JS project/directory. You can run the following two commands on the the terminal. Alternatively, you can create a folder from your file manager and open it in VS Code or any other code editor of your choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir node-express-tutorial
cd node-express-tutorial
code . # for Visual Studio Code users

&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%2Fv8dan99ojq7n96st3qgh.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%2Fv8dan99ojq7n96st3qgh.png" alt="Screenshot 2022-03-03 at 09.23.16.png" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the folder to use npm
&lt;/h2&gt;

&lt;p&gt;Run the following in the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init

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

&lt;/div&gt;



&lt;p&gt;You will be prompted with a few questions. You can press enter through most of them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Alternatively, you can run &lt;code&gt;npm init -y&lt;/code&gt; if you want to skip through all the questions with the default value.&lt;/p&gt;
&lt;/blockquote&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%2Fpvqlnendq59wink15rib.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvqlnendq59wink15rib.gif" alt="npminit.gif" width="600" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with the coding part
&lt;/h2&gt;

&lt;p&gt;So, start with creating a file named &lt;code&gt;index.js&lt;/code&gt;. You can name it anything, just make sure you end it with &lt;code&gt;.js&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Conventionally, the file is named &lt;code&gt;index.js&lt;/code&gt;, &lt;code&gt;server.js&lt;/code&gt; or &lt;code&gt;app.js&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Installing express
&lt;/h2&gt;

&lt;p&gt;Like most NodeJS packages, you can install express using npm. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install express

&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%2Fa823ye3psmcz4zpy152y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa823ye3psmcz4zpy152y.gif" alt="npmiexpress.gif" width="600" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will add express as a &lt;strong&gt;dependency&lt;/strong&gt; in your &lt;code&gt;package.json&lt;/code&gt; and also install it in your &lt;code&gt;node_modules&lt;/code&gt; folder.&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%2F2s6iw5iuoadb4j00iqfu.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%2F2s6iw5iuoadb4j00iqfu.png" alt="Screenshot 2022-03-03 at 09.28.32.png" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using express
&lt;/h2&gt;

&lt;p&gt;In your &lt;code&gt;index.js&lt;/code&gt; file, write the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express")

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

&lt;/div&gt;



&lt;p&gt;If you've used Node.JS before, this should look familiar. This line basically imports the express package. Now, to use express, you need to instantiate the imported function. So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require("express")
const app = express() // add this line

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

&lt;/div&gt;



&lt;p&gt;Now, you can use the app variable to start the server like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.listen(3000, () =&amp;gt; {
    console.log(`🚀 Server started on port 3000`)
}

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

&lt;/div&gt;



&lt;p&gt;You've basically already created a web server. You can run the app by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node index.js

&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%2Fob3wexi7jdslrl5fm10v.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob3wexi7jdslrl5fm10v.gif" alt="nodeindex.js.gif" width="600" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you get something like in the above gif, you're good to go to the next step!&lt;/p&gt;

&lt;h2&gt;
  
  
  Routes
&lt;/h2&gt;

&lt;p&gt;So now, we've started an express server but it doesn't know what it has to do when we're visiting the &lt;code&gt;/&lt;/code&gt; route. Hence we get the error:&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%2Fjxjamjft5unm5ibdbyn9.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%2Fjxjamjft5unm5ibdbyn9.png" alt="Screenshot 2022-03-03 at 09.54.40.png" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this, add the following line of code before calling the &lt;code&gt;app.listen&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/', (req, res) =&amp;gt; {
    return res.send("Hello, World")
})

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

&lt;/div&gt;



&lt;p&gt;Let's go through this code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We call the &lt;code&gt;app.get&lt;/code&gt; function. This takes in two parameters:

&lt;ol&gt;
&lt;li&gt;A route: The route on which you want to run this function. In this case we're using the &lt;code&gt;/&lt;/code&gt; route.&lt;/li&gt;
&lt;li&gt;A callback function: The second parameter is a callback function with the &lt;code&gt;request&lt;/code&gt; and &lt;code&gt;response&lt;/code&gt; parameters which express provides us with. The &lt;code&gt;res&lt;/code&gt;(response) gives us a send function with which we can send back a text response to the browser. &lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Now, we need to restart the NodeJS server running. Go to the terminal where you had run &lt;code&gt;node index.js&lt;/code&gt; and then hit &lt;code&gt;Control-C&lt;/code&gt;. And then restart by typing &lt;code&gt;node index.js&lt;/code&gt; again like so:&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%2Ff1xufsbrzgtsgmt8ngl8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1xufsbrzgtsgmt8ngl8.gif" alt="restartnodejsserver.gif" width="600" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;BONUS: Restarting the node server repeatedly becomes very annoying. To deal with this, there's a package called &lt;code&gt;nodemon&lt;/code&gt; which you can install and setup. For detailed instructions visit: &lt;a href="https://livecode247.com/how-to-add-auto-reload-to-your-node-js-app" rel="noopener noreferrer"&gt;https://livecode247.com/how-to-add-auto-reload-to-your-node-js-app&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, refresh the page on the browser and you should see this:&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%2F86so5zbvld2p0z3skorw.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%2F86so5zbvld2p0z3skorw.png" alt="Screenshot 2022-03-03 at 10.08.38.png" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the final step, you can refactor the port number 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;const port = process.env.PORT || 3000;
app.listen(port, () =&amp;gt; {
  console.log(`🚀 Server started on port ${port}`);
});

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;process.env.PORT&lt;/code&gt; returns the PORT environment variable which is set in many hosting providers so it is a good practice to use that instead of hardcoding a port. We're saying that if it doesn't exist, use port 3000.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Code
&lt;/h2&gt;

&lt;p&gt;Your final code in &lt;code&gt;index.js&lt;/code&gt; should look 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;const express = require("express");
const app = express();

app.get("/", (req, res) =&amp;gt; {
  return res.send("Hello, World");
});

const port = process.env.PORT || 3000;
app.listen(port, () =&amp;gt; {
  console.log(`🚀 Server started on port ${port}`);
});

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

&lt;/div&gt;



&lt;p&gt;That's it for this tutorial! Now express has a lot more stuff to offer you. Just yesterday, MDN released it's new &lt;a href="https://developer.mozilla.org/en-US/" rel="noopener noreferrer"&gt;website&lt;/a&gt; and I found a very good in-depth tutorial on express. Do check it out &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Developer Setup in 2022!</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Tue, 22 Feb 2022 16:09:47 +0000</pubDate>
      <link>https://dev.to/kavinvalli/my-developer-setup-in-2022-12gk</link>
      <guid>https://dev.to/kavinvalli/my-developer-setup-in-2022-12gk</guid>
      <description>&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%2F14eui2s4m0mewrcfqqdw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14eui2s4m0mewrcfqqdw.jpeg" alt="My Setup" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm very excited for this article because I'm going to show you guys my developer setup! So, my developer setup is something which has evolved in the past few years. I've switched through editors, IDEs, browsers, etc. and this is what I use now. This might change in a few days/months/years too... who knows!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.apple.com/in/macbook-air/" rel="noopener noreferrer"&gt;M1 Macbook Air 2020&lt;/a&gt; with 256GB storage and 8GB RAM with an external 27-inch monitor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editor
&lt;/h2&gt;

&lt;p&gt;The editor I generally use is &lt;a href="https://neovim.io/" rel="noopener noreferrer"&gt;Neovim&lt;/a&gt;. So, most of you would have heard of &lt;a href="https://www.vim.org/" rel="noopener noreferrer"&gt;Vim&lt;/a&gt;. Neovim started as a fork of Vim and has some really good features over vim. Recently, Neovim also released support for Native Language Servers. The reason I use Neovim over editors like, VS Code and Sublime Text is primarily cause of the speed. This includes, speed of Neovim as an editor, comprising of startup time, less lagging, etc, and that also includes my speed as a developer. Vim might seem pretty daunting when you start with it, but when you get the hang of it, you'd want to use it everywhere. And I'm a big keyboard-only fan. So, the fact that I don't have to touch my mouse while writing code is a big plus point.&lt;/p&gt;

&lt;p&gt;However, I do use &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; when collaborating with others in real time using the &lt;a href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare" rel="noopener noreferrer"&gt;Live Share extension&lt;/a&gt;. And guess what! I use vim keybindings inside VSCode as well using the &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim" rel="noopener noreferrer"&gt;Vim extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Though, Neovim does have a few minus points to it&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You'll have to learn vim&lt;/li&gt;
&lt;li&gt;You'll have to spend some time customising neovim to suit your needs, and setup plugins for autocomplete, LSPs etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're a beginner, I highly recommend starting with VSCode and maybe use the vim extension if you want to start learning vim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminal Setup
&lt;/h2&gt;

&lt;p&gt;I am a person, who's always on my terminal, especially cause of the fact that I use neovim as my primary code editor. I use &lt;a href="https://iterm2.com/" rel="noopener noreferrer"&gt;iTerm2&lt;/a&gt; but I've heard of &lt;a href="https://sw.kovidgoyal.net/kitty/" rel="noopener noreferrer"&gt;Kitty&lt;/a&gt; and &lt;a href="https://alacritty.org/" rel="noopener noreferrer"&gt;Alacritty&lt;/a&gt; as pretty good alternatives.&lt;/p&gt;

&lt;p&gt;I also use &lt;a href="https://github.com/tmux/tmux" rel="noopener noreferrer"&gt;tmux&lt;/a&gt; heavily in my workflow. I use multiple tmux sessions for every project and recommend a lot of people to use it.&lt;/p&gt;

&lt;p&gt;I use the &lt;a href="https://fishshell.com/" rel="noopener noreferrer"&gt;fish shell&lt;/a&gt;. It has some great features which you can find on the website which lead me to use it over zsh and bash.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://www.gnu.org/software/stow/" rel="noopener noreferrer"&gt;GNU Stow&lt;/a&gt; to manage my configurations.&lt;/p&gt;

&lt;p&gt;You can find my dotfiles in the repo linked below.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kavinvalli" rel="noopener noreferrer"&gt;
        kavinvalli
      &lt;/a&gt; / &lt;a href="https://github.com/kavinvalli/dotfiles" rel="noopener noreferrer"&gt;
        dotfiles
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A bunch of dotfiles to setup neovim, tmux, fish, etc.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Kavin's .dotfiles&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Stuff I Use&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: all these have to be installed&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://iterm2.com/" rel="nofollow noopener noreferrer"&gt;iTerm2&lt;/a&gt; - Terminal&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://fishshell.com" rel="nofollow noopener noreferrer"&gt;fish&lt;/a&gt; - Shell&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://neovim.io/" rel="nofollow noopener noreferrer"&gt;neovim&lt;/a&gt; - Editor&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tmux/tmux" rel="noopener noreferrer"&gt;tmux&lt;/a&gt; - Terminal Multiplexer&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Dependencies&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Install the following too&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/oh-my-fish/oh-my-fish" rel="noopener noreferrer"&gt;ohmyfish&lt;/a&gt; - Makes it easier to
extend fish with plugins&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/junegunn/vim-plug" rel="noopener noreferrer"&gt;vim-plug&lt;/a&gt; - Plugin Manager for Neovim&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tmux-plugins/tpm" rel="noopener noreferrer"&gt;tpm&lt;/a&gt; - Plugin Manager for Tmux&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gnu.org/software/stow/" rel="nofollow noopener noreferrer"&gt;GNU Stow&lt;/a&gt; - Symlink manager&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Some more optional dependencies for some fish functions&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/someshkar/dotco" rel="noopener noreferrer"&gt;dotco&lt;/a&gt; - A URL Shortener with Vercel and
Airtable&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cli.github.com/" rel="noopener noreferrer"&gt;Github CLI&lt;/a&gt; - Github CLI
&lt;ul&gt;
&lt;li&gt;Get the &lt;code&gt;delete repo&lt;/code&gt; permission by doing &lt;code&gt;gh auth login -s delete_repo&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Install the dependencies above&lt;/li&gt;
&lt;li&gt;Backup old dotfiles if you have any&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;mv &lt;span class="pl-k"&gt;~&lt;/span&gt;/.dotfiles &lt;span class="pl-k"&gt;~&lt;/span&gt;/.dotfiles.bak&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Clone this repo&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/kavin25/dotfiles.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; &lt;span class="pl-k"&gt;~&lt;/span&gt;/.dotfiles&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Change Airtable env vars for
&lt;a href="https://github.com/kavin25/airtable-url-cli" rel="noopener noreferrer"&gt;dotco-cli&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;cp docs/url-env-example.sh scripts/url-env.sh&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="5"&gt;
&lt;li&gt;Symlink with Stow&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;stow &lt;span class="pl-k"&gt;*&lt;/span&gt;/&lt;/pre&gt;

&lt;/div&gt;
&lt;ol start="6"&gt;
&lt;li&gt;Install some &lt;a href="https://github.com/ryanoasis/nerd-fonts" rel="noopener noreferrer"&gt;Nerd Font&lt;/a&gt; - for some
icons and stuff&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Credits&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/someshkar/dotco" rel="noopener noreferrer"&gt;dotco&lt;/a&gt; - A URL Shortener with Vercel…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kavinvalli/dotfiles" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So that's it for this post. I might post an article specific to my Neovim Configuration and how I manage my dotfiles in the recent future.&lt;/p&gt;

&lt;p&gt;Checkout more of my articles at &lt;a href="https://livecode247.com" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>developer</category>
      <category>development</category>
      <category>terminal</category>
      <category>editors</category>
    </item>
    <item>
      <title>RITA - Batteries included starter for Adonis apps</title>
      <dc:creator>Kavin Desi Valli</dc:creator>
      <pubDate>Mon, 13 Dec 2021 12:29:20 +0000</pubDate>
      <link>https://dev.to/kavinvalli/rita-batteries-included-starter-for-adonis-apps-54gi</link>
      <guid>https://dev.to/kavinvalli/rita-batteries-included-starter-for-adonis-apps-54gi</guid>
      <description>&lt;p&gt;People who've tried Laravel would know how easy it makes lives of developers. Then, came in &lt;a href="https://adonisjs.com/" rel="noopener noreferrer"&gt;AdonisJS&lt;/a&gt; which is essentially just Laravel for Typescript developers. I've used both for a while now and love not having to go through long processes of setting up codebases from scratch.&lt;/p&gt;

&lt;p&gt;One of my &lt;a href="https://github.com/dotangad" rel="noopener noreferrer"&gt;seniors&lt;/a&gt;, told me about &lt;a href="https://inertiajs.com/" rel="noopener noreferrer"&gt;Inertia&lt;/a&gt; and we used it for a couple of projects with Laravel and it was amazing to be able to use Laravel with React. Essentially, Inertia is just a connector / glue between server-side and client-side frameworks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With Inertia you build apps just like you've always done with your server-side web framework of choice. You use your framework's existing functionality for routing, controllers, middleware, authentication, authorization, data fetching, and more.&lt;/p&gt;

&lt;p&gt;The only thing that's different is your view layer. Instead of using server-side rendering (eg. Blade or ERB templates), the views are JavaScript page components. This allows you to build your entire front-end using React, Vue or Svelte.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By using Inertia, I was able to pass data from my server side framework (Laravel) to my client side framework (ReactJS) as props which made it super easy to work with data since I had to no longer do the work of fetching data from REST or GraphQL APIs.&lt;/p&gt;

&lt;p&gt;My senior created &lt;a href="https://github.com/dotangad/liret" rel="noopener noreferrer"&gt;LIRET&lt;/a&gt; which uses Laravel and React with Inertia as an adapter with more features out of the box.&lt;/p&gt;

&lt;p&gt;I finally came across &lt;a href="https://github.com/eidellev/inertiajs-adonisjs" rel="noopener noreferrer"&gt;inertia-adonisjs&lt;/a&gt; which is a &lt;code&gt;Inertia.js AdonisJS Provider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I recreated the LIRET stack but with AdonisJS and then came up &lt;a href="https://github.com/kavinvalli/rita" rel="noopener noreferrer"&gt;&lt;strong&gt;RITA&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RITA is a batteries-included starter for Adonis apps. The full form of Rita is &lt;code&gt;React Inertia Typescript Adonis&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Backend
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;AdonisJS&lt;/li&gt;
&lt;li&gt;Database (MySQL but you can change it very easily)&lt;/li&gt;
&lt;li&gt;Authentication

&lt;ul&gt;
&lt;li&gt;Email-Password&lt;/li&gt;
&lt;li&gt;Github&lt;/li&gt;
&lt;li&gt;Gmail&lt;/li&gt;
&lt;li&gt;You can also add other providers very easily&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Admin Authorisation with Middleware support&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  Frontend
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Frontend with React and Typescript&lt;/li&gt;
&lt;li&gt;TailwindCSS setup&lt;/li&gt;
&lt;li&gt;Some built in components/hooks like &lt;code&gt;useTitle&lt;/code&gt; and &lt;code&gt;TextInput&lt;/code&gt; for simplicity&lt;/li&gt;
&lt;li&gt;Built in components for Authorisation validation like &lt;code&gt;&amp;lt;Admin&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;User&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Authenticated&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Guest&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Inertia as a connector.&lt;/p&gt;

&lt;p&gt;There are a few more features and you can find detailed instructions at the &lt;a href="https://rita.kavin.me" rel="noopener noreferrer"&gt;Readme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Give the repo a star if you like it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kavinvalli/rita" rel="noopener noreferrer"&gt;https://github.com/kavinvalli/rita&lt;/a&gt;&lt;/p&gt;

</description>
      <category>adonisjs</category>
      <category>inertia</category>
    </item>
  </channel>
</rss>
