<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[LiveCode247 Blog]]></title><description><![CDATA[A blog site about web development which covers variety of categories of the same]]></description><link>https://livecode247.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1643737211529/DYTfNfHms.png</url><title>LiveCode247 Blog</title><link>https://livecode247.com</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 10 Apr 2026 12:41:03 GMT</lastBuildDate><atom:link href="https://livecode247.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[It's so easy to convert a NextJS App to use the App Router!]]></title><description><![CDATA[DISCLAIMER: This might not be the most well-written article since I haven't written in a while and I just wanted to get back to writing with a short article about my experience of the day, so sorry about that

I previously used this repository for my...]]></description><link>https://livecode247.com/its-so-easy-to-convert-a-nextjs-app-to-use-the-app-router</link><guid isPermaLink="true">https://livecode247.com/its-so-easy-to-convert-a-nextjs-app-to-use-the-app-router</guid><category><![CDATA[Next.js]]></category><category><![CDATA[app router]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Fri, 12 Apr 2024 20:39:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712953785208/70ca3e81-b2a2-45d1-b953-047a4d224eb4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>DISCLAIMER: This might not be the most well-written article since I haven't written in a while and I just wanted to get back to writing with a short article about my experience of the day, so sorry about that</p>
</blockquote>
<p>I previously used <a target="_blank" href="https://github.com/someshkar/dotco">this repository</a> for my shortlinks, but it looks like airtable recently moved away from API Keys to Permanent Access Tokens. So, I thought why not just take out the functionality from this and use it in my personal website itself so that whenever I go to <code>https://kavin.me/[something]</code>, I could redirect to the target link if it exists on the airtable base.</p>
<p>For people who don't know the backstory of my website, it's a terminal themed website and was originally made with vanilla JS but it soon got very hard to maintain. So, I moved it to NextJS in the pre-app router days by just copy pasting things and somehow made it work (it's not the best codebase because of this)</p>
<p>To implement the desired shortlink functionality, I wanted to add a catch-all API route on /. This was a bit tricky in Next.js 12, as API routes only existed within the api directory. While it was possible to use getServerSideProps in other locations, it felt like a hack. So, I decided to upgrade to the new app router, hoping it would simplify the process.</p>
<p>I wasn't wrong because it was amazingly easy to upgrade. I followed <a target="_blank" href="https://nextjs.org/docs/pages/building-your-application/upgrading/app-router-migration">this guide</a> to just install the latest dependencies. Then, I:</p>
<ol>
<li><p>Created the app directory</p>
</li>
<li><p>Created a <code>app/layout.js</code> file</p>
</li>
<li><p>Copy pasted the previous <code>index.js</code> into <code>app/page.js</code></p>
</li>
<li><p>Marked a few of the files inside the <code>components</code> directory to <code>"use client"</code></p>
</li>
</ol>
<p>And just like that, the upgrade was complete!</p>
<p>Of course, I understand that this process won't be as simple for most projects, especially those with more complexities and pages. The previous data fetching method was also quite different from the new approach using React Server Components. However, the ability to work concurrently with the pages and app directories allows for incremental changes. This means you can gradually adopt the newest features without causing significant disruption to your application.</p>
<p>I loved the experience moving to the App Router and it's something which I prefer using over the pages format.</p>
]]></content:encoded></item><item><title><![CDATA[Master NextJS 13 Data Fetching with this Step-by-Step Guide]]></title><description><![CDATA[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 getServerSideProps, getStatic...]]></description><link>https://livecode247.com/demystifying-data-fetching-in-nextjs-13</link><guid isPermaLink="true">https://livecode247.com/demystifying-data-fetching-in-nextjs-13</guid><category><![CDATA[Next.js]]></category><category><![CDATA[React]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Mon, 27 Mar 2023 08:32:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679905873039/79efb7a5-4dac-4f0d-8e07-bce8aa5cb0cf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>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 <code>getServerSideProps</code>, <code>getStaticProps</code>, and <code>getInitialProps</code>.</p>
<h2 id="heading-video">Video</h2>
<p>If you prefer watching a video, you can check out the Youtube video posted on the same</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/CYCn1I_kvjc">https://youtu.be/CYCn1I_kvjc</a></div>
<p> </p>
<h2 id="heading-fetch-api">fetch() API</h2>
<p>React recently introduces support for <a target="_blank" href="https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md">async/await in Server Components</a>. 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.</p>
<h2 id="heading-server-components">Server Components</h2>
<p>This is all you need to do to fetch data in NextJS now:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Post } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/lib/types"</span>;
<span class="hljs-keyword">import</span> { Inter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/font/google"</span>;

<span class="hljs-keyword">const</span> inter = Inter({ subsets: [<span class="hljs-string">"latin"</span>] });

<span class="hljs-keyword">const</span> getPosts = <span class="hljs-keyword">async</span> (): <span class="hljs-built_in">Promise</span>&lt;Post[]&gt; =&gt; {
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>);
  <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> data.json();

  <span class="hljs-keyword">return</span> posts;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Posts</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> getPosts();
  <span class="hljs-built_in">console</span>.log(posts);

  <span class="hljs-keyword">return</span> (
    &lt;div className={inter.className}&gt;
      &lt;h1&gt;Posts&lt;/h1&gt;
      &lt;ul&gt;
        {posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span> (
          &lt;li key={post.id}&gt;{post.title}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>The data is no more serialised so you can pass any type of data, including Dates, Maps, Sets, etc.</p>
<p>Also, note the fact that you no longer need to do this on the page level, like if you did before using <code>getStaticProps</code> or <code>getServerSideProps</code>. You can do this inside any component</p>
<h2 id="heading-client-components">Client Components</h2>
<p>For now, if you need to fetch data in a Client Component, NextJS 13 recommends using a third-party library such as <a target="_blank" href="https://swr.vercel.app/">SWR</a> or <a target="_blank" href="https://tanstack.com/query/v4">React Query</a>.</p>
<p>React also introduced the <a target="_blank" href="https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md#usepromise"><code>use</code></a> 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.</p>
<pre><code class="lang-typescript"><span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> { Post } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/lib/types"</span>;
<span class="hljs-keyword">import</span> { Inter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/font/google"</span>;
<span class="hljs-keyword">import</span> { use } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> inter = Inter({ subsets: [<span class="hljs-string">"latin"</span>] });

<span class="hljs-keyword">const</span> getPosts = <span class="hljs-keyword">async</span> (): <span class="hljs-built_in">Promise</span>&lt;Post[]&gt; =&gt; {
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>);
  <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> data.json();

  <span class="hljs-keyword">return</span> posts;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ClientPosts</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> posts = use(getPosts());

  <span class="hljs-keyword">return</span> (
    &lt;div className={inter.className}&gt;
      &lt;h1&gt;Posts&lt;/h1&gt;
      &lt;ul&gt;
        {posts.map(<span class="hljs-function">(<span class="hljs-params">post</span>) =&gt;</span> (
          &lt;li key={post.id}&gt;{post.title}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h2 id="heading-static-data-fetching">Static Data Fetching</h2>
<p><code>fetch</code> 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</p>
<pre><code class="lang-typescript">fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>, {
  cache: <span class="hljs-string">"force-cache"</span>,
});
</code></pre>
<h2 id="heading-dynamic-data-fetching">Dynamic Data Fetching</h2>
<p>You can tell the <code>fetch</code> API to never cache the data by changing <code>force-cache</code> to <code>no-cache</code> or <code>no-store</code>(both signify the same in NextJS).</p>
<pre><code class="lang-typescript">fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>, {
  cache: <span class="hljs-string">"no-cache"</span>
});
</code></pre>
<h2 id="heading-dynamic-params-data-fetching">Dynamic Params Data Fetching</h2>
<p>Say, you link all the posts to another page <code>/posts/[postId]</code> and fetch the data here once you're in there. You'd do something like this:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// app/posts/[postId]/page.tsx</span>

<span class="hljs-keyword">import</span> { Post } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/lib/types"</span>;
<span class="hljs-keyword">import</span> { Inter } <span class="hljs-keyword">from</span> <span class="hljs-string">"next/font/google"</span>;

<span class="hljs-keyword">const</span> inter = Inter({ subsets: [<span class="hljs-string">"latin"</span>] });

<span class="hljs-comment">// params: {</span>
<span class="hljs-comment">//   postId: aksdjlkjasd</span>
<span class="hljs-comment">// }</span>

<span class="hljs-keyword">const</span> getPost = <span class="hljs-keyword">async</span> (id: <span class="hljs-built_in">string</span>): <span class="hljs-built_in">Promise</span>&lt;Post&gt; =&gt; {
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`https://jsonplaceholder.typicode.com/posts/<span class="hljs-subst">${id}</span>`</span>);
  <span class="hljs-keyword">const</span> post = <span class="hljs-keyword">await</span> data.json();

  <span class="hljs-keyword">return</span> post;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PostPage</span>(<span class="hljs-params">{
  params: { postId },
}: {
  params: {
    postId: <span class="hljs-built_in">string</span>;
  };
}</span>) </span>{
  <span class="hljs-keyword">const</span> post = <span class="hljs-keyword">await</span> getPost(postId);
  <span class="hljs-keyword">return</span> (
    &lt;div className={inter.className}&gt;
      &lt;h1&gt;{post.title}&lt;/h1&gt;
      &lt;p&gt;Post ID: {postId}&lt;/p&gt;
      &lt;p&gt;{post.body}&lt;/p&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p>Now, this works great, but when you try to build it, look at the response:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679905145318/c65e6c26-2761-4136-83e6-e3cbc3d57c73.png" alt class="image--center mx-auto" /></p>
<p>It says that <code>/posts/[postId]</code> is server-side rendered at runtime even though <code>/posts</code> 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 <code>/posts/[postId]/page.tsx</code> page</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> generateStaticParams = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>);
  <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> data.json();

  <span class="hljs-keyword">return</span> posts.map(<span class="hljs-function">(<span class="hljs-params">post: Post</span>) =&gt;</span> ({
    params: {
      postId: post.id.toString(),
    },
  }));
};
</code></pre>
<p>This now tells NextJS, that all these <code>postId</code>s exist and we want it to statically generate them at build time if possible. Now, if we try rebuilding the app, this happens</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679905387382/e9f4a8c8-9868-49fc-b5c0-a673fac91b86.png" alt class="image--center mx-auto" /></p>
<p>Now, see that <code>/posts/[postId]</code> is static HTML + JSON! And, that would further optimise your app really well.</p>
<h2 id="heading-revalidating-data">Revalidating Data</h2>
<p>Say, your app is not fully dynamic but still sometimes the data does change, you can add this to your <code>/posts/[postId]/page.tsx</code> page</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> revalidate = <span class="hljs-number">3600</span>; <span class="hljs-comment">// in seconds</span>
</code></pre>
<p>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.</p>
<p>You can also do this per fetch by tweaking the fetch call as follows</p>
<pre><code class="lang-typescript">fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/posts"</span>, {
  next: {
    revalidate: <span class="hljs-number">3600</span>,
  },
});
</code></pre>
<p>And that is it!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>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.</p>
<p>You can find all the code over here</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/data-fetching-next13">https://github.com/kavinvalli/data-fetching-next13</a></div>
<p> </p>
<p>Do give the video a look if you like that more, and stay tuned for more such posts!</p>
<h2 id="heading-reference-links">Reference Links</h2>
<ul>
<li><p><a target="_blank" href="https://beta.nextjs.org/docs">NextJS 13 Docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/redirect?event=video_description&amp;redir_token=QUFFLUhqbEt2ZTlmUXk4VFBWYzBZQWZlN1ZDZWFWX3ZHZ3xBQ3Jtc0tub3NFNmZoQ2tqc09SRUM0N2kwYnNQOEF0em4wSW52QzRhXzF5UDRKTTA1NmdjMUNfYTllekRMWHQwcEdoMkV6dk0zVU4wQ3VrWk1zME1nQzNNYlhKUTRRNUxOSXd6Qm9fUjFhbWJrZVUtUGp0cXRLQQ&amp;q=https%3A%2F%2Fbeta.nextjs.org%2Fdocs%2Fdata-fetching%2Ffetching&amp;v=CYCn1I_kvjc">NextJS 13 Data Fetching Docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/redirect?event=video_description&amp;redir_token=QUFFLUhqbk1xRWc3VFpONm1fQTl2b0lOXzNnNUswcVlSd3xBQ3Jtc0trZ0MyRnVvamZ0eDZzMlRHeExRTklYS2xDeU5pVDB4amZTVFQwR0lYUy13eERGcmVrMXNORzNGWVRMNTN0aE9IVjdiaUZaNko0S2tZR2pKUG1WUDJGSFR6MmtCNm05X3IxaU9FRUU3T2lNZFRsZktTcw&amp;q=https%3A%2F%2Fgithub.com%2Facdlite%2Frfcs%2Fblob%2Ffirst-class-promises%2Ftext%2F0000-first-class-support-for-promises.md%23usepromise&amp;v=CYCn1I_kvjc"><code>use</code> hook in React</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/redirect?event=video_description&amp;redir_token=QUFFLUhqbnEwZ1BvMjhuNjZDUXozbVc1Um9oSndjLTQyUXxBQ3Jtc0ttV1dWMFpkS2JXdGNCbXJDOTk3RWZDbG9Kb19hSWdLMnFLVjJEWXplcG1XTWUwZnNpN29jMDVPQVhpVGMzV2g4TTg0dWlXYkNaMlhaVEdmakJqODduc05LbFVQWG9MOGlOZVFkbVJTbXdheGkxWTRLRQ&amp;q=https%3A%2F%2Fswr.vercel.app%2F&amp;v=CYCn1I_kvjc">SWR</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/redirect?event=video_description&amp;redir_token=QUFFLUhqbjlFdGVLVGpvZkUzQk9LRkc3cHZCRWxSZmlkZ3xBQ3Jtc0tuNWFfNWwyaEdHTk5nNk9zZWJwd0Fnd193ajh0dWlVODB3ejd0R3NDRjFLZUxHbEEyU1ljTFEwWWRiTWZvVzRNbnZqQUZfeUVlZkU4RDVpNEVkWXpGbEhhTUJtSDA3VVZSanRCYm40RmFSMkJ4b29yUQ&amp;q=https%3A%2F%2Ftanstack.com%2Fquery%2Fv4&amp;v=CYCn1I_kvjc">React Query</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Try using this authentication method in your next NextJS project!! (Hint: Magic Links)]]></title><description><![CDATA[Looking for a safe and reliable way to authenticate users? Consider implementing magic links. They offer a secure alternative to traditional passwords and can help mitigate the risk of password leaks and forgotten passwords.
Magic Link authentication...]]></description><link>https://livecode247.com/try-using-this-authentication-method-in-your-next-nextjs-project-hint-magic-links</link><guid isPermaLink="true">https://livecode247.com/try-using-this-authentication-method-in-your-next-nextjs-project-hint-magic-links</guid><category><![CDATA[Next.js]]></category><category><![CDATA[authentication]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Tue, 21 Mar 2023 15:31:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679412526052/77a964bf-94f6-4177-a487-419a25aef889.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Looking for a safe and reliable way to authenticate users? Consider implementing magic links. They offer a secure alternative to traditional passwords and can help mitigate the risk of password leaks and forgotten passwords.</p>
<p>Magic Link authentication, also known as Email-only authentication, is a trending method of authentication that has recently gained significant popularity.</p>
<h2 id="heading-how-does-it-work">How does it work?</h2>
<p>The following steps are involved:</p>
<ol>
<li><p>The user enters their email.</p>
</li>
<li><p>If the user doesn't already exist in the database, an account is created.</p>
</li>
<li><p>A unique verification token is generated.</p>
</li>
<li><p>The user is sent an email with a link which contains the verification token encoded.</p>
</li>
<li><p>When the user visits the link, the verification token is cross-checked with the one stored on the database, and the user is authenticated if the token is valid.</p>
</li>
</ol>
<h2 id="heading-why-use-email-only-authentication">Why use Email-only authentication?</h2>
<p>Doesn't it seem less secure without passwords? However, if you have access to someone's email, you can access their account. Most websites offer a "forgot password" function that allows you to reset a password with access to an email. So, if a hacker gains access to the email, they can still get into the account.</p>
<p>So, it does appear that email-only authentication (or passwordless authentication) could be more secure as it eliminates the risk of password hacking.</p>
<h2 id="heading-how-to-add-email-only-authentication-to-a-nextjs-project">How to add Email-only authentication to a NextJS project?</h2>
<p>You can easily accomplish this by utilizing Next-Auth, which is now referred to as Auth.js. Check out my video tutorial on how to implement it for further information!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/boyVzmMEtFg">https://youtu.be/boyVzmMEtFg</a></div>
]]></content:encoded></item><item><title><![CDATA[Boost Your Neovim Experience with These Essential Plugins]]></title><description><![CDATA[Neovim is a powerful text editor that can be customized with plugins to enhance its functionality. In this article, we will explore the top 10 essential Neovim plugins. These plugins can help improve your Neovim experience by adding features such as ...]]></description><link>https://livecode247.com/boost-your-neovim-experience-with-these-essential-plugins</link><guid isPermaLink="true">https://livecode247.com/boost-your-neovim-experience-with-these-essential-plugins</guid><category><![CDATA[neovim]]></category><category><![CDATA[plugins]]></category><category><![CDATA[editors]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Sun, 19 Mar 2023 05:32:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1679203934717/804a0caf-0aeb-41e3-918c-09beb7435a3f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Neovim is a powerful text editor that can be customized with plugins to enhance its functionality. In this article, we will explore the top 10 essential Neovim plugins. These plugins can help improve your Neovim experience by adding features such as file searching, syntax highlighting, language server setup, and more. So if you want to take your Neovim game to the next level, keep reading!</p>
<h2 id="heading-packernvimhttpsgithubcomwbthomasonpackernvim"><a target="_blank" href="https://github.com/wbthomason/packer.nvim">packer.nvim</a></h2>
<p><code>packer.nvim</code> is not really a plugin, but it's a plugin manager. I used to use <a target="_blank" href="https://github.com/junegunn/vim-plug">vim-plug</a> before moving to lua, and now, I am very satisfied with packer. Unlike vim-plug which is written in vim-script, packer.nvim is written in lua. It is one of the most powerful and feature-rich plugin managers written in Lua.</p>
<h2 id="heading-telescopenvimhttpsgithubcomnvim-telescopetelescopenvim"><a target="_blank" href="https://github.com/nvim-telescope/telescope.nvim">telescope.nvim</a></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679202280210/c77cf079-b2e9-412d-bc5b-b54f9bc31fe2.png" alt class="image--center mx-auto" /></p>
<p><code>telescope.nvim</code> is a highly extendable fuzzy finder over lists. Built on the latest awesome features from <code>neovim</code> core. Telescope is centred around modularity, allowing for easy customization. It has a lot of really good features, like:</p>
<ol>
<li><p>Finding Files</p>
</li>
<li><p>Fuzzy Search through buffers</p>
</li>
<li><p>Searching through files and so much more.</p>
</li>
</ol>
<h2 id="heading-nvim-treesitterhttpsgithubcomnvim-treesitternvim-treesitter"><a target="_blank" href="https://github.com/nvim-treesitter/nvim-treesitter">nvim-treesitter</a></h2>
<p>nvim-treesitter provides a simple and easy way to use the interface for <a target="_blank" href="https://github.com/tree-sitter/tree-sitter">tree-sitter</a> in Neovim and to provide some basic functionality such as highlighting based on it. It builds an Abstract Syntax Tree and helps integrate lots of features.</p>
<p>Nvim-treesitter is based on three interlocking features: language parsers, queries, and modules, where modules provide features – e.g., highlighting – based on queries for syntax objects extracted from a given buffer by language parsers</p>
<h2 id="heading-nvim-lspconfighttpsgithubcomneovimnvim-lspconfig"><a target="_blank" href="https://github.com/neovim/nvim-lspconfig">nvim-lspconfig</a></h2>
<p>Now, this is one of the most important plugins on the list. Neovim v5 brought in one of the biggest updates to neovim till now and one of the most important features was native LSP. Now, you can setup language servers in neovim without having to use plugins like <code>coc.nvim</code>. Now, one of the downsides of using native LSP is that there's quite a lot of setup you have to do. If you don't want to do that I'd highly recommend coc.nvim since it gives you a boilerplate and brings many vscode like features to neovim.</p>
<p>If that's not a problem for you, then nvim-lspconfig is a very good plugin. You can combine it with the following plugins to make it even better</p>
<h2 id="heading-nvim-cmphttpsgithubcomhrsh7thnvim-cmp"><a target="_blank" href="https://github.com/hrsh7th/nvim-cmp">nvim-cmp</a></h2>
<p><code>nvim-cmp</code> is a completion engine for neovim written in lua.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679202567234/5dc570bf-b33b-4b7f-ab01-313f5a09e774.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-null-lshttpsgithubcomjose-elias-alvareznull-lsnvim"><a target="_blank" href="https://github.com/jose-elias-alvarez/null-ls.nvim">null-ls</a></h2>
<blockquote>
<p>Unlike the VS Code and coc.nvim ecosystems, Neovim doesn't provide a way for non-LSP sources to hook into its LSP client. null-ls is an attempt to bridge that gap and simplify the process of creating, sharing, and setting up LSP sources using pure Lua.</p>
</blockquote>
<p>With Neovim LSP, it gets a little harder to setup things like Prettier and ESLint and that's where null-ls comes in. It provides a very simple way to plug in non-LSP sources.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679203211421/9f64f2ba-a438-4b92-990f-e4c992012850.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-luasniphttpsgithubcoml3mon4d3luasnip"><a target="_blank" href="https://github.com/L3MON4D3/LuaSnip">LuaSnip</a></h2>
<p><code>luasnip</code> is a vscode like snippet feature. It works hand in hand with nvim-cmp and you can customize your snippets.</p>
<h2 id="heading-nvim-treehttpsgithubcomkyazdani42nvim-treelua"><a target="_blank" href="https://github.com/kyazdani42/nvim-tree.lua">nvim-tree</a></h2>
<p><code>nvim-tree</code> is a file explorer for neovim written in lua.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679202245088/0b8a26b0-f8ea-434f-ae49-9d83c5973187.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-bufferlinehttpsgithubcomakinshobufferlinenvim"><a target="_blank" href="https://github.com/akinsho/bufferline.nvim">Bufferline</a></h2>
<p>One of the many bufferline solutions for neovim out there. It's completely written in Rust and if you want to emulate a Doom emacs style bufferline, this is your way to go. It has multiple features like Tab Pages, LSP Indicators, Pinning, GUI for closing and reordering, and so much more!</p>
<p><img src="https://user-images.githubusercontent.com/22454918/111992693-9c6a9b00-8b0d-11eb-8c39-19db58583061.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-lualinehttpsgithubcomnvim-lualinelualinenvim"><a target="_blank" href="https://github.com/nvim-lualine/lualine.nvim">Lualine</a></h2>
<p>A blazing fast and easy to configure neovim statusline plugin written in pure lua.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679203528070/1a24d71c-14ba-4354-aafb-ebc727e94f97.png" alt class="image--center mx-auto" /></p>
<p>There are a lot of themes you can choose from and customise the look of your statusline and you can reorder items, add plugins and a lot more.</p>
<p>In conclusion, Neovim is a highly customizable text editor that can be enhanced with plugins to improve your coding experience. The plugins listed in this article are just a few examples of the many options available. By adding these essential plugins to your Neovim setup, you can streamline your workflow, increase productivity, and take your coding game to the next level. So why not give them a try and see how they can transform your Neovim experience?</p>
<h2 id="heading-additional-resources">Additional Resources</h2>
<ul>
<li><p><a target="_blank" href="https://www.reddit.com/r/neovim">Neovim Reddit</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/rockerBOO/awesome-neovim">Awesome Neovim</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Typewind: The magic of Tailwind combined with the safety of Typescript]]></title><description><![CDATA[Well, the people who've read my previous articles know how much I love type-safety, hence someone who loves the t3 stack. Here's Typewind, a typesafe and zero-runtime version of Tailwind CSS, a utility-first CSS framework that can be composed to buil...]]></description><link>https://livecode247.com/typewind-the-magic-of-tailwind-combined-with-the-safety-of-typescript</link><guid isPermaLink="true">https://livecode247.com/typewind-the-magic-of-tailwind-combined-with-the-safety-of-typescript</guid><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Wed, 25 Jan 2023 13:10:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674651899791/52be5396-3b97-4ebb-99db-17c4be2eefb2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674651855860/13a5eb54-63b2-4dc8-b78d-617c8a3b0adf.png" alt class="image--center mx-auto" /></p>
<p>Well, the people who've read my previous articles know how much I love type-safety, hence someone who loves the <a target="_blank" href="https://livecode247.com/why-t3-stack">t3 stack</a>. Here's <a target="_blank" href="https://typewind.vercel.app">Typewind</a>, a <strong>typesafe</strong> and <strong>zero-runtime</strong> version of Tailwind CSS, a utility-first CSS framework that can be composed to build any design, directly in your markup.</p>
<h2 id="heading-what-does-typewind-do">What does Typewind do?</h2>
<p>Typewind is a powerful utility-first CSS framework that combines the magic of Tailwind with the safety of Typescript. It provides a typesafe environment over Tailwind CSS, enabling developers to work with autocomplete, prevent typos, and catch errors at compile time. With zero runtime overhead, Typewind generates custom type definitions based on your app's <code>tailwind.config.js</code> file, making it a top choice for developers who value type-safety. Here's an example of how Typewind works:</p>
<p><a target="_blank" href="https://twitter.com/Mokshit06/status/1617880004846825474">https://twitter.com/Mokshit06/status/1617880004846825474</a></p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { tw } <span class="hljs-keyword">from</span> <span class="hljs-string">"typewind"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Button</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        &lt;button className={tw.}&gt;&lt;/button&gt;
    )
}
</code></pre>
<p>The moment you type <code>tw.</code>, you will get autocomplete like so, based on your own custom <code>tailwind.config.js</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674663236218/5f9613b6-e151-40f3-868d-6566be5fc2ff.png" alt class="image--center mx-auto" /></p>
<p>And, the moment you make a typo:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674663315897/cfd990fa-e131-4f1e-bf09-eb2935256800.png" alt class="image--center mx-auto" /></p>
<p>And it has absolutely zero overhead runtime! Will talk a little more about the features below, but before that, let me talk about how this started!</p>
<h2 id="heading-origin">Origin</h2>
<p>The whole thing started with one tweet.</p>
<p><a target="_blank" href="https://twitter.com/stolinski/status/1613699772111638530">https://twitter.com/stolinski/status/1613699772111638530</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674651739185/b39b37fa-5ad6-46df-a1e7-1e609c0f7b86.png" alt class="image--center mx-auto" /></p>
<p>Then <a target="_blank" href="https://twitter.com/colinhacks">Colin McDonnell</a> tweeted on what tailwind with type safety and proper autocompletion would look like.</p>
<p><a target="_blank" href="https://twitter.com/colinhacks/status/1615154756204523521">https://twitter.com/colinhacks/status/1615154756204523521</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674651771996/779a5f25-b3fd-4f9d-b82b-17d4dac0a93a.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://mokshitjain.co">Mokshit</a>, 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 <a target="_blank" href="https://twitter.com/t3dotgg/status/1615232346231558147?s=20&amp;t=I5tEkOkmymKw31I4_7YT0A">Theo</a> had similar thoughts.</p>
<p>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.</p>
<p>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).</p>
<p>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.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674646321258/70dda6a9-7fd4-47ff-ac3a-b6084b91aef2.png" alt="Typewind Logo" class="image--center mx-auto" /></p>
<p>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:</p>
<h2 id="heading-features">Features</h2>
<ul>
<li><p>Zero runtime</p>
</li>
<li><p>Type-safety and auto-completion</p>
</li>
<li><p>CSS docs based on your config</p>
</li>
<li><p>Apply variants to multiple styles at once</p>
</li>
<li><p>No need for additional editor extensions</p>
</li>
<li><p>Catches errors at compile time</p>
</li>
</ul>
<p>Typewind, generated type definitions on Tailwind classes custom to your app's <code>tailwind.config.js</code> after running the <code>npx typewind generate</code> command.</p>
<p>Typewind has currently been tested to work with Vite (React) and Next.JS and you can find them in the <a target="_blank" href="https://typewind.vercel.app/docs/examples/vite">examples</a>.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>The <a target="_blank" href="https://typewind.vercel.app/docs/installation">installation page in the docs</a> is a very good place to start with Typewind.</p>
<h3 id="heading-installation">Installation</h3>
<p>Install via your favourite package manager (npm/yarn/pnpm).</p>
<pre><code class="lang-bash">npm install typewind
</code></pre>
<h3 id="heading-generate-type-definitions">Generate Type Definitions</h3>
<pre><code class="lang-bash">npx typewind generate
</code></pre>
<p>This will go through your <code>tailwind.config.js</code> and generate types and css docs custom to your app.</p>
<h3 id="heading-setup-with-nextjs">Setup with Next.JS</h3>
<p>After setting up <a target="_blank" href="https://tailwindcss.com/docs/installation">Tailwind</a>, make the following changes:</p>
<ol>
<li>Add a <code>.babelrc</code> with the following contents:</li>
</ol>
<pre><code class="lang-json">{
  <span class="hljs-attr">"presets"</span>: [<span class="hljs-string">"next/babel"</span>],
  <span class="hljs-attr">"plugins"</span>: [<span class="hljs-string">"typewind/babel"</span>]
}
</code></pre>
<ol>
<li>Add transformer to your Tailwind Config</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { typewindTransforms } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'typewind/transform'</span>);

<span class="hljs-comment">/** @type {import('tailwindcss').Config} \*/</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">content</span>: {
    <span class="hljs-attr">files</span>: [<span class="hljs-string">'./src/**/*.{js,jsx,ts,tsx}'</span>],
    <span class="hljs-attr">transform</span>: typewindTransforms,
  },
};
</code></pre>
<p>And you're good to go! Just run <code>npm run dev</code> next time and you should be able to use Typewind inside your app.</p>
<h3 id="heading-setup-with-vite">Setup with Vite</h3>
<p>Make the same change in the <code>tailwind.config.js</code> file as mentioned in the NextJS example, but the babel change has to be done in the <code>vite.config.js</code> like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>;
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>;

<span class="hljs-comment">// https://vitejs.dev/config/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: [react({ <span class="hljs-attr">babel</span>: { <span class="hljs-attr">plugins</span>: [<span class="hljs-string">'typewind/babel'</span>] } })],
});
</code></pre>
<p>And, you'll be done setting up Typewind in your Vite application.</p>
<h2 id="heading-usage">Usage</h2>
<p>Here's just a trailer to show you what it's capable of:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { tw } <span class="hljs-keyword">from</span> <span class="hljs-string">'typewind'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;div
      className={tw.flex.items_center.justify_center.h_screen.bg_white.text_[<span class="hljs-string">"#333"</span>].dark(tw.bg_black.text_white)}&gt;
      &lt;h1 className={tw.text_xl.sm(tw.text_3xl).md(tw.text_4xl).font_bold}&gt;
        Hello World
      &lt;/h1&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h3 id="heading-applying-normal-tailwind-classes">Applying Normal Tailwind Classes</h3>
<p>All the utility tailwind classes are available in the <code>tw</code> proxy, and can be chained one after another. They can be found in the <a target="_blank" href="https://tailwindcss.com/docs/utility-first">Tailwind Docs</a>. The <code>-</code> in the tailwind classes are replaced with <code>_</code> (for eg. <code>bg-red-500</code> can be accessed as <code>tw.bg_red_500</code>)</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { tw } <span class="hljs-keyword">from</span> <span class="hljs-string">'typewind'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Button</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;button className={tw.bg_blue_500.text_white.rounded.py_3.px_4}&gt;
      Click Me
    &lt;/button&gt;
  );
}
</code></pre>
<h3 id="heading-applying-tailwind-modifiers">Applying Tailwind Modifiers</h3>
<p><a target="_blank" href="https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-classes">Pseudo-classes</a> like <code>:hover</code> and <code>:focus</code>, <a target="_blank" href="https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-elements">Pseudo-elements</a> like <code>::before</code>, <code>::after</code>, <code>::placeholder</code> and <code>::selection</code>, <a target="_blank" href="https://tailwindcss.com/docs/hover-focus-and-other-states#media-and-feature-queries">Media and feature queries</a> and <a target="_blank" href="https://tailwindcss.com/docs/hover-focus-and-other-states#attribute-selectors">Attribute Selectors</a> are available as a function (for eg. <code>:hover</code> can be accessed as <code>tw.hover(tw.some_class)</code> )</p>
<p>Typewind also have a <code>dark</code> function which is used to apply styles when the user is in dark mode.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { tw } <span class="hljs-keyword">from</span> <span class="hljs-string">'typewind'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Button</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;button
      className={tw.bg_blue_500
        .hover(tw.bg_blue_600)
        .text_white.rounded.py_3.px_4.md(tw.py_4.px_5)
        .dark(tw.bg_sky_900.hover(tw.bg_sky_800))}
    &gt;
      Click Me
    &lt;/button&gt;
  );
}
</code></pre>
<blockquote>
<p>Note that Typewind does not have <code>tw.2xl()</code> but has <code>tw._2xl()</code> because object keys cannot start with a number 🫠</p>
</blockquote>
<h3 id="heading-applying-tailwind-arbitrary-values">Applying Tailwind Arbitrary Values</h3>
<p>Tailwind JIT Mode introduced the feature of arbitrary values. You could now apply classes like <code>bg-[#2977f5]</code> and specify arbitrary values for classes by yourself. This can be done with Typewind as well!</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { tw } <span class="hljs-keyword">from</span> <span class="hljs-string">'typewind'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    &lt;button className={tw.text_[<span class="hljs-string">'20px'</span>].py_3.px_4.bg_blue_500}&gt;Click Me&lt;/button&gt;
  );
}
</code></pre>
<h2 id="heading-why-typewind-over-tailwind-intellisense">Why Typewind over Tailwind Intellisense?</h2>
<p>This has been answered by Mokshit in this tweet:</p>
<p><a target="_blank" href="https://twitter.com/Mokshit06/status/1617506874773082112?s=20&amp;t=erkUIb_bUjty0KfXzGlrDw">https://twitter.com/Mokshit06/status/1617506874773082112?s=20&amp;t=erkUIb_bUjty0KfXzGlrDw</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674663639622/c6b3ec29-49d6-444e-8150-c40706500d22.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-outro">Outro</h2>
<p>Hope this gets you interested in getting started with Typewind, and gets you to use it in your next project!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/mokshit06/typewind">https://github.com/mokshit06/typewind</a></div>
]]></content:encoded></item><item><title><![CDATA[Dev Retro 2022, A Flashback to my life as a developer this past year]]></title><description><![CDATA[For those who don't know me, I am Kavin, and I am a high schooler from Delhi, India. I have been programming for the past 2-3 years and have been in love with Web Development ever since. The past year has been a great one for me as a developer, and h...]]></description><link>https://livecode247.com/dev-retro-2022-a-flashback-to-my-life-as-a-developer-this-past-year</link><guid isPermaLink="true">https://livecode247.com/dev-retro-2022-a-flashback-to-my-life-as-a-developer-this-past-year</guid><category><![CDATA[#DevRetro2022]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Students]]></category><category><![CDATA[High-School Experience]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Thu, 08 Dec 2022 09:38:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670492002064/3QFMz99k-.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For those who don't know me, I am Kavin, and I am a high schooler from Delhi, India. I have been programming for the past 2-3 years and have been in love with Web Development ever since. The past year has been a great one for me as a developer, and here's that in a nutshell. View more about me, <a target="_blank" href="https://kavin.me">here</a>.</p>
<h2 id="heading-january-2022">January 2022</h2>
<p>In January 2022, my school's technology club, Exun Clan had our annual symposium Exun 2021-22 from January 14-21. During that, we decided to use Laravel for our cryptic hunt, <a target="_blank" href="https://github.com/kavinvalli/sudocrypt-v11">Sudocrypt v11.0</a>. I had no experience with Laravel or even PHP, for that matter, but one of my <a target="_blank" href="https://github.com/dotangad">seniors</a> had already used Laravel on a cryptic hunt, <a target="_blank" href="https://github.com/dotangad/cryptocracy-v2">Cryptocracy</a> before, and since the codebase was very similar to AdonisJS, which I had some experience with, in around a couple weeks, I went through the codebase, and plucked out the parts which we to be reused and came up with a completely unstyled app which worked.<br />With the help of a few designers, we styled the website, created an admin portal, etc and came up with a platform which handled 1500+ participants from 10+ countries, 50k+ attempts, and 4.5k+ levels solved.</p>
<p>I also had hands-on experience in holding an event/hackathon for the first time.</p>
<p>After the event, I had to write a script which went through the participant's data and generated certificates for all the participants and emailed them. In the process, I got some experience with Pillow.</p>
<h2 id="heading-february-2022">February 2022</h2>
<p>There wasn't much programming-wise, I did in February, but I tinkered around a lot with Neovim and my developer setup. I also wrote a blog post on it <a target="_blank" href="https://livecode247.com/my-developer-setup-in-2022">here</a>.</p>
<h2 id="heading-march-2022">March 2022</h2>
<p>March was a time when I got into technical writing a lot and consistently posted articles for a while. I posted articles on <a target="_blank" href="https://livecode247.com/start-a-web-server-with-nodejs-and-express">ExpressJS</a>, played around with <a target="_blank" href="https://livecode247.com/how-to-show-code-diffs-in-your-hashnode-blog">Hashnode's Custom CSS</a>, <a target="_blank" href="https://livecode247.com/deploying-a-static-html-and-css-site-using-github-pages">Github Pages</a>, React's <a target="_blank" href="https://livecode247.com/beginners-guide-to-usestate-hook-in-react">useState</a> and <a target="_blank" href="https://livecode247.com/beginners-guide-to-useeffect-hook-in-react">useEffect</a> hooks, and also on <a target="_blank" href="https://livecode247.com/how-to-implement-dark-mode-using-tailwindcss">Tailwind's Dark Mode</a>.</p>
<p>I also gave <a target="_blank" href="https://remix.run">RemixJS</a> and watched a lot of <a target="_blank" href="https://www.youtube.com/@KentCDodds-vids">Kent C. Dodds'</a> streams and read <a target="_blank" href="https://kentcdodds.com/">his blog posts</a> and got interested in Remix and its fundamentals. I also wrote a blog post on that <a target="_blank" href="https://livecode247.com/i-built-a-link-shortener-using-remix-and-heres-my-experience">here</a>.</p>
<h2 id="heading-april-2022">April 2022</h2>
<p>I had my exams March end till April and given that I didn't study the whole past year, this was a time I had to get off my computer ;)</p>
<h2 id="heading-may-2022">May 2022</h2>
<p>I had to learn Java, during this time to write my AP CS A, well which turned out not very tough, but still not something I'd write willingly.</p>
<h2 id="heading-june-2022">June 2022</h2>
<p>In June 2022, we at Exun Clan, conducted our annual inductions for the club in our school and conducted various workshops throughout the month and then tasks for the participant to prove themselves for getting inducted. I conducted a session on ReactJS, going through the basics of React and creating a couple of basic apps on the way.</p>
<p>I also wrote a platform, <a target="_blank" href="https://practice.sudocrypt.com">practice.sudocrypt.com</a> to help the students of my school get started with Cryptic Hunts, and along with the Cryptic hunt department of Exun Clan, we compiled an archive of previous year levels and uploaded them onto the site.</p>
<h2 id="heading-july-2022">July 2022</h2>
<p>In July, I participated in a high school creative event (combined Designathon, Hackathon and Pitching), where we created an app which offered a way to transfer your progress across multiple metaverses by retaining common assets, thereby paving a way to connect the different metaverses.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/comets">https://github.com/kavinvalli/comets</a></div>
<p> </p>
<h2 id="heading-august-2022">August 2022</h2>
<p>In early August, I was appointed the President of my school's technology club. During this time, my school also had 50-year celebrations. For this, I worked on a QR Code based entry system where-in each alumnus and student who registered for the event received a QR Code from our side which when scanned upon entry by a custom app would mark them as attended in our database. We were also able to track the number of people who attended with them. The app was used to scan over 2000+ QR codes over two days.</p>
<p>This project allowed me to finally use Flutter in an actual app, and the fact that I had to use PHP, Typescript, Python and Dart all in one project makes it a very memorable one.</p>
<h2 id="heading-september-2022">September 2022</h2>
<p>In September, I had my half-yearlies right after which a company, <a target="_blank" href="http://speechify.com/">Speechify</a> approached me. Unfortunately, I couldn't clear the interview, but it gave me a lot of experience and ideas on what skills to work on more.</p>
<h2 id="heading-october-2022">October 2022</h2>
<p>On October 1-2, I participated in the NASA Space Apps Challenge, where my team and I built Liberty, a browser-based 3D visualisation of the International Space Station in Realtime. This project won us second place in the Regional Round among 90+ teams and qualified us for the Global Round. We were awarded the Global Finalists Honourable Mention which was awarded to the top 80 teams from around 55000+ teams from all around the world.</p>
<p>You can find our project <a target="_blank" href="https://space-apps-eosin.vercel.app/">here</a> and our submission <a target="_blank" href="https://2022.spaceappschallenge.org/challenges/2022-challenges/track-the-iss/teams/spaced-out/project">here</a>.</p>
<p>This project allowed me to get into 3D in the browser and read a lot about ThreeJS(which we ended up not using), and CesiumJS and even had some experience with Rust and WASM(which my teammate used in the app).</p>
<h2 id="heading-november-2022">November 2022</h2>
<p>In November, we at Exun Clan conducted our annual symposium, Exun 2022, and after two years, we planned to now conduct it in a hybrid mode. The event was a success and had over 22000+ participants from around the world. Conducting an offline event and meeting so many people was a refreshing change after seeing faces across zoom meets for the past two years.</p>
<p>We completely revamped our website at <a target="_blank" href="https://exunclan.com">exunclan.com</a> using NextJS and TailwindCSS.</p>
<p>I also participated in Tiger Hacks 2022, where we created a product which aimed to solve the issue of over/under-inflation of tyres and hence reduce the road risks associated with them, elongating the lifetime of tyres, making car rides more enjoyable and saving fuel at the same time. We aimed to take into all the environmental factors that cause the internal pressure of the tyre to change and exceed the safety limits, quickly alert the user of the safety concerns using Twilio SMS and notification and then adapt the pressure of the tyres automatically to the conditions.<br />We built a software prototype for all this using Next.JS, OpenWeather API, Mapbox API, etc. and this also gave me a refreshment on my Grade 11 chemistry, having to read about Gay Lussac's Law and how pressure is affected by factors like temperature, speed of a car, etc.</p>
<p>November was also a time, I got really into the T3 stack by Theo, and learnt a lot more about tRPC. The announcement of Next13 made things very interesting for the Javascript ecosystem. I wrote an article on the T3 stack <a target="_blank" href="https://livecode247.com/why-t3-stack">here</a> which gained a lot of attention and also was my first article which got featured on Hashnode.</p>
<h2 id="heading-december-2022">December 2022</h2>
<p>Well, December just started, but I decided to give Rust a try while attempting to do <a target="_blank" href="https://adventofcode.com">Advent of Code</a>, which is a pain because I'm having to learn a lot more about memory management, the Borrow Checker and so many more concepts which were not familiar to me as a Javascript Developer.</p>
<p>I also made a <a target="_blank" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot">self-hosting discord bot</a> which shows your Private Advent of Code Leaderboards on your discord servers. Discord.js as handy as it is doesn't have very good documentation on its types, so writing this bot in Typescript was a little bit of a rollercoaster ride but was a very good experience. You can find more about it <a target="_blank" href="https://livecode247.com/discord-bot-which-shows-your-private-advent-of-code-leaderboard">here</a>.</p>
<p>A friend of mine, <a target="_blank" href="https://mokshitjain.co/">Mokshit Jain</a> recently released <a target="_blank" href="https://macaron.js.org/">Macaron</a>, a Typesafe CSS-in-JS with zero runtime, colocation, maximum safety and productivity. Macaron is a new compile-time CSS-in-JS library with type safety. Because of this, I got an opportunity to read more about build tools like babel, vite, esbuild, etc. So, learning more about them is on my todo-list for the coming year. Helping with the docs, I found out about <a target="_blank" href="https://codehike.org/">Code Hike</a> which seemed very impressive. It did have a few issues for me, because of which I had to go through the source code and find out type definitions and their working to get stuff working.</p>
<h2 id="heading-outro">Outro</h2>
<p>A lot more to come for the rest of the month and the next year, when I'll probably be in college, excited to go more in-depth into something I love. I will keep posting articles, and get more into technical writing. Hopefully, learning Rust will get easier as I go on, and might be something I end up using more.</p>
<p>I'm also participating in <a target="_blank" href="https://epoch.hackclub.com/">Epoch</a> from Dec 30 to Jan 1, a hackathon by <a target="_blank" href="https://hackclub.com">Hack Club</a> for high schoolers from all around the world, and am excited to be part of such a big event.</p>
]]></content:encoded></item><item><title><![CDATA[Discord bot which shows your private Advent of Code leaderboard]]></title><description><![CDATA[It is December! That means Advent of Code is here! If you don't know what that is:

Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like...]]></description><link>https://livecode247.com/discord-bot-which-shows-your-private-advent-of-code-leaderboard</link><guid isPermaLink="true">https://livecode247.com/discord-bot-which-shows-your-private-advent-of-code-leaderboard</guid><category><![CDATA[AdventOfCode2022]]></category><category><![CDATA[Discord bot]]></category><category><![CDATA[discord.js]]></category><category><![CDATA[bot]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Sat, 03 Dec 2022 12:31:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670070624321/QD5kTVTpO.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is December! That means <a target="_blank" href="https://adventofcode.com">Advent of Code</a> is here! If you don't know what that is:</p>
<blockquote>
<p><em>Advent of Code</em> is an <a target="_blank" href="https://en.wikipedia.org/wiki/Advent_calendar">Advent calendar</a> of small programming puzzles for a variety of skill sets and skill levels that can be solved in <a target="_blank" href="https://github.com/search?q=advent+of+code">any</a> programming language you like. People use them as <a target="_blank" href="https://y3l2n.com/2018/05/09/interview-prep-advent-of-code/">interview</a> <a target="_blank" href="https://twitter.com/dznqbit/status/1037607793144938497">prep</a>, <a target="_blank" href="https://twitter.com/pgoultiaev/status/950805811583963137">company training</a>, <a target="_blank" href="https://gitlab.com/imhoffman/fa19b4-mat3006/wikis/home">university</a> <a target="_blank" href="https://gribblelab.org/teaching/scicomp2021/index.html">coursework</a>, <a target="_blank" href="https://twitter.com/mrdanielklein/status/936267621468483584">practice</a> <a target="_blank" href="https://comp215.blogs.rice.edu/">problems</a>, a <a target="_blank" href="https://adventofcode.com/leaderboard">speed contest</a>, or to <a target="_blank" href="https://www.reddit.com/r/adventofcode/search?q=flair%3Aupping&amp;restrict_sr=on">challenge each other</a>.</p>
</blockquote>
<h2 id="heading-idea-inspiration">Idea Inspiration</h2>
<p>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!</p>
<p>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 <a target="_blank" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot">this discord bot.</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670070115711/nQrVJmO0d.png" alt /></p>
<h2 id="heading-setup">Setup</h2>
<p>The bot is very easy to set up and get up and running on your server. Follow the instructions on the <a target="_blank" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot#setup">GitHub README</a> and you will be up and running in no time.</p>
<h2 id="heading-deployment">Deployment</h2>
<p>To deploy the app on an EC2, GCP Instance, etc. use <a target="_blank" href="https://pm2.keymetrics.io/">pm2</a> like mentioned <a target="_blank" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot#deployment">here</a>.</p>
<h2 id="heading-github">GitHub</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot">https://github.com/kavinvalli/aoc-private-lb-discord-bot</a></div>
<p> </p>
<p>Check out the GitHub Repository linked above and you will find all the instructions on how to get up and running with the bot.</p>
<p>Feel free to also point out any <a target="_blank" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot/issues">issues</a>, any <a target="_blank" href="https://github.com/kavinvalli/aoc-private-lb-discord-bot/pulls">PRs</a> are welcome and be sure to star the repo!</p>
]]></content:encoded></item><item><title><![CDATA[Why I think the t3 stack is the next big thing in the JS... oh wait... the TS ecosystem?]]></title><description><![CDATA[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 t...]]></description><link>https://livecode247.com/why-t3-stack</link><guid isPermaLink="true">https://livecode247.com/why-t3-stack</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[APIs]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Tailwind CSS]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Sat, 26 Nov 2022 11:44:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1669460962541/Vz2MyfxpW.png?auto=compress" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>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.</p>
<h2 id="heading-what-is-the-t3-stack">What is the T3 Stack?</h2>
<p>Quoting the website, <em>"We made create-t3-app to do one thing: Streamline the setup of typesafe Next.js apps WITHOUT compromising modularity"</em> 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:</p>
<ul>
<li><a target="_blank" href="https://nextjs.org/">Next.JS</a></li>
<li><a target="_blank" href="https://trpc.io">tRPC</a></li>
<li><a target="_blank" href="https://tailwindcss.com/">Tailwind CSS</a></li>
<li><a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a></li>
<li><a target="_blank" href="https://prisma.io/">Prisma</a></li>
<li><a target="_blank" href="https://next-auth.js.org/">NextAuth.js</a></li>
</ul>
<h2 id="heading-nextjs">Next.JS</h2>
<p>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.</p>
<blockquote>
<p>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.</p>
</blockquote>
<h2 id="heading-trpc">tRPC</h2>
<p>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.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1669463382785/w8FtiYvRr.png?auto=compress" alt="Why tRPC" /></p>
<p>You can read more about tRPC at <a target="_blank" href="https://trpc.io">trpc.io</a>.</p>
<h2 id="heading-tailwind-css">Tailwind CSS</h2>
<p>For those, who don't know what Tailwind is, I have a blog post on it and how to
get started with tailwind <a target="_blank" href="https://livecode247.com/start-with-your-first-tailwind-css-project">here</a>.</p>
<h2 id="heading-typescript">TypeScript</h2>
<p>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.</p>
<blockquote>
<p>Typesafety makes you faster. If you’re not convinced, <a target="_blank" href="https://www.youtube.com/watch?v=RmGHnYUqQ4k">you might be using TypeScript wrong…</a></p>
</blockquote>
<h2 id="heading-prisma">Prisma</h2>
<p>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.</p>
<h2 id="heading-nextauth">NextAuth</h2>
<p>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.</p>
<h2 id="heading-why-i-recommend-the-t3-stack">Why I recommend the T3 stack?</h2>
<p>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.</p>
<p><code>create-t3-app</code> makes it easier to manage the <em>modularity and simplivity</em> in code while starting off. It just doesn't add everything.</p>
<blockquote>
<p>Everything added to create-t3-app should solve a specific problem that exists within the core technologies included. This means we won’t add things like state libraries (zustand, redux) but we will add things like NextAuth.js and integrate Prisma and tRPC for you.</p>
</blockquote>
<h2 id="heading-resources-to-get-started-with-the-t3-stack">Resources to get started with the T3 stack</h2>
<ul>
<li><a target="_blank" href="https://create.t3.gg/en/introduction">Create T3 App Documentation</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=PbjHxIuHduU"><strong>The BEST Stack For Your Next Project</strong> Video</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=syEWlxVFUrY"><strong>Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma, Zod</strong> Video</a></li>
</ul>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://trpc.io/">trpc.io</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=2LYM8gf184U">Chris Bautista: Making typesafe APIs easy with tRPC</a></li>
<li><a target="_blank" href="https://github.com/t3-oss/create-t3-app">create.t3.gg Github</a></li>
<li><a target="_blank" href="https://create.t3.gg">create.t3.gg</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to implement dark mode using TailwindCSS?]]></title><description><![CDATA[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 i...]]></description><link>https://livecode247.com/how-to-implement-dark-mode-using-tailwindcss</link><guid isPermaLink="true">https://livecode247.com/how-to-implement-dark-mode-using-tailwindcss</guid><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[CSS]]></category><category><![CDATA[UI]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Wed, 23 Mar 2022 02:41:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/G9i_plbfDgk/upload/v1661698825364/C-IIH28wC.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>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.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>You should have a basic knowledge of Tailwind CSS.</li>
<li>You should know a little Javascript to understand how the theme toggle works.</li>
</ul>
<h2 id="heading-setup">Setup</h2>
<p>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 <a target="_blank" href="https://tailwindcss.com/docs/installation/framework-guides">here</a>.
I will be using it using <a target="_blank" href="https://npmjs.com">npm</a> without any bundler and with just HTML.</p>
<h3 id="heading-create-folder">Create folder</h3>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">mkdir dark-mode-tailwindcss
<span class="hljs-built_in">cd</span> dark-mode-tailwindcss
npm init -y
</code></pre>
<p>You will see something like this
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647970911855/BYRjDSthc.png" alt="Npm Init Output" /></p>
<h3 id="heading-install-tailwind">Install Tailwind</h3>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">npm i -D tailwindcss
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647971509837/rP7WOvfJD.png" alt="Install Tailwind" /></p>
<h3 id="heading-setup-tailwind">Setup Tailwind</h3>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">npx tailwindcss init
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647971553683/iSQO_vkc2.png" alt="Initialize Tailwind Config" /></p>
<p>Open <code>tailwind.config.js</code> and make the following change:</p>
<div class="code-metadata">
tailwind.config.js
</div>

<pre><code class="lang-diff"><span class="hljs-deletion">-  content: [],</span>
<span class="hljs-addition">+  content: ['./**/*.html'],</span>
</code></pre>
<p>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</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">touch index.html
</code></pre>
<h3 id="heading-when-to-use-dark-mode">When to use Dark Mode?</h3>
<p>Now, tailwind supports two ways of using Dark Mode. One is <code>prefers-color-scheme</code> and one is using <code>classes</code>. 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 <code>dark</code> 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 <code>prefers-color-scheme</code> mode is used by default. To use <code>class</code> based mode you need to add the following line in <code>tailwind.config.js</code></p>
<div class="code-metadata">
tailwind.config.js
</div>

<pre><code class="lang-diff">module.exports = {
<span class="hljs-addition">+  darkMode: 'class',</span>
   ...
}
</code></pre>
<h3 id="heading-setup-tailwind-css-file">Setup tailwind css file</h3>
<p>Create a src directory with the tailwind css file</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">mkdir -p src/css
touch src/css/tailwind.css
</code></pre>
<p>and add the following contents to it</p>
<div class="code-metadata">
src/css/tailwind.css
</div>

<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> utilities;
<span class="hljs-keyword">@tailwind</span> components;
</code></pre>
<h3 id="heading-setup-css-build-commands">Setup css build commands</h3>
<p>In your package.json make the following changes</p>
<div class="code-metadata">
package.json
</div>

<pre><code class="lang-diff">...
  "scripts": {
<span class="hljs-deletion">-    "test": "echo \"Error: no test specified\" &amp;&amp; exit 1"</span>
<span class="hljs-addition">+    "css:build": "tailwindcss -i src/css/tailwind.css -o dist/css/tailwind.css",</span>
<span class="hljs-addition">+    "css:watch": "tailwindcss -i src/css/tailwind.css -o dist/css/tailwind.css --watch"</span>
  },
...
</code></pre>
<p>And then run</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">npm run css:watch
</code></pre>
<h2 id="heading-setup-html">Setup html</h2>
<div class="code-metadata">
index.html
</div>

<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"./dist/css/tailwind.css"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Tailwind Dark Mode<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>


  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>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.</p>
<p>I'm gonna setup a basic html site like so:</p>
<div class="code-metadata">
index.html
</div>

<pre><code class="lang-html">  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"h-screen w-full bg-gray-100 dark:bg-gray-800 flex justify-center items-center"</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-white text-gray-800 rounded-lg p-4 text-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl font-bold"</span>&gt;</span>Tailwind Dark Mode<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a demo of Tailwind CSS Dark Mode.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute bottom-5 right-5 w-10 h-10 rounded-full bg-gray-800 flex justify-center items-center text-white"</span>
        <span class="hljs-attr">id</span>=<span class="hljs-string">"theme-toggle"</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
          <span class="hljs-attr">width</span>=<span class="hljs-string">"24"</span>
          <span class="hljs-attr">height</span>=<span class="hljs-string">"24"</span>
          <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span>
          <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span>
          <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
            <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
            <span class="hljs-attr">clip-rule</span>=<span class="hljs-string">"evenodd"</span>
            <span class="hljs-attr">d</span>=<span class="hljs-string">"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"</span>
            <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./src/js/index.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>Should show you something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648001444406/BoMaWJfSu.png" alt="Starting HTML" /></p>
<blockquote>
<p>I'm using the <a target="_blank" href="https://npmjs.org/serve">serve</a> package by <a target="_blank" href="https://vercel.com">Vercel</a> to serve my html. Just run <code>npx serve</code> from your project directory.</p>
</blockquote>
<h2 id="heading-javascript">Javascript</h2>
<p>We'll be needing a little bit of javascript to manage the dark mode.
Add this in the <code>index.html</code> file:</p>
<div class="code-metadata">
index.html
</div>

<pre><code class="lang-diff">...
<span class="hljs-addition">+    &lt;script src="./src/js/index.js"&gt;&lt;/script&gt;</span>
  &lt;/body&gt;
...
</code></pre>
<p>Now, create an index.js file</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">mkdir src/js
touch src/js/index.js
</code></pre>
<p>Add the following to the <code>index.js</code> file.</p>
<div class="code-metadata">
src/js/index.js
</div>

<pre><code class="lang-js"><span class="hljs-keyword">const</span> themeToggleButton = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"theme-toggle"</span>);

<span class="hljs-keyword">const</span> MOON_SVG = <span class="hljs-string">`&lt;svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"&gt;&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" /&gt;&lt;/svg&gt;`</span>;
<span class="hljs-keyword">const</span> SUN_SVG = <span class="hljs-string">`&lt;svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"&gt;&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" /&gt;&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" /&gt;&lt;/svg&gt;`</span>;

<span class="hljs-keyword">let</span> theme = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">"T_SITE_THEME"</span>) || <span class="hljs-string">"light"</span>;
theme === <span class="hljs-string">"light"</span> ? setLightTheme() : setDarkTheme();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setDarkTheme</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">document</span>.body.classList.add(<span class="hljs-string">"dark"</span>);
  themeToggleButton.innerHTML = SUN_SVG;
  <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">"T_SITE_THEME"</span>, <span class="hljs-string">"dark"</span>);
  theme = <span class="hljs-string">"dark"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setLightTheme</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">document</span>.body.classList.remove(<span class="hljs-string">"dark"</span>);
  themeToggleButton.innerHTML = MOON_SVG;
  <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">"T_SITE_THEME"</span>, <span class="hljs-string">"light"</span>);
  theme = <span class="hljs-string">"light"</span>;
}

themeToggleButton.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">if</span> (theme === <span class="hljs-string">"light"</span>) {
    setDarkTheme();
  } <span class="hljs-keyword">else</span> {
    setLightTheme();
  }
});
</code></pre>
<p>Ok, so let's go over this file and what it is doing.</p>
<ol>
<li>On line 1 - We're querying the toggle theme button from the dom</li>
<li>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.</li>
<li>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.</li>
<li>On line 6 - Based on the theme, i'm either setting dark mode or light mode.</li>
<li>In the <code>setDarkTheme</code> function - I'm first of all, adding the <code>dark</code> 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 <code>theme</code> variable to dark.</li>
<li>In the <code>setLightTheme</code> function - We're doing everything opposite to that in the <code>setDarkTheme</code> function.</li>
<li>From lines 17 to 23 - We're handling the <code>click</code> event on the toggle theme button and setting dark mode or light mode accordingly.</li>
</ol>
<h2 id="heading-tailwind-dark-variant">Tailwind <code>dark</code> variant.</h2>
<p>Now, how do we tell Tailwind to use which class in dark mode and which class in light mode? We do that using the <code>dark</code> variant which it provides us. For example, in the first div element on the page (just below the body tag), add this class:</p>
<div class="code-metadata">
index.html
</div>

<pre><code class="lang-diff"><span class="hljs-deletion">-    &lt;div class="h-screen w-full bg-gray-100 flex justify-center items-center"&gt;</span>
<span class="hljs-addition">+    &lt;div class="h-screen w-full bg-gray-100 dark:bg-gray-800 flex justify-center items-center"&gt;</span>
</code></pre>
<p>And checkout what happens when you refresh the site on the browser and click on the toggle theme button!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648002509526/GFTuxmzY-.png" alt="First view of dark mode" /></p>
<p>Notice the changes:</p>
<ol>
<li>The background color changes.</li>
<li>If you inspect the body element, you will see a <code>dark</code> class on it.</li>
<li>The localStorage <code>T_SITE_THEME</code> value changes to <code>dark</code></li>
<li>The svg inside the toggle theme button changes</li>
</ol>
<p>Now, click on the button again:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648002594741/SGaPyyHtg.png" alt="Light Mode Again" /></p>
<p>Let's make a few changes in out html now:</p>
<div class="code-metadata">
index.html
</div>

<pre><code class="lang-diff"><span class="hljs-deletion">-      &lt;div class="bg-white text-gray-800 rounded-lg p-4 text-center"&gt;</span>
<span class="hljs-addition">+      &lt;div class="bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 rounded-lg p-4 text-center"&gt;</span>
...
<span class="hljs-deletion">-      &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"&gt;</span>
<span class="hljs-addition">+      &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"&gt;</span>
</code></pre>
<p>Now your html should look like this:</p>
<div class="code-metadata">
index.html
</div>

<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"dist/css/tailwind.css"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Tailwind Dark Mode<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"h-screen w-full bg-gray-100 dark:bg-gray-800 flex justify-center items-center"</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 rounded-lg p-4 text-center"</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-2xl font-bold"</span>&gt;</span>Tailwind Dark Mode<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a demo of Tailwind CSS Dark Mode.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">class</span>=<span class="hljs-string">"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"</span>
        <span class="hljs-attr">id</span>=<span class="hljs-string">"theme-toggle"</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span>
          <span class="hljs-attr">width</span>=<span class="hljs-string">"24"</span>
          <span class="hljs-attr">height</span>=<span class="hljs-string">"24"</span>
          <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span>
          <span class="hljs-attr">fill</span>=<span class="hljs-string">"none"</span>
          <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
            <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
            <span class="hljs-attr">clip-rule</span>=<span class="hljs-string">"evenodd"</span>
            <span class="hljs-attr">d</span>=<span class="hljs-string">"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"</span>
            <span class="hljs-attr">fill</span>=<span class="hljs-string">"currentColor"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./src/js/index.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>and the site like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1648002949928/aAvyYUX3F.png" alt="Final Dark Mode" />
The repository below has all the code used in this article</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/dark-mode-tailwindcss">https://github.com/kavinvalli/dark-mode-tailwindcss</a></div>
]]></content:encoded></item><item><title><![CDATA[Beginner's guide to useEffect hook in React]]></title><description><![CDATA[A few days ago, I wrote an article on how to use the useState hook. Another important hook provided by React is the useEffect hook.
Now, if you've used React Class based Components, then useEffect will help you replace functions like componentDidMoun...]]></description><link>https://livecode247.com/beginners-guide-to-useeffect-hook-in-react</link><guid isPermaLink="true">https://livecode247.com/beginners-guide-to-useeffect-hook-in-react</guid><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Sun, 13 Mar 2022 09:35:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/UYsBCu9RP3Y/upload/v1647164086842/gPNe96ffp.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few days ago, I wrote an <a target="_blank" href="https://livecode247.com/react-hooks-usestate">article</a> on how to use the <code>useState</code> hook. Another important hook provided by React is the <code>useEffect</code> hook.
Now, if you've used React Class based Components, then useEffect will help you replace functions like <code>componentDidMount</code>, <code>componentDidUpdate</code>, etc.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Basic knowledge of ReactJS</li>
</ul>
<h2 id="heading-how-to-use">How to use?</h2>
<p><strong>useEffect</strong> takes in two arguments. A function, and an array of dependencies like so:</p>
<pre><code class="lang-js">useEffect(<span class="hljs-function"><span class="hljs-keyword">function</span>, [<span class="hljs-title">dependencies</span>])</span>
</code></pre>
<p>Let's start with the function argument</p>
<h3 id="heading-function-argument">Function Argument</h3>
<p>Let's use the example I used in the <a target="_blank" href="https://livecode247.com/react-hooks-usestate"><code>useState</code> article.</a></p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">1</span>);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">incrementCount</span>(<span class="hljs-params"></span>) </span>{
    setCount(count + <span class="hljs-number">1</span>);
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{incrementCount}</span>&gt;</span>Increase counter<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Will give you something like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647157136178/xK6nuq4XB.png" alt="Starting App" /></p>
<p>Now make these code:</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-diff"><span class="hljs-deletion">- import { useState } from "react";</span>
<span class="hljs-addition">+ import { useState, useEffect } from "react";</span>
...
    const [count, setCount] = useState(1);
<span class="hljs-addition">+   useEffect(() =&gt; {</span>
<span class="hljs-addition">+    console.log("useEffect running");</span>
<span class="hljs-addition">+   });</span>
...
</code></pre>
<p>Now, go to the browser, refresh the page, open up dev tools and move to console window</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647157327768/Cwu7Go2wG.png" alt="useEffect first" /></p>
<p>Looks like it's working! But WAIT. Try clicking on the button and notice what happens:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647157446237/fS_Pg0Cdt.png" alt="useEffect on re-render" /></p>
<p>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.</p>
<h3 id="heading-replacement-for-componentdidmount">Replacement for <code>componentDidMount</code></h3>
<p>What if you want to run it only when the component mounts for the first time (like componentDidMount did). This is where the <code>dependency</code> argument comes into play. Make this change</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-diff"><span class="hljs-deletion">-  useEffect(() =&gt; {</span>
<span class="hljs-deletion">-    console.log("useEffect running");</span>
<span class="hljs-deletion">-  });</span>
<span class="hljs-addition">+  useEffect(() =&gt; {</span>
<span class="hljs-addition">+    console.log("useEffect running");</span>
<span class="hljs-addition">+  }, []);</span>
</code></pre>
<p>You're passing in an empty array of dependencies. This basically means, run the useEffect loop only on first render.</p>
<blockquote>
<p>There is however still one difference between this and <code>componentDidMount</code>. <code>useEffect(fn, [])</code> runs after the first render to the DOM whereas <code>componentDidMount</code> runs after "mounting" the component but before it is actually rendered(shown) in the DOM.</p>
</blockquote>
<h3 id="heading-run-depending-on-a-value">Run depending on a value</h3>
<p>What if you want to run useEffect when a certain value changes. For eg. add this</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-diff">  const [count, setCount] = useState(1);
<span class="hljs-addition">+ const [isDark, setIsDark] = useState(false);</span>
...
   &lt;button onClick={incrementCount}&gt;Increase counter&lt;/button&gt;
<span class="hljs-addition">+  &lt;button onClick={() =&gt; setIsDark(!isDark)}&gt;Toggle isDark&lt;/button&gt;</span>
</code></pre>
<p>Let's take that counter <code>p</code> tag to a different component for demonstration purposes</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params">{count}</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
}
</code></pre>
<div class="code-metadata">
src/App.js
</div>


<pre><code class="lang-diff">...
&lt;div&gt;
   &lt;h1&gt;Hello, World&lt;/h1&gt;
<span class="hljs-deletion">-  &lt;p&gt;{count}&lt;/p&gt;</span>
<span class="hljs-addition">+  &lt;Counter count={count} /&gt;</span>
...
</code></pre>
<p>Now say, on the <code>Counter</code> function, you want to take the <code>isDark</code> prop and every time it changes we want to send out a console.log saying that the <code>isDark</code> prop has changed.
First let's take the prop</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-diff"><span class="hljs-deletion">-  &lt;Counter count={count} /&gt;</span>
<span class="hljs-addition">+  &lt;Counter count={count} isDark={isDark} /&gt;</span>
...
<span class="hljs-deletion">- function Counter({ count }) {</span>
<span class="hljs-addition">+ function Counter({ count, isDark }) {</span>
</code></pre>
<p>Now, if we add a useEffect hook like this:</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-diff">  function Counter({ count, isDark }) {
<span class="hljs-addition">+ useEffect(() =&gt; {</span>
<span class="hljs-addition">+   console.log("isDark value changed")</span>
<span class="hljs-addition">+ }, [isDark])</span>
</code></pre>
<p>Now, you will see a console.log everytime you click on the <code>Toggle isDark</code> button but notice that if you click on <code>Increase Counter</code>, 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!</p>
<p>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 <a target="_blank" href="https://reactjs.org/docs/hooks-reference.html#cleaning-up-an-effect">here</a>.</p>
<p>The final code for this is as follows:</p>
<div class="code-metadata">
src/App.js
</div>

<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">1</span>);
  <span class="hljs-keyword">const</span> [isDark, setIsDark] = useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"useEffect running"</span>);
  }, []);

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">incrementCount</span>(<span class="hljs-params"></span>) </span>{
    setCount(count + <span class="hljs-number">1</span>);
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Counter</span> <span class="hljs-attr">count</span>=<span class="hljs-string">{count}</span> <span class="hljs-attr">isDark</span>=<span class="hljs-string">{isDark}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{incrementCount}</span>&gt;</span>Increase counter<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsDark(!isDark)}&gt;Toggle isDark<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params">{ count, isDark }</span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"isDark value changed"</span>);
  }, [isDark]);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Beginner's guide to useState hook in React]]></title><description><![CDATA[A key component of a web application is the state. Taken directly from the beta(new) version of the ReactJS Docs:

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, yo...]]></description><link>https://livecode247.com/beginners-guide-to-usestate-hook-in-react</link><guid isPermaLink="true">https://livecode247.com/beginners-guide-to-usestate-hook-in-react</guid><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[state]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Thu, 10 Mar 2022 10:07:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/L8KQIPCODV8/upload/v1647164267285/Ej3_JiOK1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A key component of a web application is the <strong>state</strong>. Taken directly from the beta(new) version of the ReactJS Docs:</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>Now, how do we manage state inside a React Component? So, in this tutorial we'll be talking just about that!</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Basic knowledge of ReactJS</li>
</ul>
<h2 id="heading-what-are-react-hooks">What are React Hooks?</h2>
<p>First, let's start with what is a React Hook. The beta docs of ReactJS says the following:</p>
<blockquote>
<p>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 <a target="_blank" href="https://beta.reactjs.org/apis">React API reference</a>. 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.</p>
</blockquote>
<p>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.</p>
<h2 id="heading-setting-up-the-app">Setting up the app</h2>
<p>Create a project using the following command</p>
<pre><code class="lang-sh">npx create-react-app react-hooks-tutorial
</code></pre>
<p>Then edit your <code>src/App.js</code> to look like this</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> // this will update based on the state after this tutorial
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Increase counter<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h2 id="heading-usestate-hook"><code>useState</code> hook</h2>
<p>Now, the way the <code>useState</code> hook is used in React is very interesting. In a conventional, class based component you'd do something like this</p>
<pre><code class="lang-js">state = {
    <span class="hljs-attr">color</span>: <span class="hljs-string">"red"</span>
}
</code></pre>
<p>and then access it via <code>this.state</code>. But using the <code>useState</code> hook you'd do something like this</p>
<pre><code class="lang-diff"><span class="hljs-addition">+ import { useState } from "react"</span>
  function App() {
<span class="hljs-addition">+   const [count, setCount] = useState(1);</span>
    return (
</code></pre>
<p>Now the useState hook returns two things:</p>
<ol>
<li>The first variable is the actual state variable. For eg. <strong>count</strong> in this case is <strong>1</strong>.</li>
<li><code>setCount</code> is a function which you can use to change the value of the <code>count</code> state.</li>
</ol>
<h2 id="heading-using-the-count-state-variable-to-show-data">Using the count state variable to show data</h2>
<p>First, update the hardcoded value of 1 with the count variable like so</p>
<pre><code class="lang-diff">       &lt;h1&gt;Hello, World&lt;/h1&gt;
<span class="hljs-deletion">-      &lt;p&gt;1&lt;/p&gt;</span>
<span class="hljs-addition">+      &lt;p&gt;{count}&lt;/p&gt;</span>
       &lt;button&gt;Increase counter&lt;/button&gt;
</code></pre>
<h2 id="heading-using-setcount-to-update-state">Using setCount to update state</h2>
<p>Now to make this work, let's make the click of the button increase the <strong>count</strong> variable by 1.</p>
<pre><code class="lang-diff">       &lt;p&gt;{count}&lt;/p&gt;
<span class="hljs-deletion">-      &lt;button&gt;Increase counter&lt;/button&gt;</span>
<span class="hljs-addition">+      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increase counter&lt;/button&gt;</span>
</code></pre>
<h3 id="heading-using-previous-state-to-update-state">Using previous state to update state</h3>
<p>Now, let's try something. Change the button line to the following</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-     &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increase counter&lt;/button&gt;</span>
<span class="hljs-addition">+     &lt;button onClick={incrementCount}&gt;Increase counter&lt;/button&gt;</span>
</code></pre>
<pre><code class="lang-diff">  const [count, setCount] = useState(1);
<span class="hljs-addition">+ function incrementCount() {</span>
<span class="hljs-addition">+   setCount(count + 1);</span>
<span class="hljs-addition">+   setCount(count + 1);</span>
<span class="hljs-addition">+   setCount(count + 1);</span>
<span class="hljs-addition">+ }</span>
</code></pre>
<p>Now this will give you an issue. Straight from the docs again (little modified according to our app):</p>
<blockquote>
<p>This is because calling the set function does not update the <code>count</code> state variable in the already running code. So each <code>setCount(count + 1)</code> call becomes <code>setCount(2)</code>.</p>
</blockquote>
<p>To fix this issue, you can reference the previous state and then update the current state using that. So change your code like this</p>
<pre><code class="lang-diff"><span class="hljs-deletion">-  function incrementCount() {</span>
<span class="hljs-deletion">-    setCount(count + 1);</span>
<span class="hljs-deletion">-    setCount(count + 1);</span>
<span class="hljs-deletion">-    setCount(count + 1);</span>
<span class="hljs-deletion">-  }</span>
<span class="hljs-addition">+  function incrementCount() {</span>
<span class="hljs-addition">+    setCount((prevCount) =&gt; prevCount + 1);</span>
<span class="hljs-addition">+    setCount((prevCount) =&gt; prevCount + 1);</span>
<span class="hljs-addition">+    setCount((prevCount) =&gt; prevCount + 1);</span>
<span class="hljs-addition">+  }</span>
</code></pre>
<p>So, you get the <code>prevCount</code> argument and increment the current state according to that and this should work!</p>
<blockquote>
<p>Note: This is obviously not a real life scenario. To increment by 3, you'd probably do something like <code>setCount(count+3)</code> but it's good to know when you can use the previous state variable as a reference.</p>
</blockquote>
<p>That is it for this tutorial! You final code should look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">1</span>);
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">incrementCount</span>(<span class="hljs-params"></span>) </span>{
    setCount(<span class="hljs-function">(<span class="hljs-params">prevCount</span>) =&gt;</span> prevCount + <span class="hljs-number">1</span>);
    setCount(<span class="hljs-function">(<span class="hljs-params">prevCount</span>) =&gt;</span> prevCount + <span class="hljs-number">1</span>);
    setCount(<span class="hljs-function">(<span class="hljs-params">prevCount</span>) =&gt;</span> prevCount + <span class="hljs-number">1</span>);
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, World<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{incrementCount}</span>&gt;</span>Increase counter<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Deploying a static HTML and CSS site using Github Pages]]></title><description><![CDATA[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 de...]]></description><link>https://livecode247.com/deploying-a-static-html-and-css-site-using-github-pages</link><guid isPermaLink="true">https://livecode247.com/deploying-a-static-html-and-css-site-using-github-pages</guid><category><![CDATA[GitHub]]></category><category><![CDATA[deployment]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[CSS]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Mon, 07 Mar 2022 13:45:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/wX2L8L-fGeA/upload/v1646660413782/FnCS4MeIL.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>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.</p>
<h2 id="heading-register-at-github">Register at Github</h2>
<p>First of all create an account at <a target="_blank" href="https://github.com">Github</a>. Github is a Git repository hosting service which is owned by Microsoft. It provides a great feature called <a target="_blank" href="https://pages.github.com/">Github Pages</a> and can be used to deploy static sites.</p>
<h2 id="heading-create-a-github-repository">Create a Github Repository</h2>
<p>After registering, click on the button which says <strong>New</strong> on the top left of the page.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646658807807/fwCbWx1D5.png" alt="Create Repository" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646659047191/thiI_txfo.png" alt="Create repository input repo name" /></p>
<h2 id="heading-upload-files">Upload files</h2>
<p>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:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646660006991/qFS5mQjI3.gif" alt="Upload files to Github" /></p>
<h2 id="heading-enable-github-pages">Enable Github Pages</h2>
<p>Last step is to enable Github Pages like so:</p>
<ol>
<li>Click on Settings
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646660144532/dL1RxpqQx.gif" alt="Enable Github Pages" /></li>
<li>Click on Pages
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646660555903/nXO05pwgy.png" alt="Screenshot 2022-03-07 at 19.12.05.png" /></li>
<li>Click on <strong>Branch</strong> and choose <code>master</code><blockquote>
<p>This might be <code>main</code> depending on the default branch you're working on</p>
</blockquote>
</li>
<li>Click on the button on the right of <strong>Branch</strong> and choose <code>/ (root)</code></li>
<li>Click on <strong>Save</strong></li>
</ol>
<p>Then wait for some time and then refresh. Wait till you see a banner which says something like this:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646660196232/zNk9oBA_c.png" alt="Banner which says site's published" /></p>
<p>And there it is! You've deployed your site using Github Pages. For example, you can view the sample deployment <a target="_blank" href="https://kavinvalli.github.io/gh-pages-tutorial/">here</a>.</p>
<h2 id="heading-links">Links</h2>
<p>You can find the sample github repository in the example here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/gh-pages-tutorial">https://github.com/kavinvalli/gh-pages-tutorial</a></div>
]]></content:encoded></item><item><title><![CDATA[I built a Link shortener using Remix and here's my experience!]]></title><description><![CDATA[A few days ago, I decided to try out RemixJS 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.
What is Remix?
Well, let me start with what Remix ...]]></description><link>https://livecode247.com/i-built-a-link-shortener-using-remix-and-heres-my-experience</link><guid isPermaLink="true">https://livecode247.com/i-built-a-link-shortener-using-remix-and-heres-my-experience</guid><category><![CDATA[React]]></category><category><![CDATA[react router]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[javascript framework]]></category><category><![CDATA[Experience ]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Sat, 05 Mar 2022 15:24:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1646493698651/AraKEotSC.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few days ago, I decided to try out <a target="_blank" href="https://remix.run">RemixJS</a> 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.</p>
<h2 id="heading-what-is-remix">What is Remix?</h2>
<p>Well, let me start with what Remix is. If you've used ReactJS before, you'd most probably have come across <a target="_blank" href="https://reactrouterdotcom.fly.dev/docs/en/v6">React Router</a>. 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.</p>
<h2 id="heading-more-about-remix">More about Remix?</h2>
<p>I started following <a class="user-mention" href="https://hashnode.com/@kentcdodds">Kent C. Dodds</a>, 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 <a target="_blank" href="https://www.youtube.com/c/KentCDodds-vids">Youtube Channel</a> and he has an amazing <a target="_blank" href="https://kentcdodds.com">Website</a> also built using remix. You'll learn about some very cool stuff if you go through it, and you can find a really good video on it by Kent <a target="_blank" href="https://youtu.be/owOZMwNPAyc">here</a>.</p>
<h2 id="heading-about-the-link-shortener">About the Link shortener</h2>
<p>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 <a target="_blank" href="https://github.com/kavinvalli/remix-url-shortener">here</a>.
First, I went through the <a target="_blank" href="https://remix.run/docs/en/v1/tutorials/blog">tutorials</a> on Remix's docs which is a really good resource on starting with remix.</p>
<h3 id="heading-authentication">Authentication</h3>
<p>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 <a target="_blank" href="https://github.com/sergiodxa/remix-auth">Remix Auth</a>. It works really really well with Remix and has <a target="_blank" href="https://github.com/sergiodxa/remix-auth/discussions/111">support</a> for a lot of strategies.
It took me a little while to get started with it cause, it didn'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.</p>
<h3 id="heading-core-concepts">Core Concepts</h3>
<p>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.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>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.</p>
<p>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!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/remix-url-shortener">https://github.com/kavinvalli/remix-url-shortener</a></div>
]]></content:encoded></item><item><title><![CDATA[How to show code diffs in your Hashnode Blog?]]></title><description><![CDATA[Code Diffs was something I wanted to use for a while in Hashnode but I didn't know that it was already there to be used in markdown. The way you can implement this is like follows:
```diff
+ const port = process.env.PORT || 3000;
- app.listen(3000, (...]]></description><link>https://livecode247.com/how-to-show-code-diffs-in-your-hashnode-blog</link><guid isPermaLink="true">https://livecode247.com/how-to-show-code-diffs-in-your-hashnode-blog</guid><category><![CDATA[Hashnode]]></category><category><![CDATA[Developer Blogging]]></category><category><![CDATA[Blogger]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Fri, 04 Mar 2022 04:10:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/miWGZ02CLKI/upload/v1646366984434/jDNSN0atjj.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Code Diffs was something I wanted to use for a while in Hashnode but I didn't know that it was already there to be used in markdown. The way you can implement this is like follows:</p>
<pre><code>```diff
<span class="hljs-operator">+</span> const port <span class="hljs-operator">=</span> process.env.PORT <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-number">3000</span>;
<span class="hljs-operator">-</span> app.listen(<span class="hljs-number">3000</span>, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
<span class="hljs-operator">-</span>   console.log(`🚀 Server started on port <span class="hljs-number">3000</span>`)
<span class="hljs-operator">-</span> }
<span class="hljs-operator">+</span> app.listen(port, () <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
<span class="hljs-operator">+</span>   console.log(`🚀 Server started on port ${port}`);
<span class="hljs-operator">+</span> });
```
</code></pre><blockquote>
<p>This example is from on of my <a target="_blank" href="https://livecode247.com/start-a-web-server-with-nodejs-and-express">articles</a>.</p>
</blockquote>
<p>So, the way this works is, hashnode uses a plugin called <a target="_blank" href="https://highlightjs.org/">highlight.js</a> to convert the codeblocks. Highlight.js already has this feature implemented.
Now this looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646366426943/nJqnhH8Tm.png" alt="Code Block with diff without Custom CSS" /></p>
<p>You can definitely go forward with this, but the colors and design wasn't something I was satisfied with.
So, I decided to tweak my custom css to make it look better.</p>
<blockquote>
<p>You can get access to Hashnode's <a target="_blank" href="https://hashnode.com/post/style-your-hashnode-blog-with-custom-css-ckfwpesyg00ut0es10jgk5uwl">Custom CSS</a> feature by becoming a <a target="_blank" href="https://hashnode.com/ambassador">Hashnode Ambassador</a></p>
</blockquote>
<p>I added the following to my custom css:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.hljs-addition</span> {
    <span class="hljs-attribute">color</span>: green <span class="hljs-meta">!important</span>;
    <span class="hljs-attribute">box-shadow</span>: inset <span class="hljs-number">10.5px</span> <span class="hljs-number">0</span> green <span class="hljs-meta">!important</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">4.4px</span> <span class="hljs-number">0</span> <span class="hljs-meta">!important</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>);
}

<span class="hljs-selector-class">.hljs-deletion</span> {
    <span class="hljs-attribute">color</span>: red <span class="hljs-meta">!important</span>;
    <span class="hljs-attribute">box-shadow</span>: inset <span class="hljs-number">10.5px</span> <span class="hljs-number">0</span> red <span class="hljs-meta">!important</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">4.4px</span> <span class="hljs-number">0</span> <span class="hljs-meta">!important</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">255</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);
}
</code></pre>
<p>Now, this definitely can be refactored a little bit, but this is what I got:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646366739833/SXWSU8vS_.png" alt="Code block with diff with custom css" /></p>
<p>Now, I'm pretty satisfied with this! You can go ahead and use this feature and you're welcome to use my custom css and if you want tweak it a little bit and I would love to see your implementation in the comments!</p>
<blockquote>
<p>NOTE: This has one drawback that I couldn't find a way where you could have both the diff highlighting and the syntax highlighting for a certain language together in a code block. That is something we might have to wait for @Hashnode to implement, if they do.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Start a web server with Node.JS and Express]]></title><description><![CDATA[Node.JS and Express 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.
Getting started with Node.JS and Express is very easy.
Requireme...]]></description><link>https://livecode247.com/start-a-web-server-with-nodejs-and-express</link><guid isPermaLink="true">https://livecode247.com/start-a-web-server-with-nodejs-and-express</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[web servers]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Thu, 03 Mar 2022 04:48:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/bAaeJ0XtiMI/upload/v1646277385215/jkkFPapmd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://nodejs.org/en/">Node.JS</a> and <a target="_blank" href="https://expressjs.com/">Express</a> 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.</p>
<p>Getting started with Node.JS and Express is very easy.</p>
<h2 id="heading-requirements">Requirements</h2>
<ul>
<li>You should have Node.JS installed for this tutorial. If not, visit https://nodejs.org/en/ and download the <strong>LTS Version</strong>. This will also install <a target="_blank" href="https://nodejs.org/en/knowledge/getting-started/npm/what-is-npm/">npm</a> which is a widely used package manager for Node.JS.</li>
<li>You're also expected to have a basic knowledge of Javascript and Node.JS.</li>
</ul>
<h2 id="heading-creating-a-project">Creating a project</h2>
<p>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. </p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">mkdir node-express-tutorial
<span class="hljs-built_in">cd</span> node-express-tutorial
code . <span class="hljs-comment"># for Visual Studio Code users</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646279609131/G2qHVOx38.png" alt="Screenshot 2022-03-03 at 09.23.16.png" /></p>
<h2 id="heading-configuring-the-folder-to-use-npm">Configuring the folder to use npm</h2>
<p>Run the following in the terminal.</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">npm init
</code></pre>
<p>You will be prompted with a few questions. You can press enter through most of them.</p>
<blockquote>
<p>Alternatively, you can run <code>npm init -y</code> if you want to skip through all the questions with the default value.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646279797992/mh5lTLqD-.gif" alt="npminit.gif" /></p>
<h2 id="heading-starting-with-the-coding-part">Starting with the coding part</h2>
<p>So, start with creating a file named <code>index.js</code>. You can name it anything, just make sure you end it with <code>.js</code>.</p>
<blockquote>
<p>Conventionally, the file is named <code>index.js</code>, <code>server.js</code> or <code>app.js</code>.</p>
</blockquote>
<h2 id="heading-installing-express">Installing express</h2>
<p>Like most NodeJS packages, you can install express using npm. Run:</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">npm install express
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646279888889/kVlsvGfuY.gif" alt="npmiexpress.gif" /></p>
<p>This will add express as a <strong>dependency</strong> in your <code>package.json</code> and also install it in your <code>node_modules</code> folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646279919859/uSzroLgZS.png" alt="Screenshot 2022-03-03 at 09.28.32.png" /></p>
<h2 id="heading-using-express">Using express</h2>
<p>In your <code>index.js</code> file, write the following:</p>
<div class="code-metadata">
index.js
</div>

<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>)
</code></pre>
<p>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:</p>
<div class="code-metadata">
index.js
</div>

<pre><code class="lang-diff">const express = require("express")
<span class="hljs-addition">+ const app = express()</span>
</code></pre>
<p>Now, you can use the app variable to start the server like so:</p>
<div class="code-metadata">
index.js
</div>

<pre><code class="lang-js">app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`🚀 Server started on port 3000`</span>)
}
</code></pre>
<p>You've basically already created a web server. You can run the app by running</p>
<div class="code-metadata">
sh
</div>

<pre><code class="lang-sh">node index.js
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646281402768/-LJcRAriL.gif" alt="nodeindex.js.gif" /></p>
<p>If you get something like in the above gif, you're good to go to the next step!</p>
<h2 id="heading-routes">Routes</h2>
<p>So now, we've started an express server but it doesn't know what it has to do when we're visiting the <code>/</code> route.  Hence we get the error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646281487165/8i6yAXewV.png" alt="Screenshot 2022-03-03 at 09.54.40.png" /></p>
<p>For this, add the following line of code before calling the <code>app.listen</code> function:</p>
<div class="code-metadata">
index.js
</div>

<pre><code class="lang-js">app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> res.send(<span class="hljs-string">"Hello, World"</span>)
})
</code></pre>
<p>Let's go through this code:</p>
<ol>
<li>We call the <code>app.get</code> function. This takes in two parameters:<ol>
<li>A route: The route on which you want to run this function. In this case we're using the <code>/</code> route.</li>
<li>A callback function: The second parameter is a callback function with the <code>request</code> and <code>response</code> parameters which express provides us with. The <code>res</code>(response) gives us a send function with which we can send back a text response to the browser. </li>
</ol>
</li>
</ol>
<p>Now, we need to restart the NodeJS server running. Go to the terminal where you had run <code>node index.js</code> and then hit <code>Control-C</code>. And then restart by typing <code>node index.js</code> again like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646281847831/7EuhkIQ1i.gif" alt="restartnodejsserver.gif" /></p>
<blockquote>
<p>BONUS: Restarting the node server repeatedly becomes very annoying. To deal with this, there's a package called <code>nodemon</code> which you can install and setup. For detailed instructions visit: https://livecode247.com/how-to-add-auto-reload-to-your-node-js-app</p>
</blockquote>
<p>Now, refresh the page on the browser and you should see this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646282325271/94UDlGOUg.png" alt="Screenshot 2022-03-03 at 10.08.38.png" /></p>
<p>For the final step, you can refactor the port number like this</p>
<div class="code-metadata">
index.js
</div>

<pre><code class="lang-diff"><span class="hljs-addition">+ const port = process.env.PORT || 3000;</span>
<span class="hljs-deletion">- app.listen(3000, () =&gt; {</span>
<span class="hljs-deletion">-   console.log(`🚀 Server started on port 3000`)</span>
<span class="hljs-deletion">- }</span>
<span class="hljs-addition">+ app.listen(port, () =&gt; {</span>
<span class="hljs-addition">+   console.log(`🚀 Server started on port ${port}`);</span>
<span class="hljs-addition">+ });</span>
</code></pre>
<p><code>process.env.PORT</code> 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.</p>
<h2 id="heading-final-code">Final Code</h2>
<p>Your final code in <code>index.js</code> should look like this:</p>
<div class="code-metadata">
index.js
</div>

<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> res.send(<span class="hljs-string">"Hello, World"</span>);
});

<span class="hljs-keyword">const</span> port = process.env.PORT || <span class="hljs-number">3000</span>;
app.listen(port, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`🚀 Server started on port <span class="hljs-subst">${port}</span>`</span>);
});
</code></pre>
<p>That's it for this tutorial! Now express has a lot more stuff to offer you. Just yesterday, MDN released it's new <a target="_blank" href="https://developer.mozilla.org/en-US/">website</a> and I found a very good in-depth tutorial on express. Do check it out <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[My Developer Setup in 2022!]]></title><description><![CDATA[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...]]></description><link>https://livecode247.com/my-developer-setup-in-2022</link><guid isPermaLink="true">https://livecode247.com/my-developer-setup-in-2022</guid><category><![CDATA[Developer]]></category><category><![CDATA[development]]></category><category><![CDATA[terminal]]></category><category><![CDATA[editors]]></category><category><![CDATA[setup]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Tue, 22 Feb 2022 16:09:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645546085481/tXaa2xvNp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>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!</p>
<h2 id="heading-hardware">Hardware</h2>
<p><a target="_blank" href="https://www.apple.com/in/macbook-air/">M1 Macbook Air 2020</a> with 256GB storage and 8GB RAM with an external 27-inch monitor.</p>
<h2 id="heading-editor">Editor</h2>
<p>The editor I generally use is <a target="_blank" href="https://neovim.io/">Neovim</a>. So, most of you would have heard of <a target="_blank" href="https://www.vim.org/">Vim</a>. 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.</p>
<p>However, I do use <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> when collaborating with others in real time using the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=MS-vsliveshare.vsliveshare">Live Share extension</a>. And guess what! I use vim keybindings inside VSCode as well using the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=vscodevim.vim">Vim extension</a>.</p>
<p>Though, Neovim does have a few minus points to it</p>
<ul>
<li>You'll have to learn vim</li>
<li>You'll have to spend some time customising neovim to suit your needs, and setup plugins for autocomplete, LSPs etc.</li>
</ul>
<p>If you're a beginner, I highly recommend starting with VSCode and maybe use the vim extension if you want to start learning vim.</p>
<h2 id="heading-terminal-setup">Terminal Setup</h2>
<p>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 <a target="_blank" href="https://iterm2.com/">iTerm2</a> but I've heard of <a target="_blank" href="https://sw.kovidgoyal.net/kitty/">Kitty</a> and <a target="_blank" href="https://alacritty.org/">Alacritty</a> as pretty good alternatives.</p>
<p>I also use <a target="_blank" href="https://github.com/tmux/tmux">tmux</a> heavily in my workflow. I use multiple tmux sessions for every project and recommend a lot of people to use it.</p>
<p>I use the <a target="_blank" href="https://fishshell.com/">fish shell</a>. It has some great features which you can find on the website which lead me to use it over zsh and bash.</p>
<p>I use <a target="_blank" href="https://www.gnu.org/software/stow/">GNU Stow</a> to manage my configurations.</p>
<p>You can find my dotfiles in the repo linked below.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/dotfiles">https://github.com/kavinvalli/dotfiles</a></div>
<p>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.</p>
]]></content:encoded></item><item><title><![CDATA[RITA - Batteries included starter for Adonis apps]]></title><description><![CDATA[People who've tried Laravel would know how easy it makes lives of developers. Then, came in AdonisJS 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 setti...]]></description><link>https://livecode247.com/rita-batteries-included-starter-for-adonis-apps</link><guid isPermaLink="true">https://livecode247.com/rita-batteries-included-starter-for-adonis-apps</guid><category><![CDATA[React]]></category><category><![CDATA[AdonisJS]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[full stack]]></category><category><![CDATA[risingstack]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Mon, 13 Dec 2021 12:29:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639398409920/L4eyY4wiR.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>People who've tried Laravel would know how easy it makes lives of developers. Then, came in <a target="_blank" href="https://adonisjs.com/">AdonisJS</a> 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.</p>
<p>One of my <a target="_blank" href="https://github.com/dotangad">seniors</a>, told me about <a target="_blank" href="https://inertiajs.com/">Inertia</a> 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.</p>
<blockquote>
<p>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.</p>
<p>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.</p>
</blockquote>
<p>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.</p>
<p>My senior created <a target="_blank" href="https://github.com/dotangad/liret">LIRET</a> which uses Laravel and React with Inertia as an adapter with more features out of the box.</p>
<p>I finally came across <a target="_blank" href="https://github.com/eidellev/inertiajs-adonisjs">inertia-adonisjs</a> which is a <code>Inertia.js AdonisJS Provider</code>. </p>
<p>I recreated the LIRET stack but with AdonisJS and then came up <a target="_blank" href="https://github.com/kavinvalli/rita"><strong>RITA</strong></a></p>
<p>RITA is a batteries-included starter for Adonis apps. The full form of Rita is <code>React Inertia Typescript Adonis</code>.</p>
<h3 id="heading-features">Features</h3>
<h4 id="heading-backend">Backend</h4>
<ul>
<li>AdonisJS</li>
<li>Database (MySQL but you can change it very easily)</li>
<li>Authentication<ul>
<li>Email-Password</li>
<li>Github</li>
<li>Gmail</li>
<li>You can also add other providers very easily</li>
</ul>
</li>
<li>Admin Authorisation with Middleware support</li>
</ul>
<h4 id="heading-frontend">Frontend</h4>
<ul>
<li>Frontend with React and Typescript</li>
<li>TailwindCSS setup</li>
<li>Some built in components/hooks like <code>useTitle</code> and <code>TextInput</code> for simplicity</li>
<li>Built in components for Authorisation validation like <code>&lt;Admin&gt;</code>, <code>&lt;User&gt;</code>, <code>&lt;Authenticated&gt;</code> and <code>&lt;Guest&gt;</code></li>
</ul>
<p>Using Inertia as a connector.</p>
<p>There are a few more features and you can find detailed instructions at the <a target="_blank" href="https://rita.kavin.me">Readme</a>.</p>
<p>Give the repo a star if you like it!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/rita">https://github.com/kavinvalli/rita</a></div>
]]></content:encoded></item><item><title><![CDATA[I wrote a Github CLI extension to fuzzy find repos and run actions on them]]></title><description><![CDATA[I went ahead and created a Github CLI extension which fuzzy finds repos and you can choose an action you want to run on it.

Requirements

gh cli - minimum version (2.0.0)
fzf

Installation
Via the Github CLI
gh extension install kavinvalli/gh-repo-f...]]></description><link>https://livecode247.com/i-wrote-a-github-cli-extension-to-fuzzy-find-repos-and-run-actions-on-them</link><guid isPermaLink="true">https://livecode247.com/i-wrote-a-github-cli-extension-to-fuzzy-find-repos-and-run-actions-on-them</guid><category><![CDATA[GitHub]]></category><category><![CDATA[cli]]></category><category><![CDATA[extension]]></category><category><![CDATA[Bash]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Fri, 03 Dec 2021 16:01:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638546705319/d-0ijv7VI.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I went ahead and created a Github CLI extension which fuzzy finds repos and you can choose an action you want to run on it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638547640775/1TnE4fnycI.gif" alt="gh-repo-fzf.gif" /></p>
<h3 id="heading-requirements">Requirements</h3>
<ol>
<li><code>gh cli</code> - minimum version (2.0.0)</li>
<li><code>fzf</code></li>
</ol>
<h2 id="heading-installation">Installation</h2>
<h3 id="heading-via-the-github-cli">Via the Github CLI</h3>
<pre><code class="lang-sh">gh extension install kavinvalli/gh-repo-fzf
</code></pre>
<h3 id="heading-manually">Manually</h3>
<p>You can also install it manually by following these steps:</p>
<ol>
<li><p>Clone repo</p>
<pre><code class="lang-bash"><span class="hljs-comment"># git</span>
git <span class="hljs-built_in">clone</span> https://github.com/kavinvalli/gh-repo-fzf
<span class="hljs-comment"># github cli</span>
gh repo <span class="hljs-built_in">clone</span> kavinvalli/gh-fzf
</code></pre>
</li>
<li><p>cd into it</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> gh-repo-fzf
</code></pre>
</li>
<li><p>Install it locally</p>
<pre><code class="lang-bash">gh extension install .
</code></pre>
</li>
</ol>
<h2 id="heading-usage">Usage</h2>
<ul>
<li>To list all directories you have access to, run:</li>
</ul>
<pre><code class="lang-sh">gh repo-fzf
</code></pre>
<ul>
<li>To list directories of a particular user / organisation:</li>
</ul>
<pre><code class="lang-sh">gh repo-fzf &lt;username/organisation-name&gt;
</code></pre>
<p>After choosing a directory, you will be prompted to choose one of the following:</p>
<ul>
<li><code>Clone</code> - clones a repository to your local machine</li>
<li><code>View</code> - opens the Github URL of the repository</li>
<li><code>Fork</code> - forks the repository</li>
<li><code>Archive</code> - archives the repository</li>
</ul>
<p>Feel free to put up any issue you face on the <a target="_blank" href="https://github.com/kavinvalli/gh-repo-fzf">Github Repository</a>.
Contributions are also welcome.</p>
<p>Don't forget to star the repo 😉</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/gh-repo-fzf">https://github.com/kavinvalli/gh-repo-fzf</a></div>
]]></content:encoded></item><item><title><![CDATA[My attempt at creating a unique portfolio website! Hint: Terminal]]></title><description><![CDATA[I created my portfolio website a few months ago and tried to make it as unique as possible and came up with the idea of a terminal based website. You can find it here
It takes in a command (you can list all commands you can use by typing help and the...]]></description><link>https://livecode247.com/my-attempt-at-creating-a-unique-portfolio-website</link><guid isPermaLink="true">https://livecode247.com/my-attempt-at-creating-a-unique-portfolio-website</guid><category><![CDATA[portfolio]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Sat, 11 Sep 2021 09:48:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1637756084685/lOMalXecz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I created my portfolio website a few months ago and tried to make it as unique as possible and came up with the idea of a terminal based website. You can find it <a target="_blank" href="https://kavin.me">here</a>
It takes in a command (you can list all commands you can use by typing <code>help</code> and then typing the command) and displays an output much like a proper terminal.
I used HTML, CSS, and Vanilla Javascript which I regret sometimes because of how hard it is to maintain now. I might add Parcel later to make it easier to bundle the code. But for now it's how it is and you can find the code in the Github Embed below!</p>
<blockquote>
<p>Update (26/10/2021): The website is now made using NextJS</p>
</blockquote>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/kavinvalli.github.io">https://github.com/kavinvalli/kavinvalli.github.io</a></div>
<p>Oh, there is also a normal mode on the website if you don't want to use the terminal mode.
I'll love some feedback on the website and drop your portfolio links below too!</p>
<p>I also later created a normal design website which can be found <a target="_blank" href="https://n.kavin.me">here</a> and the code for that is in this repo:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/kavinvalli/normal-website">https://github.com/kavinvalli/normal-website</a></div>
]]></content:encoded></item><item><title><![CDATA[Local NodeJS Environment Variables]]></title><description><![CDATA[The DotEnv is an NPM package which allows you to load local NodeJS Environment Variables in your project. It is based on The Twelve-Factor App Methodology - Storing configuration in environment separate from code.
Installation
The installation is as ...]]></description><link>https://livecode247.com/local-nodejs-environment-variables</link><guid isPermaLink="true">https://livecode247.com/local-nodejs-environment-variables</guid><category><![CDATA[Node.js]]></category><category><![CDATA[variables]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Kavin Desi Valli]]></dc:creator><pubDate>Mon, 23 Aug 2021 17:24:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629739381974/cxB1I-NTA.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a target="_blank" href="https://www.npmjs.com/package/dotenv">DotEnv</a> is an NPM package which allows you to load local NodeJS Environment Variables in your project. It is based on <a target="_blank" href="https://12factor.net/config">The Twelve-Factor App Methodology</a> - Storing configuration in environment separate from code.</p>
<h2 id="heading-installation">Installation</h2>
<p>The installation is as easy as any other NPM Package</p>
<pre><code class="lang-sh">npm install dotenv
<span class="hljs-comment"># YARN</span>
yarn add dotenv
</code></pre>
<h2 id="heading-setup">Setup</h2>
<p>Create a <code>.env</code> file in your root directory. Add any env vars you want in that file.
For eg.</p>
<pre><code><span class="hljs-attr">DB_HOST</span>=localhost
<span class="hljs-attr">DB_PORT</span>=<span class="hljs-number">3306</span>
<span class="hljs-attr">DB_USER</span>=root
<span class="hljs-attr">DB_PASSWORD</span>=password
</code></pre><h2 id="heading-load-the-variables">Load the variables</h2>
<p>Now in your starting JS file (which you run using <code>node &lt;filename&gt;.js</code>) add the following line of code</p>
<pre><code class="lang-js"><span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config()
</code></pre>
<p>What this does is, it imports the <code>dotenv</code> module using the CommonJS syntax and then calls the <code>config</code> function on it. This loads up the dotenv variables in the <code>.env</code> file created earlier. You can also pass an object as an argument into it which you can find <a target="_blank" href="https://www.npmjs.com/package/dotenv#options">here</a></p>
<h2 id="heading-use-the-variables">Use the variables</h2>
<p>You can use the variables inside that file now like any other env variable using the Global Object <code>process</code> and the object <code>env</code> inside it in the following way:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(process.env.DB_HOST)
</code></pre>
<p>Note that you can use the env variables inside the .env file only after calling the config function in the dotenv module. So the above line of code needs to come after the <code>require('dotenv').config()</code> function.</p>
]]></content:encoded></item></channel></rss>