<?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[Usman Writes]]></title><description><![CDATA[Hey all! My name is Usman! I am 17 years old and learning web development and programming. I also have a YouTube channel on the subject of programming and mostl]]></description><link>https://blog.usmans.me</link><generator>RSS for Node</generator><lastBuildDate>Sun, 12 Apr 2026 08:55:30 GMT</lastBuildDate><atom:link href="https://blog.usmans.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[🎣 Webhooks Demystified - Get Real-Time Personal Notifications with Discord Webhooks]]></title><description><![CDATA[Hey all 👋👋
Webhooks are a powerful tool that allow applications to communicate with each other in real-time. They are often used to send notifications or updates from one system to another without requiring manual intervention.

If you know the bas...]]></description><link>https://blog.usmans.me/webhooks-101</link><guid isPermaLink="true">https://blog.usmans.me/webhooks-101</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[discord]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sat, 17 Dec 2022 16:33:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1671194963625/CNEO1c9HL.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey all 👋👋</p>
<p>Webhooks are a powerful tool that allow applications to communicate with each other in real-time. They are often used to send notifications or updates from one system to another without requiring manual intervention.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671195122067/ZXhD0O3ZI.gif" alt class="image--center mx-auto" /></p>
<p>If you know the basics of sending a request to a REST API, you can easily use Webhooks to make your lives easier.</p>
<p>Today, I will show you how you can use <strong>Discord Webhooks</strong> to send <strong>personal notifications</strong> to your Discord server. This will be an easy and quick demo of how Discord Webhook works.</p>
<p>Discord Webhooks can be used for:</p>
<ul>
<li><p>Notifying a server about updates to a website or social media account (YouTube, Twitch, Twitter, etc)</p>
</li>
<li><p>Automating messages for a welcome or goodbye message to new server members</p>
</li>
<li><p>Sending notifications about events or reminders to a server</p>
</li>
<li><p>Sharing information from other sources, such as weather reports or game updates</p>
</li>
</ul>
<p>If you are comfortable with videos rather than articles, you can check out the video on <a target="_blank" href="https://youtube.com/@MaxProgramming">my YouTube channel</a> 👇</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=oOIPrLr7i3o">https://www.youtube.com/watch?v=oOIPrLr7i3o</a></div>
<p> </p>
<h2 id="heading-the-goal">🎯 The Goal</h2>
<p>By the end of this article, you will understand how Discord Webhooks work, and how you can use them to notify you when a user clicks on a button on your website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671021820822/EIfGwovBy.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-creating-a-webhook">🌱 Creating a Webhook</h2>
<p>On Discord, you can easily create a webhook by following the steps below</p>
<blockquote>
<p>You can't create or control a Webhook on Discord mobile. Either use the web version or the desktop version to do that.</p>
</blockquote>
<p>The first step is to go into your Server Settings.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671015410927/kyqC5nUkS.png" alt class="image--center mx-auto" /></p>
<p>Then on the settings page, click on <strong>Integrations</strong>, and then <strong>Create Webhook</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671015669679/ftVcdzix9.png" alt class="image--center mx-auto" /></p>
<p>Choose a name and avatar for your Webhook Bot, and hit <strong>Save Changes</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671015933050/Nc4dLXB7Y.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>Make sure to copy the Webhook URL by clicking on the <strong>Copy Webhook URL</strong> button. We will need that later to interact with the Webhook.</p>
</blockquote>
<h2 id="heading-testing-the-webhook">🧪 Testing the Webhook</h2>
<p>To test and see how our Webhook works, we will use the <a target="_blank" href="https://apitester.org">API Tester</a> mobile app. You can download it from the <a target="_blank" href="https://apps.apple.com/us/app/api-tester-debug-requests/id1575521212">App Store link</a> and the <a target="_blank" href="https://play.google.com/store/apps/details?id=apitester.org">Play Store link</a>.</p>
<p>The rapid changes in the world have made it possible for individuals to increase their productivity and gain greater mobility by working directly from their smartphones from any location.</p>
<p>API Tester allows users to test APIs from anywhere, at any time, using a device that they already have with them. This can be especially useful for testing APIs while on the go or when a desktop or laptop computer is not available.</p>
<p>There are a few reasons I really like API Tester:</p>
<ul>
<li><p>Beautiful and easy-to-use UI</p>
</li>
<li><p>Great UX</p>
</li>
<li><p>Importing data from Postman and other platforms</p>
</li>
<li><p>Environment variables</p>
</li>
<li><p>Much more...</p>
</li>
</ul>
<h3 id="heading-creating-a-request">Creating a request</h3>
<p>You can create a new request on API Tester, click on the Plus Button on the top-right, then select <strong>POST</strong> as your request type.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671017488751/VYzXJeHcv.png?height=500" alt class="image--center mx-auto" /></p>
<p>Then, paste the Webhook URL you copied earlier after creating the Webhook.</p>
<p>You must hide the Webhook URL because anyone with the Webhook URL can use it to send messages on your server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671019449058/a0LIOiwzN.png?height=300" alt class="image--center mx-auto" /></p>
<p>Next, go to the Body section, select <strong>Raw</strong>, and open <strong>Post Data.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671019722782/xqsfO0ZRI.png?height=300" alt class="image--center mx-auto" /></p>
<p>Inside the <strong>Post Data</strong>, add this JSON</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"content"</span>: <span class="hljs-string">"This is a test message"</span>
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671019862935/B08FPzOGX.jpg?height=250" alt class="image--center mx-auto" /></p>
<p>Finally, close the <strong>Post Data</strong> popup, and hit the <strong>Send</strong> button in the <strong>top right corner</strong>.</p>
<p>You will immediately receive a message on your Discord server from the webhook you created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671020004172/HDdgnlniL.png" alt class="image--center mx-auto" /></p>
<p>You can learn more about API Tester from their official site:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://apitester.org">https://apitester.org</a></div>
<p> </p>
<h2 id="heading-adding-the-feature">💬 Adding the feature</h2>
<p>To add this feature to your website, simply send a POST request to the Discord Webhook URL.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendDiscordMessage</span>(<span class="hljs-params">name</span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"DISCORD_WEBHOOK_URL"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ 
      <span class="hljs-attr">content</span>: <span class="hljs-string">`<span class="hljs-subst">${name}</span> button was clicked.`</span>,
    }),
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
    },
  });
}
</code></pre>
<h2 id="heading-how-do-i-do-it-with-nextjs">✨ How do I do it with Next.js?</h2>
<p>My personal site is built using Next.js and React. I created a serverless function using the <a target="_blank" href="https://nextjs.org/docs/api-routes/introduction">API Routes in Next.js</a> so that my <strong>discord webhook URL is protected</strong>.</p>
<p>Otherwise, directly sending the request from the front end might cause your Webhook URL to be exposed.</p>
<p>This is my code for the backend 👇.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671022473132/n1xjHj9IH.png" alt class="image--center mx-auto" /></p>
<p>And this is the code for my front end 👇.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671022614120/4tV_8OjKb.png" alt class="image--center mx-auto" /></p>
<p>You can always find the code for my website on GitHub.</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/max-programming/usmans.me">https://github.com/max-programming/usmans.me</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope this article helped you understand how Webhooks work and how you can use Discord Webhooks for various tasks. Comment below how you utilized Discord Webhooks or any other type of Webhooks.</p>
<p>I would love to hear your thoughts on this topic. Please share your ideas and experiences in the comments section below!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671023089231/XY_eDTzt7.gif" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[🛑 Why You Should Avoid the onclick Attribute in Your Code]]></title><description><![CDATA[Hey everyone! It's been a while since I wrote my last article. But here I am with another topic that might be informational to you 🙂.
This time I am writing about why you should avoid the onclick attribute in your HTML and JavaScript code.


This ar...]]></description><link>https://blog.usmans.me/why-you-should-avoid-the-onclick-attribute-in-your-code</link><guid isPermaLink="true">https://blog.usmans.me/why-you-should-avoid-the-onclick-attribute-in-your-code</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[HTML]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sun, 11 Dec 2022 13:18:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670764121043/qWsc4ln31.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey everyone! It's been a while since I wrote my last article. But here I am with another topic that might be informational to you 🙂.</p>
<p>This time I am writing about why you should avoid the <code>onclick</code> attribute in your HTML and JavaScript code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670764630357/7W5GzIP-0.gif" alt="meme - you avoiding onclick" class="image--center mx-auto" /></p>
<blockquote>
<p>This article is not particularly about <strong>click events</strong> but rather all events in HTML and JS. The <strong>click event</strong> is a good and easy example to explain.</p>
</blockquote>
<p>First, I will try to explain the various ways to handle click events or rather any events in JavaScript.</p>
<h1 id="heading-different-ways-to-handle-click-events">Different Ways to Handle Click Events</h1>
<p>There are three ways I know to handle click events in HTML and JavaScript (comment below if you know more).</p>
<h2 id="heading-1-using-the-onclick-attribute">1. Using the <code>onclick</code> attribute</h2>
<p>The first way I learned was by using the <code>onclick</code> attribute in HTML and calling a function that was written in JavaScript.</p>
<p>It is maybe the easiest way to handle click events. As there is nothing complicated. Everything makes sense.</p>
<pre><code class="lang-xml"><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">title</span>&gt;</span>The onclick way<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">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"whenButtonClicked()"</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">whenButtonClicked</span>(<span class="hljs-params"></span>) </span>{
        alert(<span class="hljs-string">'button clicked'</span>);
      }
    </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>In the code above, we create a function inside our JavaScript that we then call when the button is clicked.</p>
<p>It will result in something like this 👇</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670751015067/_4GdNviTz.gif" alt="button is clicked and an alert is shown" class="image--center mx-auto" /></p>
<h2 id="heading-2-using-the-addeventlistener-function">2. Using the <code>addEventListener</code> function</h2>
<p>The second way I learned was by using the <code>addEventListener</code> function inside JavaScript. I saw it for the first time in <a target="_blank" href="https://youtu.be/jaVNP3nIAv0">this tutorial</a>.</p>
<p>At first, I felt this was unnecessary as the <code>onclick</code> felt easier. But with time and building large projects, I understood why this makes more sense.</p>
<pre><code class="lang-xml"><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">title</span>&gt;</span>The onclick way<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">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"btn"</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">const</span> btn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'btn'</span>);

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">whenButtonClicked</span>(<span class="hljs-params"></span>) </span>{
        alert(<span class="hljs-string">'button clicked'</span>);
      }

      <span class="hljs-comment">// 1. either pass the function</span>
      btn.addEventListener(<span class="hljs-string">'click'</span>, whenButtonClicked);
      <span class="hljs-comment">// 2. or use anonymous function</span>
      btn.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">() =&gt;</span> {
        alert(<span class="hljs-string">'button clicked'</span>);
      });
    </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>What happens here is you first <strong>select the button</strong> inside your JavaScript code with <code>id</code> or <code>class</code> etc. And then <strong>register/add an event listener</strong> called <code>click</code>. Then either <strong>pass the function</strong> in or use an <strong>anonymous function</strong>.</p>
<p>This is better because when you are going to build something large the first way, <strong>your JavaScript code will get mixed with HTML.</strong> Then maintaining your code will be very hard.</p>
<p>You can also remove an event listener using the <code>removeEventListener</code> method. By just passing in the function that was used previously.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">whenButtonClicked</span>(<span class="hljs-params"></span>) </span>{
  alert(<span class="hljs-string">'button clicked'</span>);
}

<span class="hljs-comment">// add event listener</span>
btn.addEventListener(<span class="hljs-string">'click'</span>, whenButtonClicked);
<span class="hljs-comment">// remove event listener</span>
btn.removeEventListener(<span class="hljs-string">'click'</span>, whenButtonClicked);
</code></pre>
<h2 id="heading-3-using-the-onclick-property">3. Using the <code>onclick</code> property</h2>
<p>This is by far my favourite way to handle events.</p>
<ul>
<li><p>It's as straightforward as the first one.</p>
</li>
<li><p>Separated from HTML as the second one.</p>
</li>
</ul>
<pre><code class="lang-xml"><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">title</span>&gt;</span>The onclick way<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">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"btn"</span>&gt;</span>Click me<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">const</span> btn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'btn'</span>);

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">whenButtonClicked</span>(<span class="hljs-params"></span>) </span>{
        alert(<span class="hljs-string">'button clicked'</span>);
      }

      <span class="hljs-comment">// 1. either pass the function</span>
      btn.onclick = whenButtonClicked;
      <span class="hljs-comment">// 2. or use anonymous function</span>
      btn.onclick = <span class="hljs-function">() =&gt;</span> {
        alert(<span class="hljs-string">'button clicked'</span>);
      };
    </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>What we do in this piece of code is that we assign the <code>onclick</code> attribute to a function (same as the second way).</p>
<p>The downside of using this method is that you cannot assign multiple event listeners. If you use <code>addEventListener</code>. With that, you can add multiple functions to one element. And not to mention you also <strong>cannot</strong> use something like <code>removeEventListener</code></p>
<h1 id="heading-so-whats-wrong-with-onclick">So What's Wrong with <code>onclick</code>?</h1>
<p>Now let's come to the main section of the article.</p>
<p>The <code>onclick</code> attribute is not recommended in HTML because it is considered to be a <strong>bad practice</strong> to use <strong>inline JavaScript</strong> in your HTML code.</p>
<p>Instead, it is better to separate your JavaScript code from your HTML code and use event listeners to handle events in your web page. This makes your code easier to read, maintain, and reuse.</p>
<p>In general, it is better to avoid using the <code>onclick</code> attribute in HTML and to use event listeners instead, as this allows you to keep your JavaScript code separate from your HTML code and makes it easier to manage and maintain.</p>
<p>Additionally, using inline JavaScript in your HTML can make your code more difficult to maintain and update. If you need to change the behaviour of your web page, you will have to go through your HTML code and update all of the <code>onclick</code> attributes, which can be time-consuming and error-prone.</p>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>I hope this article helped you out and made you better!</p>
<p>I would love to hear your thoughts on this topic. Please share your ideas and experiences in the comments section below.</p>
]]></content:encoded></item><item><title><![CDATA[🎉 Presenting Memoriez - A quick & easy journal]]></title><description><![CDATA[❔ What and Why Memoriez ❔
This is a very important question because it makes things clear as to why this app is needed.
I built Memoriez because I honestly found it hard to write and maintain journal/diary entries daily.
It's not easy to maintain a j...]]></description><link>https://blog.usmans.me/memoriez</link><guid isPermaLink="true">https://blog.usmans.me/memoriez</guid><category><![CDATA[Linode Hackathon]]></category><category><![CDATA[Linode]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Clerk.dev]]></category><category><![CDATA[PlanetScale]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Fri, 01 Jul 2022 04:42:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656647378837/zTE_GI6xd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-and-why-memoriez">❔ What and Why Memoriez ❔</h2>
<p>This is a very important question because it makes things clear as to why this app is needed.
I built <a target="_blank" href="https://memoriez.cc">Memoriez</a> because I honestly found it hard to write and maintain journal/diary entries daily.</p>
<p>It's not easy to maintain a journal (especially not for lazy people like me 😜) but with this platform, people can easily maintain a journal where their data is also stored on the cloud. So it's preserved as well.</p>
<h2 id="heading-features">✨ Features ✨</h2>
<p><a target="_blank" href="https://memoriez.cc">Memoriez</a> contains not too many features as of now but still many features. But it has the following great features that are different from a normal journal app.</p>
<h3 id="heading-cover-image-using-pexels">Cover Image (Using Pexels)</h3>
<p>Users can add a cover image to their entry using this feature, they can search for something and choose that image to set their cover. I used the Pexels API for this.</p>
<iframe width="640" height="300" src="https://www.loom.com/embed/9af10c4ad4dc493db458a3967a41d2cb"></iframe>

<h3 id="heading-set-mood-of-the-day">Set Mood of the day</h3>
<p>Users can set the mood of the day which will then help them to figure out how the day went instead of reading the whole entry. This gives a sort of emotion for the day and makes it better.</p>
<iframe width="640" height="300" src="https://www.loom.com/embed/24e80032766c4fc1be9ac2e818d73fd8"></iframe>

<h2 id="heading-tech-stack">⚒ Tech Stack ⚒</h2>
<p>The Tech Stack used here might be familiar to a lot of people. Because it has gotten very popular nowadays.</p>
<ul>
<li><a target="_blank" href="https://nextjs.org/">Next.js</a> (With TypeScript)</li>
<li><a target="_blank" href="https://chakra-ui.com/">Chakra UI</a> (CSS Framework)</li>
<li><a target="_blank" href="http://clerk.dev/">Clerk</a> (User Authentication)</li>
<li><a target="_blank" href="http://prisma.io/">Prisma</a> (ORM)</li>
<li><a target="_blank" href="planetscale.com">PlanetScale</a> (Database)</li>
<li><a target="_blank" href="https://www.linode.com/">Linode</a> (Deployment/VPS)</li>
</ul>
<h2 id="heading-what-i-learned">🍂 What I Learned 🍂</h2>
<p>One of the most important things from this hackathon was to learn new things about new technologies.
Here are a few new things I learned by building this project.</p>
<ol>
<li>⚡ Deployment of Next.js app on Linode (Most interesting)</li>
<li>🚀 Deploy on commit with GitHub Actions</li>
<li>🔒 Building a full CRUD app with Secure API</li>
<li>✨ Using PlanetScale for the database with Prisma</li>
</ol>
<h2 id="heading-what-next">🔮 What Next? 🔮</h2>
<p>I built this in a very few days because I did not have much time. Most of my time went in other things. Now that I have made the basic working version of it. These are the features I have planned for the future:</p>
<ul>
<li>Make entries shareable (set public or private)</li>
<li>Ability to filter entries by tags</li>
<li>Ability to filter entries by mood</li>
<li>Show graphs and charts based on mood</li>
<li>Searching for entry</li>
</ul>
<hr />
<h2 id="heading-conclusion">⛳ Conclusion ⛳</h2>
<p>This was one of my greatest experiences of all time. This is my second huge app!</p>
<p>The first huge app I built was <a target="_blank" href="https://easypastes.tk">Easypastes</a> with <a class="user-mention" href="https://hashnode.com/@janaSunrise">Sunrit Jana</a>.
This time, I built it myself all alone. With some feedback from the community.</p>
<p>Memoriez is open-source! Contributions are welcome 🤗</p>
<ul>
<li><a target="_blank" href="https://memoriez.cc">Website</a></li>
<li><a target="_blank" href="https://github.com/max-programming/memoriez">GitHub</a></li>
</ul>
<p>Overall, I would like to mention these super useful resources that helped me deploy my project to Linode. It was a little too much work but I learned something very new that I had never come across before.</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=X3F3El_yvFg">Automatic Deployment With GitHub Actions - By Traversy Media and Anson the Developer</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=7aRjGIhwyQM">Linux Server Setup &amp; MERN Deployment - By Traversy Media</a> </li>
</ul>
<p>Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Thanks for reading ✌</p>
<p><img src="https://c.tenor.com/2wUCMoB0S_gAAAAC/peace-tony-stark.gif" alt /></p>
]]></content:encoded></item><item><title><![CDATA[🗃️ How to use Mongoose with Next.js for MongoDB?]]></title><description><![CDATA[Hey all 👋!
Next.js is an amazing full-stack framework and MongoDB is a great NoSQL database. Using them together will make an app super fast and awesome! In this post, we'll go ahead and set up the Mongoose ODM inside our Next.js app to make use of ...]]></description><link>https://blog.usmans.me/how-to-use-mongoose-with-nextjs-for-mongodb</link><guid isPermaLink="true">https://blog.usmans.me/how-to-use-mongoose-with-nextjs-for-mongodb</guid><category><![CDATA[MongoDB]]></category><category><![CDATA[mongoose]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Databases]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sun, 17 Apr 2022 08:45:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1650185052230/2wzY_Fd6f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-hey-all">Hey all 👋!</h1>
<p>Next.js is an amazing full-stack framework and MongoDB is a great NoSQL database. Using them together will make an app super fast and awesome! In this post, we'll go ahead and set up the Mongoose ODM inside our Next.js app to make use of MongoDB!</p>
<p>So let's see how you can set up Mongoose in a Next.js app to connect and interact with your MongoDB database!</p>
<h2 id="heading-setting-up-mongoose-and-the-connection-string">Setting up mongoose and the connection string</h2>
<p>In your Next.js project, to set up mongoose you simply have to install it as a dependency just as you do with Node.js.</p>
<pre><code><span class="hljs-built_in">npm</span> i mongoose
</code></pre><p>After installing <code>mongoose</code>, we'll create a folder called <code>utils</code> in our root and create a new file named <code>connectMongo.js</code> file.</p>
<p>In this file, we will export a function that connects us to MongoDB.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650178314792/H0ZTJa7ma.png" alt="image.png" /></p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> mongoose <span class="hljs-keyword">from</span> <span class="hljs-string">'mongoose'</span>;

<span class="hljs-keyword">const</span> connectMongo = <span class="hljs-keyword">async</span> () =&gt; mongoose.connect(process.env.MONGO_URI);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connectMongo;
</code></pre>
<p>Also create a file named <code>.env.local</code> in the root of your project to store the connection URI in your environment variable and hide it from the main code.</p>
<pre><code class="lang-py"><span class="hljs-comment"># I am using MongoDB locally but you can use MongoDB Atlas also if you want</span>
MONGO_URI=<span class="hljs-string">"mongodb://localhost:27017/mongoose_nextjs_demo"</span>
</code></pre>
<h2 id="heading-create-a-basic-mongoose-model">Create a basic mongoose model</h2>
<p>Now that <code>mongoose</code> is set up successfully in our Next.js project, the rest of the work is quite similar to a Node.js app. I personally like to create a folder called <code>models</code> in the root of my project and create my model files there, just like a normal node.js app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650178623079/FI6HSWVCK.png" alt="image.png" /></p>
<p>So now we'll create a file named <code>testModel.js</code> in our <code>models</code> folder where we'll create our mongoose model.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Schema, model, models } <span class="hljs-keyword">from</span> <span class="hljs-string">'mongoose'</span>;

<span class="hljs-keyword">const</span> testSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">email</span>: {
    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span>,
  },
});

<span class="hljs-keyword">const</span> Test = models.Test || model(<span class="hljs-string">'Test'</span>, testSchema);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Test;
</code></pre>
<blockquote>
<p>IMPORTANT: Notice how we use <code>models.Test</code> and then the logical OR operator and then use the <code>model</code> function by mongoose. We do that because we don't want to create a new model every single time we hit an API route in Next.js. If you don't do that and just go with <code>model('Test', testSchema)</code>, you might face an error that would prevent creating/updating etc.</p>
</blockquote>
<h2 id="heading-using-mongoose-in-api-routes">Using mongoose in API routes</h2>
<p>Now that we have our model created, we can use it to see it in action!</p>
<p>Next.js is a full-stack framework, and so it also provides a node environment where we can run Node.js back-end code easily and integrate that with the frontend.</p>
<p>In the <code>pages/api</code> folder, we can create a file or folder that will ultimately create an API route and we can write back-end code in that file and call it as a REST API.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650183014182/dxFl9KmIN.png" alt="image.png" /></p>
<p>For this demo, I created a folder <code>test</code> and a file <code>add.js</code> inside of it which gives the path <code>/api/test/add</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> connectMongo <span class="hljs-keyword">from</span> <span class="hljs-string">'../../../utils/connectMongo'</span>;
<span class="hljs-keyword">import</span> Test <span class="hljs-keyword">from</span> <span class="hljs-string">'../../../models/testModel'</span>;

<span class="hljs-comment">/**
 * @param {import('next').NextApiRequest} req
 * @param {import('next').NextApiResponse} res
 */</span>
<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">addTest</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'CONNECTING TO MONGO'</span>);
    <span class="hljs-keyword">await</span> connectMongo();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'CONNECTED TO MONGO'</span>);

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'CREATING DOCUMENT'</span>);
    <span class="hljs-keyword">const</span> test = <span class="hljs-keyword">await</span> Test.create(req.body);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'CREATED DOCUMENT'</span>);

    res.json({ test });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
    res.json({ error });
  }
}
</code></pre>
<p>Here, we import the <code>connectMongo</code> function and our <code>Test</code> model that we created from the respective files. And the big comment I have at the top is <a target="_blank" href="https://jsdoc.app/">JSDoc</a> which can be used to provide autocomplete and typing in the IDE. You can omit it if you want.</p>
<p>Finally, the code is simple and straightforward, you can use the normal <code>mongoose</code> style code to create a new document. By getting the data from <code>req.body</code>.</p>
<p>You can test it from the <a target="_blank" href="https://www.thunderclient.com/">Thunder Client</a> extension in VS Code, <a target="_blank" href="https://www.postman.com/">Postman</a> or <a target="_blank" href="https://insomnia.rest/download">Insomnia</a>. Whatever you wish! I like to use Thunder Client.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650183454458/zEdrw_Mvy.png" alt="image.png" /></p>
<h2 id="heading-create-new-document-from-front-end">Create new document from front-end</h2>
<p>Now that we have our back-end API created and we have verified that it's working, we can quickly write some front-end code to make it usable in our app.</p>
<p>On the homepage inside the <code>index.js</code> file, I changed the file so that when we click the button, a new document will get added to the database.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">'next/head'</span>;
<span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> <span class="hljs-string">'next/image'</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'../styles/Home.module.css'</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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> createTest = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> randomNum = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000</span>);
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/test/add'</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-attr">name</span>: <span class="hljs-string">`Test <span class="hljs-subst">${randomNum}</span>`</span>,
        <span class="hljs-attr">email</span>: <span class="hljs-string">`test<span class="hljs-subst">${randomNum}</span>@test.com`</span>,
      }),
    });
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
    <span class="hljs-built_in">console</span>.log(data);
  };
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</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">title</span>&gt;</span>Create Next App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">'description'</span> <span class="hljs-attr">content</span>=<span class="hljs-string">'Generated by create next app'</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">'icon'</span> <span class="hljs-attr">href</span>=<span class="hljs-string">'/favicon.ico'</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">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.main}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{createTest}</span>&gt;</span>Create Test<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.title}</span>&gt;</span>
          Welcome to <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">'https://nextjs.org'</span>&gt;</span>Next.js!<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.description}</span>&gt;</span>
          Get started by editing{' '}
          <span class="hljs-tag">&lt;<span class="hljs-name">code</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.code}</span>&gt;</span>pages/index.js<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.grid}</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">main</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.footer}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">'https://vercel.com?utm_source=create-next-app&amp;utm_medium=default-template&amp;utm_campaign=create-next-app'</span>
          <span class="hljs-attr">target</span>=<span class="hljs-string">'_blank'</span>
          <span class="hljs-attr">rel</span>=<span class="hljs-string">'noopener noreferrer'</span>
        &gt;</span>
          Powered by{' '}
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.logo}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Image</span> <span class="hljs-attr">src</span>=<span class="hljs-string">'/vercel.svg'</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">'Vercel Logo'</span> <span class="hljs-attr">width</span>=<span class="hljs-string">{72}</span> <span class="hljs-attr">height</span>=<span class="hljs-string">{16}</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-fetch-and-display-documents">Fetch and display documents</h2>
<p>Now it's time to use Next.js's biggest feature! Server-Side Rendering. We can use SSR in Next.js to easily run back-end Node.js code as we want and the data can be easily accessible through the <code>props</code> to the page.</p>
<p>In the <code>index.js</code> file itself, we'll import the <code>connectMongo</code> and <code>Test</code> again and use them inside the <code>getServerSideProps</code> function that we have to export like this 👇</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> connectMongo <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/connectMongo'</span>;
<span class="hljs-keyword">import</span> Test <span class="hljs-keyword">from</span> <span class="hljs-string">'../models/testModel'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getServerSideProps = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'CONNECTING TO MONGO'</span>);
    <span class="hljs-keyword">await</span> connectMongo();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'CONNECTED TO MONGO'</span>);

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'FETCHING DOCUMENTS'</span>);
    <span class="hljs-keyword">const</span> tests = <span class="hljs-keyword">await</span> Test.find();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'FETCHED DOCUMENTS'</span>);

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">props</span>: {
        <span class="hljs-attr">tests</span>: <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">JSON</span>.stringify(tests)),
      },
    };
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(error);
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">notFound</span>: <span class="hljs-literal">true</span>,
    };
  }
};
</code></pre>
<p>In this function, we can easily fetch any data we want and it will be done on the server and then we have to <strong>return</strong> it as <code>props</code>. That will be accessible to the page. You can read about <a target="_blank" href="https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props"><code>getServerSideProps</code> on the Next.js docs</a></p>
<blockquote>
<p>IMPORTANT: Make sure to sanitize the <code>tests</code> variable with <code>JSON.parse(JSON.stringify(tests))</code> because it contains <code>ObjectID</code> from MongoDB instead of a normal string. This trick converts it into a string that can be passed in the <code>return</code> object.</p>
</blockquote>
<p>That's it! After we're done fetching the data we can easily display it by accessing it through the props on our page and we can use it however we want. In this case we'll map over that data to output every document like so</p>
<pre><code class="lang-jsx"><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">Home</span>(<span class="hljs-params">{ tests }</span>) </span>{
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">//   ...</span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.grid}</span>&gt;</span>
      {tests.map((test) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
          <span class="hljs-attr">href</span>=<span class="hljs-string">"https://nextjs.org/docs"</span>
          <span class="hljs-attr">key</span>=<span class="hljs-string">{test._id}</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.card}</span>
        &gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{test.name} <span class="hljs-symbol">&amp;rarr;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{test.email}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    <span class="hljs-comment">// ...</span>
  );
}
</code></pre>
<p>Finally, this is what our page looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1650184603173/bbdiBR1rw.png" alt="image.png" /></p>
<p>I have explained everything deeply in the YouTube tutorial 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://www.youtube.com/watch?v=cM0pA50R20M">https://www.youtube.com/watch?v=cM0pA50R20M</a></div>
<p>I hope this post helped you successfully set up Mongoose in your Next.js app. If it did, please leave a like!</p>
<p>Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Thanks for reading ✌</p>
]]></content:encoded></item><item><title><![CDATA[🎨 Sort imports using Prettier in a JavaScript Project inside VS Code!]]></title><description><![CDATA[👋 Hey developers! This post is about how you can sort import statements in your JavaScript/TypeScript/React/Node etc projects easily with Prettier in VS Code when you format the code.
https://www.youtube.com/watch?v=QQWgN0_gUxI
What will you achieve...]]></description><link>https://blog.usmans.me/sort-imports-using-prettier-in-a-javascript-project-inside-vs-code</link><guid isPermaLink="true">https://blog.usmans.me/sort-imports-using-prettier-in-a-javascript-project-inside-vs-code</guid><category><![CDATA[Prettier]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[clean code]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Tue, 22 Mar 2022 10:47:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647939834412/-rOHcxwbV.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>👋 Hey developers! This post is about how you can sort import statements in your JavaScript/TypeScript/React/Node etc projects easily with Prettier in VS Code when you format the code.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=QQWgN0_gUxI">https://www.youtube.com/watch?v=QQWgN0_gUxI</a></div>
<h2 id="heading-what-will-you-achieve">What will you achieve?</h2>
<p>By default, we import other files and libraries in an unformatted way. With Prettier and one of it's community plugins, we can easily configure it to sort import statements the way we want them automatically whenever we format code inside VS Code.</p>
<blockquote>
<p>Before</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647944153303/suNfQ7Fnf.png" alt="image.png" /></p>
<blockquote>
<p>After</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647944178892/mAd4GSyrY.png" alt="image.png" /></p>
<h2 id="heading-installation-andamp-configuration">Installation &amp; Configuration</h2>
<p>In your JavaScript project, firstly you have to install and configure Prettier, you can do that easily by installing <code>prettier</code> as a dev dependency by running this command.</p>
<pre><code class="lang-sh">npm install prettier -D
</code></pre>
<p>After installing Prettier, we'll create a configuration file at the root of your project called <code>.prettierrc</code>. In that file, you can write JSON to configure prettier fitting to your needs. This is my configuration.</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"trailingComma"</span>: <span class="hljs-string">"none"</span>,
  <span class="hljs-attr">"arrowParens"</span>: <span class="hljs-string">"avoid"</span>,
  <span class="hljs-attr">"singleQuote"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"printWidth"</span>: <span class="hljs-number">80</span>,
  <span class="hljs-attr">"useTabs"</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">"tabWidth"</span>: <span class="hljs-number">2</span>,
  <span class="hljs-attr">"semi"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<p>Now whenever you format code, Prettier will format it according to your configuration. Next up, we have to install the plugin we are going to use to sort imports.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.npmjs.com/package/@trivago/prettier-plugin-sort-imports">https://www.npmjs.com/package/@trivago/prettier-plugin-sort-imports</a></div>
<p>You can install it as a dev dependency simply by running this command</p>
<pre><code class="lang-sh">npm install @trivago/prettier-plugin-sort-imports -D
</code></pre>
<h2 id="heading-sorting-settings">Sorting Settings</h2>
<p>Once the plugin is installed, you can look around in their documentation on the NPM page, but we are going to keep it simple. </p>
<p>The basic setup is to add 3 options in your prettier config file. <code>importOrder</code>, <code>importOrderSeparation</code> and <code>importOrderSortSpecifiers</code> as follows:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"importOrder"</span>: [<span class="hljs-string">"ARRAY OF IMPORT NAMES"</span>],
  <span class="hljs-attr">"importOrderSeparation"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"importOrderSortSpecifiers"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<p>The main option in these is the <code>importOrder</code> option, in this option, you have to create an array of imports as you want to sort them. In my case, I wanted imports in this order:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> {} <span class="hljs-keyword">from</span> <span class="hljs-string">'next'</span> <span class="hljs-comment">// "next" imports at the top</span>

<span class="hljs-keyword">import</span> {} <span class="hljs-keyword">from</span> <span class="hljs-string">'other-lib'</span>

<span class="hljs-keyword">import</span> config <span class="hljs-keyword">from</span> <span class="hljs-string">'next-seo.config'</span> <span class="hljs-comment">// A single file</span>

<span class="hljs-keyword">import</span> Component <span class="hljs-keyword">from</span> <span class="hljs-string">'components/Component'</span>

<span class="hljs-keyword">import</span> helperFunction <span class="hljs-keyword">from</span> <span class="hljs-string">'utils/helperFunction'</span>

<span class="hljs-keyword">import</span> {} <span class="hljs-keyword">from</span> <span class="hljs-string">'assets/file'</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'@fontsource/font'</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">'others.css'</span>
</code></pre>
<p>To configure this type of order, in the <code>importOrder</code> option, you have to pass an array of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">regular expressions</a>.</p>
<p>My configuration was like this</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"trailingComma"</span>: <span class="hljs-string">"none"</span>,
  <span class="hljs-attr">"arrowParens"</span>: <span class="hljs-string">"avoid"</span>,
  <span class="hljs-attr">"singleQuote"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"printWidth"</span>: <span class="hljs-number">80</span>,
  <span class="hljs-attr">"useTabs"</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">"tabWidth"</span>: <span class="hljs-number">2</span>,
  <span class="hljs-attr">"semi"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"importOrder"</span>: [
    <span class="hljs-string">"^(next/(.*)$)|^(next$)"</span>, <span class="hljs-comment">// Imports by "next"</span>
    <span class="hljs-string">"&lt;THIRD_PARTY_MODULES&gt;"</span>,
    <span class="hljs-string">"next-seo.config"</span>, 
    <span class="hljs-string">"^components/(.*)$"</span>,
    <span class="hljs-string">"^utils/(.*)$"</span>,
    <span class="hljs-string">"^assets/(.*)$"</span>,
    <span class="hljs-string">"^@fontsource/(.*)$"</span>,
    <span class="hljs-string">"^[./]"</span> <span class="hljs-comment">// Other imports</span>
  ],
  <span class="hljs-attr">"importOrderSeparation"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"importOrderSortSpecifiers"</span>: <span class="hljs-literal">true</span>
}
</code></pre>
<p>Here, <code>"&lt;THIRD_PARTY_MODULES"</code> is provided by the plugin itself to place any other libraries in between. By default all third party modules will move at the top.</p>
<p>Now, you can go ahead and enable <strong>Format on Save</strong> setting inside VS Code to format code on save and install the Prettier extension too for the same.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647945251114/dFOBreRKV.png" alt="image.png" /></p>
<h2 id="heading-format-script">Format script</h2>
<p>A quick way to format all the files is by going into your <code>package.json</code> file and adding a script to it like this:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-attr">"format"</span>: <span class="hljs-string">"prettier --write \"./**/*.{ts,tsx,json}\""</span>
}
</code></pre>
<p>You can refer to <a target="_blank" href="https://prettier.io/docs/en/cli.html">Prettier's CLI documentation</a> for more information.</p>
<p>It's better to ignore some files and folders so that they don't get formatted as well by Prettier, for that you can create a <code>.prettierignore</code> file in the root of your project and you can simply name the files and folders you don't want to format. Just like <code>.gitignore</code>.</p>
<p>This is my <code>.prettierignore</code> file:</p>
<pre><code class="lang-sh">.next
node_modules
*-lock.json           <span class="hljs-comment"># package-lock.json</span>
</code></pre>
<p>Then you can run the <code>npm run format</code> command in your terminal and it will format all the required files in your project as per your configuration.</p>
<p>I hope this post helped you make your code look more clean and elegant and readable. If it did, please leave a like!</p>
<p>Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Thanks for reading ✌</p>
]]></content:encoded></item><item><title><![CDATA[🎉 Introducing Only Formats | The quickest way to format code!]]></title><description><![CDATA[Hey everybody!
I saw the Netlify x Hashnode Hackathon and I was very very excited to participate this time. It was quite hard to think about an idea but I finally got one!
Story
This time building an app was a weird and funny experience at the same t...]]></description><link>https://blog.usmans.me/onlyformats</link><guid isPermaLink="true">https://blog.usmans.me/onlyformats</guid><category><![CDATA[Netlify]]></category><category><![CDATA[NetlifyHackathon]]></category><category><![CDATA[React]]></category><category><![CDATA[Prettier]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sun, 27 Feb 2022 12:54:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645965586101/f9tZgtt-T.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://cdn.dribbble.com/users/720738/screenshots/3848385/media/3fb3a31b0a1fd949593feab51cf712a0.gif" alt /></p>
<p>Hey everybody!</p>
<p>I saw the <strong><a target="_blank" href="https://townhall.hashnode.com/netlify-hackathon">Netlify x Hashnode</a></strong> Hackathon and I was very very excited to participate this time. It was quite hard to think about an idea but I finally got one!</p>
<h2 id="heading-story">Story</h2>
<p>This time building an app was a weird and funny experience at the same time.</p>
<p>In the beginning, I, <a class="user-mention" href="https://hashnode.com/@janaSunrise">Sunrit Jana</a>, and <a class="user-mention" href="https://hashnode.com/@FaheemKhancodes">Faheem Khan</a> were about to work on a <em>different idea</em> together, but then because of lack of time management we couldn't do so. And then I came up with this idea and finished it.</p>
<p>I thank them for supporting me with this project too 🙂.</p>
<h2 id="heading-only-formats-what-is-it">Only Formats - What is it?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645956633202/7ott9BUI0.png" alt="frame_edge_mac_v94_light.png" /></p>
<p><strong><a target="_blank" href="http://onlyformats.netlify.app/">Only Formats</a></strong> is a web application that helps you quickly format code and copy it easily!!!</p>
<p>It makes things very easy with a very quick and simple user interface with no complications 💫.</p>
<p>The supported languages that Only Formats can format are:</p>
<ul>
<li>JavaScript</li>
<li>TypeScript</li>
<li>CSS</li>
<li>HTML</li>
<li>PHP</li>
<li>JSON</li>
<li>Markdown</li>
<li>SQL</li>
</ul>
<h2 id="heading-motivation">Motivation</h2>
<p>The real reason and motivation behind building this app were that I saw a lot of people having doubts and when they send the code, it's mostly unformatted, thus making it unreadable.</p>
<p><img src="https://media3.giphy.com/media/3o7btPCcdNniyf0ArS/200.gif" alt /></p>
<p>To understand it, I had to open up VS Code or any other website that takes a lot of my time.</p>
<p>I built this app with a very simple set of tools to format and copy and paste code with syntax highlighting that makes things a lot better!</p>
<h2 id="heading-app-tour">App tour</h2>
<p>The first main page is very self-explanatory, you can select the language you want to format code in or search by clicking on the search icon on the top right. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645964144136/yDTd_5D9s.gif" alt="search.gif" /></p>
<blockquote>
<p>I removed Java temporarily because it throws an unknown error. <a target="_blank" href="https://github.com/max-programming/only-formats/issues/2">ISSUE</a></p>
</blockquote>
<p>Once you've selected that, you will be redirected to that page with the tools. There might or might not be settings for a formatter an indentation. You can set that value and it will reflect changes instantly!</p>
<p>Paste the code or simply type it out on the code editor and once you type in the code, it will format it in one go!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645964675521/UR1dusg0c.gif" alt="paste and copy.gif" /></p>
<p>It's also a PWA (Progressive Web App) so you can install it and work with it offline too</p>
<blockquote>
<p>Also an API to format code is coming soon 😉!</p>
</blockquote>
<h2 id="heading-tech-stack">Tech Stack</h2>
<p>This is one of my favourite parts of the app! I enjoyed using the following Tech Stack!</p>
<ol>
<li>Next.js with TypeScript</li>
<li>Chakra UI</li>
<li>Prettier to format code</li>
<li>Monaco editor for code editing</li>
<li>PrismJS for syntax highlight</li>
<li>Simple Icons (for language icons)</li>
<li>Netlify for deployment</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I really enjoyed building this project and I encourage all of you to contribute to this project! It will be very nice of you to create issues and/or make pull requests to make it better and better every day 😊.</p>
<p><a target="_blank" href="https://github.com/max-programming/only-formats">GitHub Repo</a></p>
<p><a target="_blank" href="https://onlyformats.netlify.app">Live Website</a></p>
<p>Thanks to the folks over at Hashnode and Netlify for this amazing Hackathon! This time I learned a lot of things and most importantly about working with a deadline.</p>
<p>Goodbye everyone</p>
<p><img src="https://media3.giphy.com/media/VgC5dVK3KzQCm1TdPI/200w.gif?cid=82a1493b1y9z1fvlf8tdqyl7h4d4sgp8g8kkej34gl0m9b5s&amp;rid=200w.gif&amp;ct=g" alt /></p>
]]></content:encoded></item><item><title><![CDATA[🗨️ Build a WhatsApp API using Node & Express]]></title><description><![CDATA[Today, you will be able to build a WhatsApp REST API using Node.js and Express using Puppeteer and web scraping.
Although we won't be doing any web scraping, we will use a library that does everything for you already and makes it very easy to work wi...]]></description><link>https://blog.usmans.me/whatsapp-api-node-express</link><guid isPermaLink="true">https://blog.usmans.me/whatsapp-api-node-express</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Express]]></category><category><![CDATA[APIs]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sat, 08 Jan 2022 12:40:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1641644668347/EXSQ8lHur.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://c.tenor.com/8GDoVtr9mvQAAAAC/hey-everyone-spider-man.gif" alt="hey.gif" /></p>
<p>Today, you will be able to build a <strong>WhatsApp REST API</strong> using Node.js and Express using Puppeteer and web scraping.</p>
<p>Although we won't be doing any web scraping, we will use a library that does everything for you already and makes it very easy to work with WhatsApp programmatically.</p>
<h2 id="heading-setup">Setup</h2>
<h3 id="heading-express-server-setup">Express server setup</h3>
<p>To set up the express server, we are not going to do it from scratch, we'll use a generator called  <a target="_blank" href="https://npmjs.org/express-draft"><code>express-draft</code></a>  by  <a target="_blank" href="https://www.youtube.com/c/yoursTRULY267">YoursTruly</a>. Firstly, install <code>express-draft</code> globally and use the following command to generate an express app.</p>
<pre><code>npm i <span class="hljs-operator">-</span>g express<span class="hljs-operator">-</span>draft
exp .
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641634524269/MM1PjxGlU.png" alt="image.png" /></p>
<h3 id="heading-install-whatsapp-web-library">Install Whatsapp Web library</h3>
<blockquote>
<p><strong>Caution</strong>: Installing this package will also download Chromium because of Puppeteer. To disable Chromium download, follow the steps on  <a target="_blank" href="https://blog.usman-s.me/how-to-skip-chromium-download-in-puppeteer">this post</a>  </p>
</blockquote>
<p>So there's an awesome open-source Whatsapp client that connects through the Whatsapp Web browser app made by <a target="_blank" href="https://twitter.com/pedroslopez">Pedro S. Lopez</a>.</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/pedroslopez/whatsapp-web.js/">https://github.com/pedroslopez/whatsapp-web.js/</a></div>
<p>First, we'll install it through NPM <em>or yarn</em>.</p>
<pre><code class="lang-sh">npm i whatsapp-web.js
</code></pre>
<p>After we're done with that, we can set it up in our <code>app.js</code> file by following the given  <a target="_blank" href="https://github.com/pedroslopez/whatsapp-web.js/blob/main/example.js">example</a>.</p>
<p>We can alter the file as follows,</p>
<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> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-errors'</span>);
<span class="hljs-keyword">const</span> morgan = <span class="hljs-built_in">require</span>(<span class="hljs-string">'morgan'</span>);
<span class="hljs-keyword">const</span> { Client } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'whatsapp-web.js'</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-keyword">const</span> SESSION_FILE_PATH = <span class="hljs-string">'./session.json'</span>;
<span class="hljs-keyword">let</span> sessionCfg;
<span class="hljs-keyword">if</span> (fs.existsSync(SESSION_FILE_PATH)) {
  sessionCfg = <span class="hljs-built_in">require</span>(SESSION_FILE_PATH);
}

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> Client({
  <span class="hljs-attr">puppeteer</span>: { <span class="hljs-attr">headless</span>: <span class="hljs-literal">false</span> }, <span class="hljs-comment">// Make headless true or remove to run browser in background</span>
  <span class="hljs-attr">session</span>: sessionCfg,
});

client.initialize();
</code></pre>
<p>While using this library, whenever a user logs in, their information will be stored in a <code>session.json</code> file, which is then used to authenticate the user the next time when the server starts.</p>
<p><strong>Important</strong>: Create a <code>nodemon.json</code> file in the root folder and add these contents to ignore the <code>session.json</code> file whenever it changes.</p>
<pre><code class="lang-json"><span class="hljs-comment">// "$schema" can be omitted it's used for IntelliSense. REMOVE THIS COMMENT</span>
{
  <span class="hljs-attr">"$schema"</span>: <span class="hljs-string">"https://json.schemastore.org/nodemon.json"</span>,
  <span class="hljs-attr">"ignore"</span>: [<span class="hljs-string">"session.json"</span>]
}
</code></pre>
<h2 id="heading-creating-routes-and-user-login">Creating routes and user login</h2>
<h3 id="heading-using-events">Using events</h3>
<p><code>whatsapp-web.js</code> has a lot of events to work with, and we'll now use some of them to get the QR code, check the authentication, etc.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Add this after express code but before starting the server</span>

client.on(<span class="hljs-string">'qr'</span>, <span class="hljs-function"><span class="hljs-params">qr</span> =&gt;</span> {
  <span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> This event will not be fired if a session is specified.</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'QR RECEIVED'</span>, qr);
  app.get(<span class="hljs-string">'/getqr'</span>, <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
    res.send({ qr });
  });
});

client.on(<span class="hljs-string">'authenticated'</span>, <span class="hljs-function"><span class="hljs-params">session</span> =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'AUTHENTICATED'</span>, session);
  sessionCfg = session;
  fs.writeFile(SESSION_FILE_PATH, <span class="hljs-built_in">JSON</span>.stringify(session), <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
    <span class="hljs-keyword">if</span> (err) {
      <span class="hljs-built_in">console</span>.error(err);
    }
  });
});

client.on(<span class="hljs-string">'auth_failure'</span>, <span class="hljs-function"><span class="hljs-params">msg</span> =&gt;</span> {
  <span class="hljs-comment">// Fired if session restore was unsuccessfull</span>
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'AUTHENTICATION FAILURE'</span>, msg);
});

client.on(<span class="hljs-string">'ready'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'READY'</span>);
});

<span class="hljs-comment">// Listening for the server</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">`🚀 @ http://localhost:<span class="hljs-subst">${PORT}</span>`</span>));
</code></pre>
<p>The above code uses events provided by the library to tackle different situations. They are pretty self-explanatory so I am not gonna explain each of them.</p>
<p>In the <code>"qr"</code> method, we create a route that sends the QR code as the response. The QR code is in raw format, meaning it needs to be generated so for the purpose of this tutorial, we'll use a library called <code>qrcode-terminal</code> to show the QR Code in the terminal.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Run `npm i qrcode-terminal` before this</span>

<span class="hljs-keyword">const</span> qrcode = <span class="hljs-built_in">require</span>(<span class="hljs-string">'qrcode-terminal'</span>)

client.on(<span class="hljs-string">'qr'</span>, <span class="hljs-function"><span class="hljs-params">qr</span> =&gt;</span> {
  <span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> This event will not be fired if a session is specified.</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'QR RECEIVED'</span>, qr);
  qrcode.generate(qr, { <span class="hljs-attr">small</span>: <span class="hljs-literal">true</span> }); <span class="hljs-comment">// Add this line</span>
  app.get(<span class="hljs-string">'/getqr'</span>, <span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
    res.send({ qr });
  });
});
</code></pre>
<h3 id="heading-the-sendmessage-endpoint">The <code>sendmessage</code> endpoint</h3>
<p>Now that we have everything set up, let's do the most exciting part that is to send a message using our own API.</p>
<p>For that, we create a route in the <code>app.js</code> file itself.</p>
<p>Let's create the POST endpoint for <code>sendmessage</code> and it will be an <code>async</code> function with a try-catch block.</p>
<pre><code class="lang-js">app.post(<span class="hljs-string">'/sendmessage'</span>, <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Magic happens here</span>
  } <span class="hljs-keyword">catch</span> (error) {
    next(error)
  }
})
</code></pre>
<p>In the body of the request, the user has to enter two pieces of data.</p>
<ol>
<li>Mobile number</li>
<li>Message</li>
</ol>
<p>We'll identify those as <code>number</code> and <code>message</code> respectively. Hence, we get them from the request body, and use them to very easily send the message <strong>from the client to the given number</strong>.</p>
<p>To send a message, we use the <code>client.sendMessage</code> method and these are the arguments we need to pass in</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641641747436/t-Pzomgq-.png" alt="image.png" /></p>
<pre><code class="lang-js">app.post(<span class="hljs-string">'/sendmessage'</span>, <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> { number, message } = req.body; <span class="hljs-comment">// Get the body</span>
    <span class="hljs-keyword">const</span> msg = <span class="hljs-keyword">await</span> client.sendMessage(<span class="hljs-string">`<span class="hljs-subst">${number}</span>@c.us`</span>, message); <span class="hljs-comment">// Send the message</span>
    res.send({ msg }); <span class="hljs-comment">// Send the response</span>
  } <span class="hljs-keyword">catch</span> (error) {
    next(error);
  }
});
</code></pre>
<p>Now here, in the <code>sendMessage</code> method, we pass in the mobile number and the message itself. With the mobile number, we have to attach <code>@c.us</code> at the very end, so we do that with template literals in JavaScript.</p>
<h2 id="heading-testing-the-api">Testing the API</h2>
<p>In order to test our API, we first run it using <code>npm run dev</code>. That will open up a browser (if you've set <code>headless</code> to <code>false</code>)</p>
<p>Running the server will give us the QR Code to authenticate because it's the first time. So, you have to scan it through WhatsApp.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641642355849/9jDhG2-nd.png" alt="image.png" /></p>
<p>Once authenticated, you will notice that a <code>session.json</code> file has been created with the following contents.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641642315529/HTwbVxMBq.png" alt="image.png" /></p>
<p>Now in VS Code itself, we'll use an extension called <strong>Thunder Client</strong>, which works like Postman for API testing.  <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client">Here's the link</a> </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641642506648/MYLChp2-l.png" alt="image.png" /></p>
<p>Create a <strong>New Request</strong> in Thunder Client, and then add the following details. In the <code>number</code> field, add the mobile number followed by the country code of the number.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641645569198/ysdOUnwwE.png" alt="image.png" /></p>
<blockquote>
<p>Look at the image carefully</p>
</blockquote>
<p>And then hit <strong>Send</strong>.</p>
<p>If the message is sent successfully, the number you entered will receive it and you will get back the <code>msg</code> as the response. If not, then an error.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1641643609398/muQhzRQSn.png" alt="image.png" /></p>
<p><img src="https://c.tenor.com/68a5_Ug62VYAAAAM/success-strong.gif" alt="success.gif" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You can read more about the library 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://wwebjs.dev/">https://wwebjs.dev/</a></div>
<p>I hope you enjoyed building out the WhatsApp API using Node.js, Express, and <code>whatsapp-web.js</code>.</p>
<p>Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Until next time, keeping awesome ✌️.</p>
]]></content:encoded></item><item><title><![CDATA[😎 How to convert a normal React form to use react-hook-form?]]></title><description><![CDATA[Hey everyone!
Nice to see you all around again! Today you'll find out how easy it is to use the  react-hook-form  library for forms instead of the normal method of forms in React.

So, the first thing is first, normally, in React we use state, and wh...]]></description><link>https://blog.usmans.me/how-to-convert-a-normal-react-form-to-use-react-hook-form</link><guid isPermaLink="true">https://blog.usmans.me/how-to-convert-a-normal-react-form-to-use-react-hook-form</guid><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Mon, 08 Nov 2021 08:56:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636361670727/LQQwoWgyC.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-hey-everyone">Hey everyone!</h2>
<p>Nice to see you all around again! Today you'll find out how easy it is to use the  <a target="_blank" href="https://react-hook-form.com/"><code>react-hook-form</code></a>  library for forms instead of the normal method of forms in React.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636358413364/vCNnmkq-M.png" alt="image.png" /></p>
<p>So, the first thing is first, normally, in React we use state, and whenever the value of an input changes, we change the state. This method's good but there is a lot of code. Here's how the code looks like in this case.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</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">LoginForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [password, setPassword] = useState(<span class="hljs-string">''</span>);

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    e.preventDefault()
    <span class="hljs-comment">// Submit logic</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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{onSubmit}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">'email'</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setEmail(e.target.value)}
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">'password'</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{password}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPassword(e.target.value)}
        /&gt;
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>And I personally feel that this is indeed a lot of code that could be made better. That's why you should use <code>react-hook-form</code>. </p>
<p>So to convert this normal one to use <code>react-hook-form</code>, we install it via NPM or Yarn.</p>
<pre><code><span class="hljs-built_in">npm</span> i react-hook-form
<span class="hljs-comment"># yarn add react-hook-form</span>
</code></pre><p>And then, the first thing we have to do is get rid of the <strong>state we created</strong>, the <code>onSubmit</code> function and the <code>value</code> and <code>onChange</code> props too. </p>
<p>After we remove that bit of code, we import <code>useForm</code> from <code>react-hook-form</code>, and this is how we use it.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-hook-form'</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">LoginForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { register, handleSubmit } = useForm();

  <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">form</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'email'</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'password'</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Then, we use the <code>register</code> function as a prop in the inputs to register each input with a name to get the value of it, like this.</p>
<pre><code class="lang-js"><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">form</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'email'</span> {<span class="hljs-attr">...register</span>('<span class="hljs-attr">email</span>')} /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'password'</span> {<span class="hljs-attr">...register</span>('<span class="hljs-attr">password</span>')} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
);
</code></pre>
<p>Then, for the form submission, we use the <code>handleSubmit</code> provided by the <code>useForm</code> hook with our own submit function which provides us the values of the inputs directly. We can also destructure the values from it.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-hook-form'</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">LoginForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { register, handleSubmit } = useForm();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> { <span class="hljs-comment">// OR DESTRUCTURING ({ email, password })</span>
    <span class="hljs-built_in">console</span>.log(data.email, data.password)
    <span class="hljs-comment">// Submit logic</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">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span> {/* handleSubmit is invoked and onSubmit is passed into it */}
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'email'</span> {<span class="hljs-attr">...register</span>('<span class="hljs-attr">email</span>')} /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'password'</span> {<span class="hljs-attr">...register</span>('<span class="hljs-attr">password</span>')} /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This way, it automatically prevents the page from refreshing on submit.</p>
<h2 id="heading-using-it-with-typescript">💪 Using it with TypeScript</h2>
<p>Using RHF with TypeScript is super easy because firstly, you don't need to install separate type definitions as they come along with RHF.</p>
<p>You've to define an <code>interface</code> for the fields you're using, and then pass it in <code>useForm</code> as generic.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">interface</span> LoginFields {
  email: <span class="hljs-built_in">string</span>;
  password: <span class="hljs-built_in">string</span>;
}

<span class="hljs-comment">// In component</span>
<span class="hljs-keyword">const</span> { register, handleSubmit } = useForm&lt;LoginFields&gt;();
</code></pre>
<p>And while calling the submit function, you've to set the type of the <code>onSubmit</code> function to the type <code>SubmitHandler</code> provided directly by RHF.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { useForm, SubmitHandler } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-hook-form'</span>;

<span class="hljs-comment">// In component</span>
<span class="hljs-keyword">const</span> onSubmit: SubmitHandler&lt;LoginFields&gt; = <span class="hljs-function">(<span class="hljs-params">{ email, password }</span>) =&gt;</span> { 
    <span class="hljs-built_in">console</span>.log(email, password)
    <span class="hljs-comment">// Submit logic</span>
  }
</code></pre>
<p>This way you also get good IntelliSense in your IDE or code editor
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636359131717/olZ_U7uCy.gif" alt="intellisense.gif" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You can read a lot more functionalities provided by <code>react-hook-form</code> on  <a target="_blank" href="https://react-hook-form.com/">their website</a>. </p>
<p>I hope you liked it! Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Until next time, keeping awesome ✌️</p>
]]></content:encoded></item><item><title><![CDATA[How to make your QR Code Generator using HTML, CSS & JavaScript]]></title><description><![CDATA[Hey all 🤘!
So I am back again! This time we have a little different project to build and it's an easy one.
I discovered that this was interesting and indeed it is!
I will teach you how you can make your own QR Code Generator using HTML, CSS, and Jav...]]></description><link>https://blog.usmans.me/how-to-make-your-qr-code-generator-using-html-css-and-javascript</link><guid isPermaLink="true">https://blog.usmans.me/how-to-make-your-qr-code-generator-using-html-css-and-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[vanilla-js]]></category><category><![CDATA[Javascript library]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sun, 26 Sep 2021 09:09:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632647097912/4rTqHn94N.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-hey-all">Hey all 🤘!</h2>
<p>So I am back again! This time we have a little different project to build and it's an easy one.</p>
<p>I discovered that this was interesting and indeed it is!</p>
<p>I will teach you how you can make your own QR Code Generator using HTML, CSS, and JavaScript!</p>
<iframe height="300" style="width:100%" src="https://codepen.io/Max_Programming/embed/eYRPbZm?default-tab=result">
  See the Pen <a href="https://codepen.io/Max_Programming/pen/eYRPbZm">
  QR Code Generator using JavaScript</a> by Max Programming (<a href="https://codepen.io/Max_Programming">@Max_Programming</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

<p><img src="https://media0.giphy.com/media/5zf2M4HgjjWszLd4a5/giphy.gif" alt /></p>
<h2 id="heading-html">HTML</h2>
<p>The HTML we need is very very straightforward! What we need in this case is this:</p>
<pre><code class="lang-xml"><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">title</span>&gt;</span>QR Code Generator<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">h1</span>&gt;</span>QR Code Generator<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> 
    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> 
    <span class="hljs-attr">spellcheck</span>=<span class="hljs-string">"false"</span>
    <span class="hljs-attr">id</span>=<span class="hljs-string">"text"</span>
    <span class="hljs-attr">value</span>=<span class="hljs-string">"https://google.com"</span>
  /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"qrcode"</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">"https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.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>
<ul>
<li><p>We add some attributes to the input to select it in JavaScript, we remove spellcheck from the input so any spelling is valid and we add a default value for the input.</p>
</li>
<li><p>We add <code>&lt;div&gt;</code> with an <code>id</code> of <code>qrcode</code> to use it in JavaScript and output the QR Code</p>
</li>
<li><p>We create the <code>&lt;script&gt;</code> tag to include a simple library that helps us generating the QR Code.</p>
</li>
</ul>
<h2 id="heading-css">CSS</h2>
<p>For the CSS, we add some super simple styles to make it look a little better than default.</p>
<p>We are adding the CSS in <code>&lt;style&gt;</code> tags because it's minimal.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
* {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">80%</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
    <span class="hljs-attribute">margin</span>: auto;
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">place-items</span>: center;
}

<span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">font-family</span>: sans-serif;
}

<span class="hljs-selector-tag">input</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid steelblue;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5rem</span>;
    <span class="hljs-attribute">letter-spacing</span>: <span class="hljs-number">2px</span>;
    <span class="hljs-attribute">outline</span>: none;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Most of the styling is done for the <code>input</code> element to give it a good border and padding.</p>
<h2 id="heading-javascript">JavaScript</h2>
<p>The JavaScript used to generate the QR Code is also very minimal so we'll write it in the <code>&lt;script&gt;</code> tags inside our HTML.</p>
<p>Firstly, we select the HTML elements by ID to use them.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="javascript">

<span class="hljs-keyword">const</span> qrcode = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"qrcode"</span>);
<span class="hljs-keyword">const</span> textInput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"text"</span>);

</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Then, we use the <code>QRCode</code> constructor to create an instance of it. Which comes along with the <code>qrcode.js</code> library we added the script for.</p>
<p>We pass in the <code>&lt;div&gt;</code> with the <code>id</code> of <code>qrcode</code> in the constructor And we use the <code>makeCode</code> method to embed the <code>value</code> of the input in a QR Code.</p>
<blockquote>
<p>The <code>trim()</code> method helps in removing extra space before and after a string</p>
</blockquote>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> qrcode = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"qrcode"</span>);
<span class="hljs-keyword">const</span> textInput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"text"</span>);

<span class="hljs-keyword">const</span> qr = <span class="hljs-keyword">new</span> QRCode(qrcode);
qr.makeCode(textInput.value.trim());
</code></pre>
<p>Now, whenever the user types into the input, we generate the QR Code again using the <code>makeCode</code> method.</p>
<p>We use the <code>oninput</code> event on the <code>textInput</code> element for that. We get an event object with the function, we use the <code>e.target.value</code> to get the current value of the input and generate the QR Code accordingly!</p>
<pre><code class="lang-javascript">textInput.oninput = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    qr.makeCode(e.target.value.trim());
};
</code></pre>
<p>Here is the final code for the QR Code generator: https://easypastes.tk/pastes/qrcode-gen</p>
<p>I hope you liked it! Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my</strong> <a target="_blank" href="https://youtube.com/MaxProgramming"><strong>YouTube channel</strong></a> <strong>and my</strong> <a target="_blank" href="https://twitter.com/maxprogramming1"><strong>Twitter</strong></a> <strong>😉</strong></p>
<p>Until next time, keeping awesome ✌️</p>
]]></content:encoded></item><item><title><![CDATA[👽️ What are Netlify Serverless Functions and how to use them?]]></title><description><![CDATA[👋 Welcome back!
So I recently looked into Serverless functions or Lambda functions and I learned them.
They can be extremely useful when building an app that is fully front-end and there are chances to expose API keys and so on.
So today we'll be le...]]></description><link>https://blog.usmans.me/what-are-netlify-serverless-functions-and-how-to-use-them</link><guid isPermaLink="true">https://blog.usmans.me/what-are-netlify-serverless-functions-and-how-to-use-them</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[Netlify]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[serverless]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Fri, 20 Aug 2021 16:07:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629475587236/31szEXipw.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="welcome-back">👋 Welcome back!</h2>
<p>So I recently looked into Serverless functions or Lambda functions and I learned them.</p>
<p>They can be extremely useful when building an app that is fully front-end and there are chances to expose API keys and so on.</p>
<p>So today we'll be learning what exactly are serverless functions and how could we use them with  <a target="_blank" href="https://netlify.com">Netlify</a>.</p>
<h2 id="what-are-serverless-functions">❓ What are serverless functions?</h2>
<p><img src="https://media1.giphy.com/media/XAZXdtskTiFVIpGpJV/giphy.gif" alt="1.gif" /></p>
<p>In simple words, serverless functions are a <strong>replacement to a custom node.js server</strong>. If you are familiar with Node.js and creating APIs using Node, serverless functions are easy to understand.</p>
<p>A Node.js server and serverless functions are exactly the same but the biggest difference between them is,</p>
<ul>
<li>Node.js servers require you to manage the server</li>
<li>Serverless functions are handled by another provider</li>
</ul>
<h3 id="example">🪜 Example</h3>
<p>If you have a website that runs at <code>coolsite.com</code> and is delivered by a CDN service like <a target="_blank" href="https://netlify.com">Netlify</a>, your serverless functions might be running at <code>coolsite.com/api/...</code>.</p>
<p>Whilst if you have a custom Node.js server, you have to deploy it somewhere else to keep it running like on <a target="_blank" href="https://heroku.com/">Heroku</a>.</p>
<h2 id="using-netlify-serverless-functions">🏗️ Using Netlify Serverless functions</h2>
<p><img src="https://media4.giphy.com/media/NsIwMll0rhfgpdQlzn/giphy.gif" alt /></p>
<p>Say you have a static HTML, CSS, and JS website, and you want to use serverless functions on that site. In simple words, you want to create an API that runs <strong>backend code</strong>. </p>
<p>Like fetching data from an external API, making database queries, etc...</p>
<p>The first thing you will need to do is install <code>netlify-cli</code> globally on your machine. You can do that by running:</p>
<pre><code class="lang-bash">npm i -g netlify-cli
</code></pre>
<p>After doing that, in your project folder, create a <code>netlify.toml</code> file with this content, this specifies the path of the folder where you want your functions to be</p>
<pre><code class="lang-toml"><span class="hljs-section">[build]</span>
    <span class="hljs-attr">functions</span> = <span class="hljs-string">"functions"</span>
</code></pre>
<p>Then run this command in the terminal, and it will ask you a few questions.</p>
<pre><code class="lang-bash">netlify <span class="hljs-built_in">functions</span>:create
</code></pre>
<p>You can make your choice as per your preference, we'll choose JavaScript and <code>hello-world</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629454753907/NNv4dJ0Zs.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629454811482/kch-e2Ir9.png" alt="image.png" /></p>
<p>After you have entered the name of your function in the prompt, you will see a folder inside the <code>functions</code> folder for your <strong>Serverless Function</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629454877961/Dma_NXEPh.png" alt="image.png" /></p>
<p>Now that file simply exports a function, and that function <strong>returns the response</strong>, just like in a Node.js server.</p>
<p>For this demo, I simplified the file and made the function return some dummy data, here's how the file looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handler = <span class="hljs-keyword">async</span> event =&gt; {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-string">'Hello, World!'</span>,
  };
};

<span class="hljs-built_in">module</span>.exports = { handler };
</code></pre>
<p>Here, the parameter called <code>event</code> is an object with the following properties:</p>
<pre><code class="lang-js">{
    <span class="hljs-attr">path</span>: <span class="hljs-string">"Path parameter"</span>,
    <span class="hljs-attr">httpMethod</span>: <span class="hljs-string">"Incoming request’s method name"</span>,
    <span class="hljs-attr">headers</span>: {Incoming request headers},
    <span class="hljs-attr">queryStringParameters</span>: {Query string parameters},
    <span class="hljs-attr">body</span>: <span class="hljs-string">"A JSON string of the request payload"</span>,
    <span class="hljs-attr">isBase64Encoded</span>: <span class="hljs-string">"A boolean flag to indicate if the applicable request payload is Base64-encoded"</span>
}
</code></pre>
<p>To see the function in action, you can run the command <code>netlify dev</code>, it'll start a dev server with hot reload on port 8888, and follow these steps to see how you can use it.</p>
<pre><code class="lang-bash">netlify dev
</code></pre>
<p>On <code>localhost:8888</code>, append this part: <code>/.netlify/functions/[FUNCTION_NAME]</code>. So the URL should look like this: http://localhost:8888/.netlify/functions/hello-world</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629455172207/RiCx8_3_-.png" alt="image.png" /></p>
<p>If I changed the response from normal text to this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">return</span> {
  <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    <span class="hljs-attr">hello</span>: <span class="hljs-string">'world'</span>,
  }),
};
</code></pre>
<p>The result will be this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629455584228/-ZA9pMa5R.png" alt="image.png" /></p>
<blockquote>
<p>Similarly, you can write <strong>any valid Node.js code</strong> in the function file, and that will work as your back-end code.</p>
</blockquote>
<h2 id="using-api-endpoint">♻️ Using <code>/api/*</code> endpoint</h2>
<p>Now a lot of you might not be liking the endpoint <code>/.netlify/functions/*</code>, so to convert that endpoint to a simpler one, we can edit the <code>netlify.toml</code> file with this config:</p>
<pre><code class="lang-toml"><span class="hljs-section">[build]</span>
    <span class="hljs-attr">functions</span> = <span class="hljs-string">"functions"</span>
<span class="hljs-comment"># Add from here</span>
<span class="hljs-section">[[redirects]]</span>
    <span class="hljs-attr">from</span> = <span class="hljs-string">"api/*"</span>
    <span class="hljs-attr">to</span>= <span class="hljs-string">".netlify/functions/:splat"</span>
    <span class="hljs-attr">status</span> = <span class="hljs-number">200</span>
</code></pre>
<p>Now if you were to visit http://localhost:8888/api/hello-world, it will give you the same output!</p>
<h2 id="fetching-the-data-from-the-front-end">🏋️‍♂️ Fetching the data from the front-end</h2>
<p>Now that we have our function created, we can easily fetch the data from our frontend JavaScript.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span>(<span class="hljs-params"></span>) </span>{
  fetch(<span class="hljs-string">'/api/hello-world'</span>)
    .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json())
    .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(data);
    });
}

fetchData();
</code></pre>
<p>And now when you check it on <code>localhost:8888</code>, in the console, we get the response successfully.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629455872758/LmdfyjNJ7.png" alt="image.png" /></p>
<p>Read more on the documentation: https://docs.netlify.com/functions/build-with-javascript/</p>
<p>Thanks for reading!</p>
<p>I hope you liked it! Comment down your thoughts! There is always room for improvement so let me know your suggestions!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Until next time, keeping awesome ✌️!</p>
]]></content:encoded></item><item><title><![CDATA[🍽️ Next.js Fetching methods - getStaticProps explained]]></title><description><![CDATA[👋 Welcome back!
Today I thought of starting my first series about  Next.js Fetching methods because many people (including me) don't understand them easily.
I will make these methods very easy for you to understand so that you don't have to be worri...]]></description><link>https://blog.usmans.me/getstaticprops-in-nextjs</link><guid isPermaLink="true">https://blog.usmans.me/getstaticprops-in-nextjs</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Thu, 19 Aug 2021 06:50:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629355732366/z3F831Ivg.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="welcome-back">👋 Welcome back!</h2>
<p>Today I thought of starting my first series about  <a target="_blank" href="https://blog.usman-s.me/series/fetching-in-nextjs">Next.js Fetching methods</a> because many people (including me) don't understand them easily.</p>
<p>I will make these methods very easy for you to understand so that you don't have to be worried about <strong>how it works</strong>.</p>
<p><img src="https://media2.giphy.com/media/5zf2M4HgjjWszLd4a5/200.gif" alt /></p>
<h2 id="what-is-getstaticprops">What is <code>getStaticProps</code>?</h2>
<p>In simple words, <code>getStaticProps</code> is a method that can be exported from a <strong>page</strong> in Next.js which is simply used to get some data for further use.</p>
<p>For eg.</p>
<pre><code class="lang-js"><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">MainPage</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{props.helloWorld}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getStaticProps = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      <span class="hljs-attr">helloWorld</span>: <span class="hljs-string">'Hello World'</span>
    }
  }
}
</code></pre>
<p>We get back data in the form of <code>props</code>, but we don't use <code>getStaticProps</code> this way 👆.</p>
<p>If you have a database or you want to fetch some data from an API, you can use <code>getStaticProps</code>. But only <strong>if that data is STATIC</strong>.</p>
<p>The <code>getStaticProps</code> method runs <strong>at the build time</strong>, so whatever you write inside the method, is available to you <strong>statically</strong>. And it does not change over time because <strong>YOU NEVER FETCH THE DATA AGAIN</strong>.</p>
<p><img src="https://c.tenor.com/B-WCTfAez-kAAAAC/everything-is-ready-all-set.gif" alt /></p>
<h2 id="better-example">Better example</h2>
<p>Now let's take a better example to use <code>getStaticProps</code> in Next.js and why you would want to use it instead of the <em>normal fetching in React</em>.</p>
<blockquote>
<p>By using <code>getStaticProps</code>, the data is only fetched once and is READY TO USE without refetching.</p>
</blockquote>
<p>Suppose you are building an app that has <strong>a list of people</strong>, and that list is always static. You want to show or use that list but you have them stored in the database or you are using an external API.</p>
<p>We will take an example of  <a target="_blank" href="https://jsonplaceholder.typicode.com/">JSONPlaceholder API</a>  and we want to fetch the  <a target="_blank" href="https://jsonplaceholder.typicode.com/users">users</a> from the API.</p>
<p>This is how the code will look like:</p>
<pre><code class="lang-jsx"><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">MainPage</span>(<span class="hljs-params">{ people }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {people.map(person =&gt; (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{person.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Website: {person.website}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          Email: <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>{person.email}<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
      ))}
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getStaticProps = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/users'</span>);
  <span class="hljs-keyword">const</span> people = <span class="hljs-keyword">await</span> response.json();

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      people
    }
  };
};
</code></pre>
<p><strong>Now when the app gets built using <code>npm run build</code>, the data will be fetched at that point and it will be </strong>READY TO USE<strong> in your app.</strong></p>
<p>So there is no need to fetch the data, show loading spinner, etc, etc. <strong>THE DATA IS ONLY FETCHED ONCE.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629351612242/it-d3oAAM.png" alt="image.png" /></p>
<p>Thanks for reading!</p>
<p>I hope you liked it! Read the other posts of this <a target="_blank" href="https://blog.usman-s.me/series/fetching-in-nextjs">series</a>! Comment down your thoughts! There is always room for improvement so let me know your suggestions!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Until next time, keeping awesome ✌️!</p>
]]></content:encoded></item><item><title><![CDATA[⚡ How to skip Chromium download in Puppeteer?]]></title><description><![CDATA[Hello again 👋!
If you're a Node.js developer and you've used Puppeteer for web scraping, you might have seen that it downloads Chromium whenever you install puppeteer.

Many of you people don't like to download an external web browser for this. You ...]]></description><link>https://blog.usmans.me/how-to-skip-chromium-download-in-puppeteer</link><guid isPermaLink="true">https://blog.usmans.me/how-to-skip-chromium-download-in-puppeteer</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[web scraping]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Wed, 18 Aug 2021 10:59:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629284301822/qFmrKbq2T.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="hello-again">Hello again 👋!</h2>
<p>If you're a Node.js developer and you've used Puppeteer for web scraping, you might have seen that it downloads Chromium whenever you install <code>puppeteer</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629274490931/ylVdgUI0f.png" alt="image.png" /></p>
<p>Many of you people don't like to download an external web browser for this. You might have Chrome, Edge, Brave, or any other Chromium-based browser on your system so why not use that?</p>
<p><img src="https://i.giphy.com/media/BpGWitbFZflfSUYuZ9/giphy.gif" alt="1.gif" /></p>
<h2 id="step-1-set-the-environment-variables">Step 1 - Set the environment variables</h2>
<p>Whenever you install Puppeteer, it will first check for the environment variables listed below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629278289686/EcmxpVUpV.png" alt="image.png" /></p>
<blockquote>
<p>Read more on DevDocs: https://devdocs.io/puppeteer/index#environment-variables</p>
</blockquote>
<p>We are interested in <code>PUPPETEER_SKIP_CHROMIUM_DOWNLOAD</code> and <code>PUPPETEER_EXECUTABLE_PATH</code>.</p>
<p>In your operating system, you have to set these two environment variables to these values 👇</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Key</td><td>Value</td></tr>
</thead>
<tbody>
<tr>
<td>PUPPETEER_SKIP_CHROMIUM_DOWNLOAD</td><td>true</td></tr>
<tr>
<td>PUPPETEER_EXECUTABLE_PATH</td><td>{ PATH_TO_CHROME_OR_CHROMIUM }</td></tr>
</tbody>
</table>
</div><h2 id="on-windows">On Windows</h2>
<p>Search this term <code>Edit the system environment variables</code> in Start Menu and open it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629278539460/sA6iv6lmx.png" alt="image.png" /></p>
<p>Click this button on the bottom right:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629278611843/w-R-M8rlY.png" alt="image.png" /></p>
<p>Click on the <strong>New</strong> button under <strong>System variables</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629278662747/WHH5KilX1.png" alt="image.png" /></p>
<p>Enter the variable name and value as given below:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Key</td><td>Value</td></tr>
</thead>
<tbody>
<tr>
<td>PUPPETEER_SKIP_CHROMIUM_DOWNLOAD</td><td>true</td></tr>
<tr>
<td>PUPPETEER_EXECUTABLE_PATH</td><td>{ PATH_TO_CHROME_OR_CHROMIUM }</td></tr>
</tbody>
</table>
</div><h3 id="find-browsers-path">Find browser's path</h3>
<p>The simplest way to find the path to your browser's executable (on Windows) is to right-click the shortcut on the desktop, and click on <strong>Open file location</strong>.</p>
<p>In my case, I used <a target="_blank" href="https://microsoftedge.com">Microsoft Edge</a> so this was the path: <code>C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629278809164/C8wooA7Fj.png" alt="image.png" /></p>
<p>It'll take you to the file location and you can copy the path, and paste it into the environment variables.</p>
<p><img src="https://c.tenor.com/oz5lssXIlfkAAAAC/sgn-we-did-it.gif" alt="2.gif" /></p>
<p>Thanks for reading!</p>
<p>I hope you liked it! Comment down your thoughts! There is always room for improvement so let me know your suggestions!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Until next time, keeping awesome ✌️!</p>
]]></content:encoded></item><item><title><![CDATA[😱 Make a Random Meme API With Node.js and Puppeteer]]></title><description><![CDATA[👋 Hello there
Today's article is all about how you can make a Random Meme API using Node.js and web scraping. We'll be using Fastify for our API and we'll be using Puppeteer to scrape the web and get the random meme.
This random meme API was inspire...]]></description><link>https://blog.usmans.me/make-a-random-meme-api-with-nodejs-and-puppeteer</link><guid isPermaLink="true">https://blog.usmans.me/make-a-random-meme-api-with-nodejs-and-puppeteer</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[web scraping]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Tue, 17 Aug 2021 16:34:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629217819962/54P2j0rjH.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="hello-there">👋 Hello there</h1>
<p>Today's article is all about how you can make a <strong>Random Meme</strong> API using Node.js and web scraping. We'll be using <a target="_blank" href="https://www.fastify.io/">Fastify</a> for our API and we'll be using <a target="_blank" href="https://github.com/puppeteer/puppeteer">Puppeteer</a> to scrape the web and get the random meme.</p>
<p>This random meme API was inspired by the same kind of API <a target="_blank" href="https://github.com/techytushar/random-memer">here</a>. But I wanted to build it using Node.js and Puppeteer.</p>
<p>We'll be scraping <a target="_blank" href="http://memedroid.com/">Memedroid</a> using the  <a target="_blank" href="http://npmjs.org/package/puppeteer">Puppeteer NPM package</a>.</p>
<h2 id="initializing-the-project">Initializing the project</h2>
<p>First of all, we'll need to create a folder with the name we want and we'll need to initialize our Node.js app in that folder. We do it using this command:</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<p>Then we need two dependencies to install, simply install <code>puppeteer</code> and <code>fastify</code>.</p>
<pre><code class="lang-bash">npm i puppeteer fastify
</code></pre>
<h2 id="using-fastify-for-api">Using Fastify for API</h2>
<p>After we have our project set up and our dependencies installed, we're good to go with writing the code! Create an <code>index.js</code> file and import <code>fastify</code> with this code to create the server.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> fastify = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fastify'</span>)({ <span class="hljs-attr">logger</span>: <span class="hljs-literal">true</span> });

<span class="hljs-keyword">const</span> start = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> fastify.listen(<span class="hljs-number">5555</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    fastify.log.error(err);
    process.exit(<span class="hljs-number">1</span>);
  }
};

start();
</code></pre>
<p>Once this thing is done, when we run the app using <code>node index</code>, our app will be running on port <code>5555</code>. But let's create the base route (<code>/</code> )for it.</p>
<pre><code class="lang-js">fastify.get(<span class="hljs-string">'/'</span>, <span class="hljs-keyword">async</span> (request, reply) =&gt; {
  reply.send({ <span class="hljs-attr">hello</span>: <span class="hljs-string">'world'</span> });
});
</code></pre>
<h2 id="getting-the-random-meme-using-puppeteer">Getting the random meme using Puppeteer</h2>
<p>Here comes the fun part now! We'll open the web browser and get all the images from memedroid, and we'll do all of it through code. </p>
<p>With the <code>puppeteer</code> package, Chromium also comes installed to scrape the web. That's why it might have taken time for you to get installed</p>
<blockquote>
<p>To skip Chromium download, you can use <a target="_blank" href="http://npmjs.org/package/puppeteer-core"><code>puppeteer-core</code></a> package and add the path to your Chrome file following the docs.</p>
</blockquote>
<p>We'll create a function to <strong>get all memes</strong> and then we'll pick a random one in the route.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getAllMemes</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> URL = <span class="hljs-string">'https://www.memedroid.com/memes/tag/programming'</span>;

  <span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.launch({ <span class="hljs-attr">headless</span>: <span class="hljs-literal">true</span> }); <span class="hljs-comment">// launch browser</span>
  <span class="hljs-keyword">const</span> page = <span class="hljs-keyword">await</span> browser.newPage(); <span class="hljs-comment">// open a page</span>

  <span class="hljs-keyword">await</span> page.goto(URL); <span class="hljs-comment">// go to the page</span>
}
</code></pre>
<p>We simply launch the browser and open the page for memedroid in this code 👆.</p>
<p>Now let's get all the <code>&lt;img&gt;</code> tags which are in the <code>&lt;div&gt;</code> with the class of <code>item-aux-container</code>. That's where all the memes live in.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629208607331/hMu6pVYP6h.png" alt="image.png" /></p>
<p>As in the above image, inside of each <code>&lt;article&gt;</code> tag, the div with that class exists, so we simply get it using the <code>$$eval</code> method on the <code>page</code>.</p>
<p>This method takes two arguments:</p>
<ol>
<li>Selector</li>
<li>Callback function with the element(s)</li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> allImages = <span class="hljs-keyword">await</span> page.$$eval(<span class="hljs-string">'div.item-aux-container img[src]'</span>, <span class="hljs-function">(<span class="hljs-params">imgs</span>) =&gt;</span> {});
</code></pre>
<p>We will map over the images in the callback function, and we'll return only the URL of the image from getting the <code>src</code> attribute. And this is how we do it.</p>
<p>We check if the <code>src</code> attribute starts with <code>http</code> and ends with <code>jpeg</code> and we return that if it does.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> allImages = <span class="hljs-keyword">await</span> page.$$eval(<span class="hljs-string">'div.item-aux-container img[src]'</span>, <span class="hljs-function"><span class="hljs-params">imgs</span> =&gt;</span>
  imgs.map(<span class="hljs-function"><span class="hljs-params">img</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (
      img.getAttribute(<span class="hljs-string">'src'</span>).startsWith(<span class="hljs-string">'http'</span>) &amp;&amp;
      img.getAttribute(<span class="hljs-string">'src'</span>).endsWith(<span class="hljs-string">'jpeg'</span>)
    )
      <span class="hljs-keyword">return</span> img.getAttribute(<span class="hljs-string">'src'</span>);
  })
);
</code></pre>
<p>Unfortunately, that also returns to us <code>null</code> if that's not the case, so we filter out the nulls using the <code>.filter()</code> method.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> imgs = allImages.filter(<span class="hljs-function"><span class="hljs-params">img</span> =&gt;</span> img !== <span class="hljs-literal">null</span>);
</code></pre>
<p>Once all that work is done, we close the browser and return the array of images, this is how the whole function looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getAllMemes</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> URL = <span class="hljs-string">'https://www.memedroid.com/memes/tag/programming'</span>;

  <span class="hljs-keyword">const</span> browser = <span class="hljs-keyword">await</span> puppeteer.launch({ <span class="hljs-attr">headless</span>: <span class="hljs-literal">true</span> });
  <span class="hljs-keyword">const</span> page = <span class="hljs-keyword">await</span> browser.newPage();

  <span class="hljs-keyword">await</span> page.goto(URL);

  <span class="hljs-keyword">const</span> allImages = <span class="hljs-keyword">await</span> page.$$eval(<span class="hljs-string">'div.item-aux-container img[src]'</span>, <span class="hljs-function"><span class="hljs-params">imgs</span> =&gt;</span>
    imgs.map(<span class="hljs-function"><span class="hljs-params">img</span> =&gt;</span> {
      <span class="hljs-keyword">if</span> (
        img.getAttribute(<span class="hljs-string">'src'</span>).startsWith(<span class="hljs-string">'http'</span>) &amp;&amp;
        img.getAttribute(<span class="hljs-string">'src'</span>).endsWith(<span class="hljs-string">'jpeg'</span>)
      )
        <span class="hljs-keyword">return</span> img.getAttribute(<span class="hljs-string">'src'</span>);
    })
  );

  <span class="hljs-keyword">const</span> imgs = allImages.filter(<span class="hljs-function"><span class="hljs-params">img</span> =&gt;</span> img !== <span class="hljs-literal">null</span>);

  <span class="hljs-comment">// NEW LINES</span>
  <span class="hljs-keyword">await</span> browser.close();
  <span class="hljs-keyword">return</span> imgs;
}
</code></pre>
<h2 id="using-fastify-to-send-the-random-meme">Using Fastify to send the random meme</h2>
<p>Finally, we will pick a random meme and send it to the user using this code</p>
<pre><code class="lang-js">fastify.get(<span class="hljs-string">'/'</span>, <span class="hljs-keyword">async</span> (request, reply) =&gt; {
  <span class="hljs-keyword">const</span> memes = <span class="hljs-keyword">await</span> getAllMemes();
  <span class="hljs-keyword">const</span> randomNumber = <span class="hljs-built_in">Math</span>.round(<span class="hljs-built_in">Math</span>.random() * memes.length);
  reply.send({ <span class="hljs-attr">memeUrl</span>: memes[randomNumber] });
});
</code></pre>
<p>Now, whenever the user visits <code>localhost:5555</code>, they get this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629209526927/q3deMvwlE.png" alt="image.png" /></p>
<p><img src="https://media0.giphy.com/media/DRNHiOI54DlW3MBO30/200.gif" alt="done.gif" /></p>
<p>We have our app done! Thanks for reading! You can find all the code  <a target="_blank" href="https://github.com/max-programming/meme-api">here</a>.</p>
<p>I hope you liked it! Comment down your thoughts! There is always room for improvement so let me know your suggestions on this project!</p>
<p><strong>Connect with me on my <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube channel</a> and my  <a target="_blank" href="https://twitter.com/maxprogramming1">Twitter</a> 😉</strong></p>
<p>Until next time, keeping awesome ✌️</p>
]]></content:encoded></item><item><title><![CDATA[✨ How to make a Next.js app a PWA with offline support]]></title><description><![CDATA[Hello everyone 👋
In today's article, we will see how we can make a PWA out of a Next.js app! And it is going to be very exciting as the biggest feature will be offline support with a very little configuration!
📃 INDEX

Project code
next-pwa package...]]></description><link>https://blog.usmans.me/how-to-make-a-nextjs-app-a-pwa-with-offline-support</link><guid isPermaLink="true">https://blog.usmans.me/how-to-make-a-nextjs-app-a-pwa-with-offline-support</guid><category><![CDATA[Next.js]]></category><category><![CDATA[PWA]]></category><category><![CDATA[Service Workers]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Sun, 15 Aug 2021 16:50:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629045972734/ix5-HtXNi.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-hello-everyone">Hello everyone 👋</h2>
<p>In today's article, we will see how we can make a PWA out of a Next.js app! And it is going to be very exciting as the biggest feature will be <strong>offline support</strong> with a very little configuration!</p>
<h2 id="heading-index">📃 INDEX</h2>
<ol>
<li><a class="post-section-overview" href="#1-project-code">Project code</a></li>
<li><a class="post-section-overview" href="#2-next-pwa-package"><code>next-pwa</code> package</a></li>
<li><a class="post-section-overview" href="#3-getting-assets">Getting assets</a></li>
<li><a class="post-section-overview" href="#4-web-manifest-file">Web manifest file</a></li>
<li><a class="post-section-overview" href="#5-pwa-configuration">PWA Configuration</a></li>
<li><a class="post-section-overview" href="#6-offline-fallback-page">Offline fallback page</a></li>
</ol>
<p>Before we move on, I would like to recommend checking my video on YouTube about this if you are comfortable following along with a video. Make sure to leave a comment about any suggestions, or doubts you have 🙂.</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/MHjF166fcxw">https://youtu.be/MHjF166fcxw</a></div>
<p><img src="https://c.tenor.com/HvgCZhfU1zMAAAAM/znarf-lets-go.gif" alt="letsgo" /></p>
<h2 id="heading-1-project-code">1. Project code</h2>
<p>For this demo, I already have a simple project setup that we can use to start or test. </p>
<p>You can download the source or clone the repo:  <a target="_blank" href="https://github.com/max-programming/next-pwa-tut">GitHub Link</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629043215703/d7NnwUciV.png" alt="image.png" /></p>
<blockquote>
<p>This repository has 2 branches, the <code>main</code> one contains the starter code and the <code>pwa</code> branch contains the complete code.</p>
</blockquote>
<h2 id="heading-2-next-pwa-package">2. <code>next-pwa</code> package</h2>
<p>The next step is to install the NPM package we need for this. It's a great package that does everything for you automatically.</p>
<pre><code class="lang-bash">npm i next-pwa
<span class="hljs-comment"># or yarn add next-pwa</span>
</code></pre>
<h2 id="heading-3-getting-assets">3. Getting assets</h2>
<p>If you are familiar with making a PWA, you already know that we need different sizes of logos for our app to function properly on different devices. I found a very good website to generate these images in different sizes. </p>
<p>You can simply go to <a target="_blank" href="https://cthedot.de/icongen/">Icongen</a> and select the types you want. For the sake of this tutorial, I am generating these images. And upload <code>vercel.svg</code> or your existing logo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629043837535/_1ivI-6oU.png" alt="image.png" /></p>
<p>After getting all the images, add them to a new folder named <code>icons</code> in the project's <code>public</code> folder.</p>
<p>Rename all the file names with <code>icon-{size}x{size}.png</code>. For eg, <code>icon-192x192.png</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629044106745/WL7bKR5deB.png" alt="image.png" /></p>
<p>Additionally, add a <code>maskable.png</code> which you can either generate online or for the sake of this tutorial, I used the same <code>192x192</code> sized icon for the maskable icon.</p>
<h2 id="heading-4-web-manifest-file">4. Web manifest file</h2>
<p>Now we need to create a file for the metadata about the app. Create a file named <code>manifest.json</code> in the <code>public</code> folder and copy the contents of the file from <a target="_blank" href="https://easypastes.tk/pastes/manifest.json">here</a>.</p>
<p>You can fill up the contents as per your project, for this project, this is the data we are using</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"short_name"</span>: <span class="hljs-string">"Next PWA"</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Next PWA Tutorial"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">"..."</span>,
  <span class="hljs-attr">"icons"</span>: [
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-36x36.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"36x36"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-48x48.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"48x48"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-72x72.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"72x72"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-96x96.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"96x96"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-144x144.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"144x144"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-192x192.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"192x192"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/icon-512x512.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"512x512"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"/icons/maskable.png"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"192x192"</span>,
      <span class="hljs-attr">"purpose"</span>: <span class="hljs-string">"maskable"</span>
    }
  ],
  <span class="hljs-attr">"start_url"</span>: <span class="hljs-string">"/"</span>,
  <span class="hljs-attr">"background_color"</span>: <span class="hljs-string">"#FFFFFF"</span>,
  <span class="hljs-attr">"display"</span>: <span class="hljs-string">"standalone"</span>,
  <span class="hljs-attr">"scope"</span>: <span class="hljs-string">"/"</span>,
  <span class="hljs-attr">"theme_color"</span>: <span class="hljs-string">"#000000"</span>
}
</code></pre>
<p>Now you need to link the <code>manifest.json</code> file in your Next.js <code>&lt;Head&gt;</code> component in all the pages.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">Head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">'manifest'</span> <span class="hljs-attr">href</span>=<span class="hljs-string">'/manifest.json'</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Head</span>&gt;</span>
</code></pre>
<h2 id="heading-5-pwa-configuration">5. PWA Configuration</h2>
<p>In the first step, we installed the <code>next-pwa</code> NPM package which we will be using now. In your project's root, create a <code>next.config.js</code> or edit if it already exists.</p>
<p>We import the <code>withPWA</code> function from the package and wrap the export in that function, here we can add a <code>pwa</code> object which we will configure like so 👇</p>
<p>The <code>dest</code> property is the destination folder and we added a <code>disable</code> property which disables creating the service workers while we are in development.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> withPWA = <span class="hljs-built_in">require</span>(<span class="hljs-string">'next-pwa'</span>);

<span class="hljs-built_in">module</span>.exports = withPWA({
  <span class="hljs-attr">pwa</span>: {
    <span class="hljs-attr">dest</span>: <span class="hljs-string">'public'</span>,
    <span class="hljs-attr">disable</span>: process.env.NODE_ENV === <span class="hljs-string">'development'</span>,
  },
  <span class="hljs-attr">reactStrictMode</span>: <span class="hljs-literal">true</span>,
});
</code></pre>
<h2 id="heading-6-offline-fallback-page">6. Offline fallback page</h2>
<p>Additionally, we can also add a page to show <strong>if the user is offline</strong>, this enhances the user experience and makes it work like an actual app.</p>
<p>Just add a page named <code>_offline.js</code> in your <code>pages</code> folder, and <code>next-pwa</code> will automatically show that page if the user is offline. But the condition is that the user has to visit the website so that the offline page is cached whenever the user first visits the website.</p>
<p>Here are some examples of offline pages:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629045219320/o_NpKTqqq.png" alt="image.png" /></p>
<blockquote>
<p>👆 <a target="_blank" href="http://easypastes.tk/">Easy Pastes</a></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629045293755/6Za7xppAu.png" alt="image.png" /></p>
<blockquote>
<p>👆 <a target="_blank" href="http://youtube.com/">YouTube</a></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629045327502/AXCT2JuHJ.png" alt="image.png" /></p>
<blockquote>
<p>👆 <a target="_blank" href="https://meet.google.com">Google Meet</a></p>
</blockquote>
<p>A final touch would be to add these files to your <code>.gitignore</code> file to not commit these service worker files created by <code>next-pwa</code></p>
<pre><code class="lang-py"><span class="hljs-comment"># PWA files</span>
**/public/precache.*.*.js
**/public/sw.js
**/public/workbox-*.js
**/public/worker-*.js
**/public/fallback-*.js
**/public/precache.*.*.js.map
**/public/sw.js.map
**/public/workbox-*.js.map
**/public/worker-*.js.map
**/public/fallback-*.js
</code></pre>
<p>And we successfully completed the process, and now your Next.js app can be used offline, is installable as an app, and is also a PWA.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629045944767/fOOLBw6bM.png" alt="image.png" /></p>
<p><img src="https://thumbs.gfycat.com/ImpassionedFrailChimneyswift-size_restricted.gif" alt="success" /></p>
<p><strong>I hope it helped you make your app a PWA, let me know your experience in the comments and share it with people so that they can do it easily too.</strong></p>
]]></content:encoded></item><item><title><![CDATA[💥 Introduction to Jotai | The best React state management library?]]></title><description><![CDATA[Hello friends 👋
What is it and how I found it
So Jotai is a state management library for React, and it is just so easy to work with when compared to Redux, Flux, etc.
I found this interesting package looking at Ashik Chapagain's Hashnode + Clerk hac...]]></description><link>https://blog.usmans.me/introduction-to-jotai-the-best-react-state-management-library</link><guid isPermaLink="true">https://blog.usmans.me/introduction-to-jotai-the-best-react-state-management-library</guid><category><![CDATA[React]]></category><category><![CDATA[npm]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Mon, 02 Aug 2021 04:33:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627877240901/O2gF8rQnr.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-hello-friends">Hello friends 👋</h2>
<h3 id="heading-what-is-it-and-how-i-found-it">What is it and how I found it</h3>
<p>So <a target="_blank" href="https://www.npmjs.com/package/jotai">Jotai</a> is a state management library for React, and it is just so easy to work with when compared to Redux, Flux, etc.</p>
<p>I found this interesting package looking at <a class="user-mention" href="https://hashnode.com/@chapagainashik">Ashik Chapagain</a>'s Hashnode + Clerk hackathon submission. <a target="_blank" href="https://cb-ashik.hashnode.dev/introducing-postlr-multi-platform-blogging-and-scheduling">Read the article</a>.</p>
<p>I saw that he used <a target="_blank" href="https://www.npmjs.com/package/jotai">Jotai</a> for React state management and I had heard about it before that it was very easy to use it.</p>
<p>I finally looked at it and at the first glimpse of the code 🔥. I felt it's the best!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627841592826/1d6t0w1HEq.png" alt="image.png" /></p>
<h3 id="heading-the-problem">The problem</h3>
<p>Managing state in React is hard. Trust me, when you build a large application you will get confused in some way passing props from component to component. This is known as prop drilling which is fine in small apps but in medium and large scale apps, it's hard.</p>
<p>Context API is a way to manage state which I cover in <a target="_blank" href="https://blog.usman-s.me/context-api-in-react">this article</a>. But this library feels the best.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627843005714/Xo1Oi6_GW.png" alt="image.png" /></p>
<blockquote>
<p>Source: https://www.geeksforgeeks.org/what-is-prop-drilling-and-how-to-avoid-it/</p>
</blockquote>
<h3 id="heading-the-code">The code</h3>
<p>So let's now jump to the most exciting part which is how should it be used in our React app! The first step is</p>
<p><img src="https://media.tenor.com/images/fd36f87e59b4ee419761cc905e41256a/tenor.gif" alt="image.png" /></p>
<p>Installing <code>jotai</code> via npm or yarn</p>
<pre><code class="lang-xml">npm i jotai
# or yarn add jotai
</code></pre>
<p>After that is installed, in your React app, you can create an <code>atoms.js</code> file. And simply create and export an <code>atom</code> in that file with a default value. For eg., <code>lengthAtom</code> and <code>breadthAtom</code> are atoms with the value of 4 and 2 respectively.</p>
<p>An <code>atom</code> is simply a holder for our state which we can use then to get access to our state.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">'jotai'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> lengthAtom = atom(<span class="hljs-number">4</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> breadthAtom = atom(<span class="hljs-number">2</span>);
</code></pre>
<p>Then simply import the <code>useAtom</code> hook and the atoms from the file we created and pass those in <code>useAtom</code> in our component. And we get back the same thing we get back from <code>useState</code> which is the best part of this library.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useAtom } <span class="hljs-keyword">from</span> <span class="hljs-string">'jotai'</span>;
<span class="hljs-keyword">import</span> { lengthAtom, breadthAtom } <span class="hljs-keyword">from</span> <span class="hljs-string">'./atoms'</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> [length, setLength] = useAtom(lengthAtom);
  <span class="hljs-keyword">const</span> [breadth, setBreadth] = useAtom(breadthAtom);

  <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">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">'number'</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter length'</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{length}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setLength(parseFloat(e.target.value))}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">'number'</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter breadth'</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{breadth}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setBreadth(parseFloat(e.target.value))}
      /&gt;
    <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>There is also a way to create <strong>computed properties</strong> like in Vue. We create an atom for that as well, and by using the <code>get()</code> method, we get the <strong>value of an atom</strong> and we use the same hook to get the state back.</p>
<p>In this example, I am creating two atoms that depend on the <code>lengthAtom</code> and <code>breadthAtom</code>. When the state changes, the new atoms will change too.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">'jotai'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> lengthAtom = atom(<span class="hljs-number">4</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> breadthAtom = atom(<span class="hljs-number">2</span>);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> perimeterAtom = atom(
  <span class="hljs-function"><span class="hljs-params">get</span> =&gt;</span> <span class="hljs-number">2</span> * (get(lengthAtom) + get(breadthAtom))
);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> areaAtom = atom(<span class="hljs-function"><span class="hljs-params">get</span> =&gt;</span> get(lengthAtom) * get(breadthAtom));
</code></pre>
<p>And then in the component, this is how we use it. We render out whatever the <code>perimeter</code> and the <code>area</code> is depending on the values</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { useAtom } <span class="hljs-keyword">from</span> <span class="hljs-string">'jotai'</span>;
<span class="hljs-keyword">import</span> { countAtom, isCountEvenAtom } <span class="hljs-keyword">from</span> <span class="hljs-string">'./atoms'</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] = useAtom(countAtom);
  <span class="hljs-keyword">const</span> [isCountEven] = useAtom(isCountEvenAtom)

  <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">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">'number'</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter length'</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{length}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setLength(e.target.value)}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">'number'</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">'Enter breadth'</span>
        <span class="hljs-attr">value</span>=<span class="hljs-string">{breadth}</span>
        <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setBreadth(e.target.value)}
      /&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Perimeter of the rectangle is {perimeter} cm<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        Area of the rectangle is {area} cm<span class="hljs-tag">&lt;<span class="hljs-name">sup</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">sup</span>&gt;</span>
      <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>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Here's how it works like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627878667481/eA-Uk0zrf.gif" alt="demo2.gif" /></p>
<p>Read more on <a target="_blank" href="https://www.npmjs.com/package/jotai">their docs</a>, which is fantastic!</p>
<p>Let me know what do you think about <code>jotai</code> as the best state management library for React.</p>
<p>Until then, peace out ✌️</p>
]]></content:encoded></item><item><title><![CDATA[🎉 Introducing Easy Pastes - Easiest way to create and share code pastes]]></title><description><![CDATA[✨ Introduction to the app
Easy Pastes is an app where users can easily paste some code they want to share with someone with syntax highlight and even if they want to make it public, they can do so to show other people.
It is the easiest and fastest w...]]></description><link>https://blog.usmans.me/easypastes</link><guid isPermaLink="true">https://blog.usmans.me/easypastes</guid><category><![CDATA[The Clerk Hackathon on Hashnode]]></category><category><![CDATA[Clerk.dev]]></category><category><![CDATA[hackathon]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[full stack]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Mon, 26 Jul 2021 09:23:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1627290238311/Zje5ihf50.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction-to-the-app">✨ Introduction to the app</h1>
<p>Easy Pastes is an app where users can easily paste some code they want to share with someone <strong>with syntax highlight</strong> and even if they want to make it public, they can do so to show other people.</p>
<p>It is the easiest and fastest way to share code pastes and most of the programming languages are supported. You can request to add a language on the  <a target="_blank" href="https://github.com/max-programming/easypastes">GitHub repository</a>.</p>
<p>This app is fully open-source for learners to learn and to encourage people to contribute to this project to make it better.</p>
<p>The app is live on  <a target="_blank" href="https://easypastes.tk/">easypastes.tk</a> and open sourced on  <a target="_blank" href="https://github.com/max-programming/easypastes">GitHub</a> </p>
<p>Here is how you can use the app</p>
<p><a target="_blank" href="https://cdn.hashnode.com/res/hashnode/image/upload/v1627542797932/0TNW01u9N.gif">Demo GIF</a></p>
<h1 id="heading-the-team">👥 The team</h1>
<p><a class="user-mention" href="https://hashnode.com/@janaSunrise">Sunrit Jana</a> and I have been working on this app for the last fifteen days and it has been a great experience working with him!</p>
<h1 id="heading-how-is-the-app-built">🎨 How is the app built?</h1>
<p>Easy Pastes is using the latest and greatest technologies! The tech stack for the app is</p>
<ul>
<li><a target="_blank" href="https://nextjs.org">Next.js</a> with <a target="_blank" href="https://typescriptlang.org">TypeScript</a></li>
<li><a target="_blank" href="http://chakra-ui.com/">Chakra UI</a> </li>
<li><a target="_blank" href="http://supabase.io/">Supabase</a> </li>
<li><a target="_blank" href="https://clerk.dev/">Clerk</a> </li>
</ul>
<p>We are using Next.js for the whole app, Chakra UI for the user interface, Supabase for the database, and <a class="user-mention" href="https://hashnode.com/@clerk">Clerk.dev</a> for authentication.</p>
<h1 id="heading-exploring-the-app">🧐 Exploring the app</h1>
<p>We'll be going into detail on how to use this app in this section. On the main page, you will be having the functionality to create a paste. </p>
<h2 id="heading-sign-in-and-sign-up">Sign in and sign up</h2>
<p>The authentication system is powered by <a target="_blank" href="https://clerk.dev">Clerk.dev</a> which is awesome!</p>
<p>Before creating a paste, it's recommended to sign in because your pastes are stored for future use. And you can edit and delete <strong>your pastes</strong> while you are signed in. When you create a paste while signed in, it will be <strong>your paste</strong>. You can go to the <strong>My Pastes</strong> page to see what pastes you have created.</p>
<p>And Easy Pastes also has <strong>multi-account system</strong> so you can sign in with multiple accounts.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627441520326/g0Q2wbzlB.png" alt="image.png" /></p>
<blockquote>
<p>ℹ️ Public pastes are shown on the home page.
Private pastes are private and no one can view them except the author
Unlisted pastes can be viewed by anyone from the link but are not shown on the home page</p>
</blockquote>
<h3 id="heading-pick-a-language-of-your-choice-default-none">Pick a language of your choice (default: none)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627288538569/f5W_L69Lz.png" alt="image.png" /></p>
<h3 id="heading-give-paste-a-title-optional">Give paste a title (optional)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627288580340/mxqa0sED3.png" alt="image.png" /></p>
<h3 id="heading-change-visibility-and-give-a-custom-url-optional">Change visibility and give a custom URL (optional)</h3>
<blockquote>
<p>ℹ️ Making a custom URL and making paste private is only available when you are signed in.</p>
</blockquote>
<p>If the custom URL is not specified, it'll be a randomly generated id, and the pastes are public by default.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627288607758/4Ju0O4j4d.png" alt="image.png" /></p>
<h3 id="heading-paste-the-code-and-click-the-create-button">Paste the code and click the create button</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627288829506/m2t3NWbqS.png" alt="image.png" /></p>
<h3 id="heading-share-copy-edit-or-delete-the-paste">Share, copy, edit, or delete the paste</h3>
<p>You will be redirected to your created paste which you can then share the link to someone, copy the code, delete and edit the paste.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627544598199/8PDX0Fvao.png" alt="image.png" /></p>
<h2 id="heading-pwa-new">🧱 PWA (new)</h2>
<p>With the latest update, Easy Pastes is also a PWA and it can be installed and used as an app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627469533468/t2oxIaORT.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627467543090/3Qp2GshUc.png" alt="image.png" /></p>
<p>As a PWA, it also has shortcuts to directly open the My Pastes page</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628055406241/5PAEdAGcv.png" alt="image.png" /></p>
<h2 id="heading-password-protection-new">🔑🔒 Password protection (new)</h2>
<p>We're also now focused on security. We have added a feature consisting of protecting your pastes and storing the secure password hash in DB. No one other than you, or people can access it! This is one of the features we're really proud of!</p>
<p>Set a password using this button</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627585106453/tERlpYXg6.png" alt="image.png" /></p>
<p>And then visit the page where you would need to enter the password to view it</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627585196617/p-fFsybXg.png" alt="image.png" /></p>
<h1 id="heading-your-profile">👽️ Your profile</h1>
<p>You can change your account settings by clicking your account button on the top right and settings. But in this case, you also get the functionality to view your own pastes.</p>
<p>When you click on the <strong>My Pastes</strong> link in the navbar, you will see your own pastes.</p>
<blockquote>
<p>You can achieve this behaviour by simply setting the username in user settings else it will be the user id.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627289226110/q-LVjEsRi.png" alt="image.png" /></p>
</blockquote>
<p>On this page, you are able to view pastes you have created and you can even filter them by All, Public, Unlisted, and Private.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627289409250/qfRigANF7.png" alt="image.png" /></p>
<p>If the page is viewed by someone else, they will only be able to see the public pastes you have created.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1627289496084/wwsWKc1A4x.png" alt="image.png" /></p>
<h1 id="heading-conclusion">💫 Conclusion</h1>
<p>And that is how Easy Pastes works! Thanks to Hashnode for organizing this hackathon. It helped me so much to build my first full-stack web application.</p>
<p>I want to thank the folks over at Discord and Twitter who helped me to improve this app by giving their valuable feedbacks.</p>
<p>The Clerk team on Discord was very helpful to us. They were very helpful whenever we had any queries regarding Clerk.</p>
<ul>
<li><a class="user-mention" href="https://hashnode.com/@atapas">Tapas Adhikary</a></li>
<li><a class="user-mention" href="https://hashnode.com/@saviomartin">Savio Martin</a></li>
<li><a class="user-mention" href="https://hashnode.com/@avneesh0612">Avneesh Agarwal</a></li>
<li><a class="user-mention" href="https://hashnode.com/@mbosnjak">Matej Bošnjak</a></li>
<li><a class="user-mention" href="https://hashnode.com/@ishrarg">Ishrar G</a></li>
</ul>
<p>Sorry if I missed someone :)</p>
<p>Feel free to contribute to the project on the GitHub repository and give your suggestions and how the app works in the comments.</p>


<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://easypastes.tk">https://easypastes.tk</a></div>
<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/max-programming/easypastes">https://github.com/max-programming/easypastes</a></div>
<h2 id="heading-updates">📈 Updates</h2>
<h3 id="heading-27-07-2021">27-07-2021:</h3>
<ul>
<li>With <a target="_blank" href="https://github.com/max-programming/easypastes/commit/ecc885663f9ef8db779e996df57996f660200afa">this commit</a> , swears and bad words are filtered from the Title and Custom URL</li>
</ul>
<h3 id="heading-28-07-2021">28-07-2021</h3>
<ul>
<li>Made Easy Pastes a PWA</li>
<li>Custom  <a target="_blank" href="https://easypastes.tk/404">404 page</a> </li>
</ul>
<h3 id="heading-29-07-2021">29-07-2021</h3>
<ul>
<li>We're here with another amazing update! Added password protection</li>
<li>Fixed the heading and footers.</li>
</ul>
<h3 id="heading-02-08-2021">02-08-2021</h3>
<ul>
<li>Viewing paste in raw mode feature</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[💫 How to add routing loader using nprogress in Next.js?]]></title><description><![CDATA[Hey everyone 👋!
So Next.js has been very popular nowadays and I am completely switching from the good old React to the Next.js because it's of course better.
With the awesome routing system in Next.js, there are a ton of advantages like events and a...]]></description><link>https://blog.usmans.me/how-to-add-routing-loader-using-nprogress-in-nextjs</link><guid isPermaLink="true">https://blog.usmans.me/how-to-add-routing-loader-using-nprogress-in-nextjs</guid><category><![CDATA[Next.js]]></category><category><![CDATA[UX]]></category><category><![CDATA[user experience]]></category><category><![CDATA[routing]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Thu, 01 Jul 2021 11:37:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1625221932414/rjbSj_res.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="hey-everyone">Hey everyone 👋!</h1>
<p>So Next.js has been very popular nowadays and I am completely switching from the good old React to the Next.js because it's of course better.</p>
<p>With the awesome routing system in Next.js, there are a ton of advantages like events and all that which are very useful when you dig into them.</p>
<p>Today, using the router in Next.js, I'll show you how you can create a page loader that shows a progress bar while we are navigating to a different page. It'll enhance the user experience on your site.</p>
<p>And the process is absolutely simple. <code>Just a few lines of code</code> as always. We'll use an NPM package called <a target="_blank" href="https://npmjs.org/package/nprogress"><code>nprogress</code></a> </p>
<h1 id="result">✨ Result</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625138486943/aWmwyJ3pJ.gif" alt="Animation.gif" /></p>
<h1 id="1-create-a-nextjs-app">1. Create a Next.js app</h1>
<pre><code class="lang-sh">npx create-next-app nprogress-demo
</code></pre>
<h1 id="2-install-nprogress">2. Install <code>nprogress</code></h1>
<p>You can use <code>npm</code>, <code>yarn</code> or <code>pnpm</code> to do this, just install <code>nprogress</code></p>
<pre><code><span class="hljs-built_in">npm</span> i nprogress

<span class="hljs-comment"># If you're using TypeScript, install this too</span>
<span class="hljs-built_in">npm</span> i -D @types/nprogress
</code></pre><h1 id="3-get-the-nprogresscss-file">3. Get the <code>nprogress.css</code> file</h1>
<p>The <code>nprogress</code> package ships with a CSS file which it needs but you have to import it in the <code>_app.js</code> file, so you can create a <code>nprogress.css</code> file in your <code>styles</code> folder and copy and paste styles from  <a target="_blank" href="https://unpkg.com/nprogress@0.2.0/nprogress.css">this CDN</a> </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625136362244/0imrShmVe.png" alt="image.png" /></p>
<p>After saving the file, you can edit anything you want in that one, I made some changes which fit my needs are as follows: </p>
<p>I changed every background colour from <code>#29d</code> to <code>#0070f3</code> and you can change it to any other colour you want</p>
<pre><code class="lang-css"><span class="hljs-comment">/* I made these changes in nprogress.css */</span>
<span class="hljs-selector-id">#nprogress</span> <span class="hljs-selector-class">.bar</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">3px</span>;
}
<span class="hljs-selector-id">#nprogress</span> <span class="hljs-selector-class">.spinner-icon</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">25px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">25px</span>;
  <span class="hljs-attribute">border</span>: solid <span class="hljs-number">3px</span> transparent;
}
</code></pre>
<p>And finally, you can import the CSS file in the <code>_app.js</code> file</p>
<pre><code class="lang-js"><span class="hljs-comment">// _app.js</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"../styles/nprogress.css"</span>;
</code></pre>
<h1 id="4-add-a-new-page-for-the-demo">4. Add a new page (for the demo)</h1>
<p>I simply created a <code>second.js</code> file in the <code>pages</code> folder with these contents. It uses <code>getServerSideProps</code> where we fetch some data on request of the page, <em>so that we get a slight delay while navigating</em></p>
<pre><code class="lang-jsx"><span class="hljs-comment">// second.js</span>
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"next/head"</span>;
<span class="hljs-keyword">import</span> Image <span class="hljs-keyword">from</span> <span class="hljs-string">"next/image"</span>;
<span class="hljs-keyword">import</span> Link <span class="hljs-keyword">from</span> <span class="hljs-string">"next/link"</span>;
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"../styles/Home.module.css"</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">SecondPage</span>(<span class="hljs-params">{ data }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</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">title</span>&gt;</span>Second page<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.ico"</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">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.main}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.title}</span>&gt;</span>Second page<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.description}</span>&gt;</span>
          This is the second page. Go to{" "}
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.grid}</span>&gt;</span>
          {data.map(user =&gt; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.card}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{user.id}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{user.name} <span class="hljs-symbol">&amp;rarr;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Works in {user.company.name}<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">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">main</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">const</span> getServerSideProps = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://jsonplaceholder.typicode.com/users"</span>);
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">props</span>: {
      <span class="hljs-attr">data</span>: data.slice(<span class="hljs-number">0</span>, <span class="hljs-number">4</span>),
    },
  };
};
</code></pre>
<h1 id="5-use-router-events-to-show-the-progress-bar">5. Use <code>Router</code> events to show the progress bar</h1>
<p>To show the progress bar, we use the Next.js <code>Router</code>'s events. You can do all the logic inside the <code>_app.js</code> file.</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// _app.js</span>
<span class="hljs-keyword">import</span> Router <span class="hljs-keyword">from</span> <span class="hljs-string">"next/router"</span>;
<span class="hljs-keyword">import</span> nProgress <span class="hljs-keyword">from</span> <span class="hljs-string">"nprogress"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"../styles/globals.css"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"../styles/nprogress.css"</span>;

Router.events.on(<span class="hljs-string">"routeChangeStart"</span>, nProgress.start);
Router.events.on(<span class="hljs-string">"routeChangeError"</span>, nProgress.done);
Router.events.on(<span class="hljs-string">"routeChangeComplete"</span>, nProgress.done);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyApp</span>(<span class="hljs-params">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyApp;
</code></pre>
<p>When the <code>routeChangeStart</code> event fires, we start the progress bar by using <code>nProgress.start</code> function.</p>
<blockquote>
<p>Don't invoke the function like <code>nProgress.start()</code>, pass it without the parenthesis because there should be a callback function in the events.</p>
</blockquote>
<p>And when the other two events <code>routeChangeError</code>, <code>routeChangeComplete</code> occur, we simply pass in <code>nProgress.done</code> which completes the progress bar.</p>
<h1 id="and-thats-it">And that's it 🥳 !</h1>
<p>In these 5 simple steps, we managed to add a progress bar while navigating to different pages in Next.js. Let me know all your questions in the comments and share this knowledge to others to help them.</p>
<p>Finally, you can check me out on  <a target="_blank" href="https://youtube.com/MaxProgramming">YouTube</a>,  <a target="_blank" href="https://twitter.com/MaxProgramming1">Twitter</a>, etc. Thanks for reading!  </p>
]]></content:encoded></item><item><title><![CDATA[🐛 How to quickly spot errors in your JavaScript code in VS Code]]></title><description><![CDATA[Hello again 👋
This is a very amazing way to use the powers of Visual Studio Code in your JavaScript files to quickly spot errors.

You might know about  TypeScript . It's a wonderful superset of JavaScript which gives JS the power of types and helps...]]></description><link>https://blog.usmans.me/how-to-quickly-spot-errors-in-your-javascript-code-in-vs-code</link><guid isPermaLink="true">https://blog.usmans.me/how-to-quickly-spot-errors-in-your-javascript-code-in-vs-code</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Bugs and Errors]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Wed, 14 Apr 2021 12:43:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618404188804/JCkGJFKhD.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="hello-again">Hello again 👋</h1>
<h3 id="this-is-a-very-amazing-way-to-use-the-powers-of-visual-studio-code-in-your-javascript-files-to-quickly-spot-errors">This is a very amazing way to use the powers of Visual Studio Code in your JavaScript files to quickly spot errors.</h3>
<blockquote>
<p>You might know about  <a target="_blank" href="http://typescriptlang.org/">TypeScript</a> . It's a wonderful superset of JavaScript which gives JS the power of types and helps in debugging right inside your IDE (especially VS Code). This simple trick will even help you if you are not a fan of types and TypeScript.</p>
</blockquote>
<p>Most of the times, there are very small and silly bugs in our JavaScript code which we can't catch in the development process and can cause high impact in production. A simple example is this 👇</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618394258949/UibX9tbeK.png" alt="image.png" /></p>
<p>In this example above, we are using Vanilla JavaScript where we cannot spot the error which is on <strong>line 7</strong>. We could've used TypeScript here, but if you want to use JavaScript, you can easily spot errors by adding only a comment on the top.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618394650705/msRXzwE2I.png" alt="image.png" /></p>
<p>As you can see the warning we got by hovering over the parameter in the function is telling us that this parameter is of <code>any</code> type which is not good at all. So how can you expect only a <code>string</code> into the function without TypeScript? </p>
<p>The easiest way to do it is to add the <code>string</code> argument in the function call and then do this 👇.</p>
<blockquote>
<p>Arrow function</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395013649/cJocHis3K.gif" alt="jsdoc 1.gif" /></p>
<blockquote>
<p>Normal function</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395128939/0knhLk7ng.gif" alt="jsdoc 2.gif" /></p>
<p>The 2nd way looks neater to me. </p>
<p>Besides, you can also spot silly bugs which are very bad. Some are listed below:</p>
<blockquote>
<p>Without <code>// @ts-check</code></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395257971/zMKf3in7s.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395313031/OHcfyK8JV.png" alt="image.png" /></p>
<blockquote>
<p>With <code>// @ts-check</code></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395398986/xhpZv5Z-r.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395411067/EkfjfMpau.png" alt="image.png" /></p>
<blockquote>
<p>TIP: To enable <code>// @ts-check</code> for every <code>.js</code> file, you can simply enable this setting in VS Code.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618395578363/8QriPysit.png" alt="image.png" /></p>
</blockquote>
<p>And to ignore checking in any file, just use <code>// @ts-nocheck</code> on the top of the file.</p>
<p>For more information about those types for parameters, you can refer to the  <a target="_blank" href="https://jsdoc.app/">JSDoc Documentation</a>.</p>
]]></content:encoded></item><item><title><![CDATA[🎨 How to create Twitter Profile Hover Card using HTML and CSS]]></title><description><![CDATA[Welcome back developers! 👋
In this post, we'll see how you can recreate the hover card by Twitter using HTML and CSS, so let's get started.
This hover card will appear when you hover over any profile. But in our case, we will just make the over card...]]></description><link>https://blog.usmans.me/how-to-create-twitter-profile-hover-card-using-html-and-css</link><guid isPermaLink="true">https://blog.usmans.me/how-to-create-twitter-profile-hover-card-using-html-and-css</guid><category><![CDATA[HTML5]]></category><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[Twitter]]></category><category><![CDATA[Design]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Fri, 29 Jan 2021 07:40:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1611905993702/akVYADg6g.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="welcome-back-developers">Welcome back developers! 👋</h2>
<p>In this post, we'll see how you can recreate the hover card by Twitter using HTML and CSS, so let's get started.</p>
<p>This hover card will appear when you hover over any profile. But in our case, we will just make the over card.</p>
<p>I also have a video on YouTube on this which you might want to check out too.</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/uRd4YXSZ0_M">https://youtu.be/uRd4YXSZ0_M</a></div>
<p>This is how it will look like in the end.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611901969675/tuMaafCgh.png" alt="image.png" /></p>
<h2 id="html">🧱 HTML</h2>
<p>The HTML is very self explanatory and very easy. We create wrappers around and then we create three <code>&lt;div&gt;</code> tags which will contain the content.</p>
<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">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">title</span>&gt;</span>Twitter Hovercard<span class="hljs-tag">&lt;/<span class="hljs-name">title</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">"./styles.css"</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">"container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"profile"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-profile"</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">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"user-bio"</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">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"user-follows"</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">div</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">div</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>
<h3 id="1-main-profile-div">1. <code>main-profile</code> div</h3>
<p>The <code>main-profile</code> div will basically contain the <strong>Profile Picture</strong>, <strong>Name</strong>, <strong>Handle</strong> and the <strong>Follow button</strong>. Which will be in the first row. We will then use flexbox to style it.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-profile"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"user-info"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./profile.jpg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Profile Pic"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Max Programming<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>@MaxProgramming1<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">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"follow-btn"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Follow<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">div</span>&gt;</span>
</code></pre>
<h3 id="2-user-bio-div">2. <code>user-bio</code> div</h3>
<p>This div will contain the bio of the user, in this case my bio. You can separate it into different lines using the <code>&lt;br /&gt;</code> tag.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"user-bio"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
    👨‍💻 Programmer, Learner, YTuber, Blogger, and Cricket lover!
    <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
    😊 15 years old
    <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
    My name is Usman
    <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
    ☪ Muslim
    <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
    Blog: <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"http://blog.usman-s.me"</span>&gt;</span>blog.usman-s.me<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
    YT:
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"http://youtube.com/MaxProgramming"</span>&gt;</span>youtube.com/MaxProgramming<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <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>
</code></pre>
<h3 id="3-user-follows-div">3. <code>user-follows</code> div</h3>
<p>This is the simplest one of all. You just create two <code>&lt;div&gt;</code> tags inside it with <strong>Following</strong> and <strong>Followers</strong> and their numbers. </p>
<p>We use the <code>&lt;b&gt;</code> tags to bolden out the numbers.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"user-follows"</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">b</span>&gt;</span>613<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span> Following<span class="hljs-tag">&lt;/<span class="hljs-name">div</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">b</span>&gt;</span>471<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span> Followers<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>This is what we get after this table is done. Let's now style it out with the magic of CSS.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611902917920/qo83juShP.png" alt="image.png" /></p>
<h2 id="css">🎨 CSS</h2>
<h3 id="1-resets">1. Resets</h3>
<p>At the start, we set the margin and padding to 0, and set the <code>box-sizing</code> to <code>border-box</code>.
And then we set the font for every element to be <code>sans-serif</code> according to the system.</p>
<p>We style the <code>container</code> to center everything on the page</p>
<pre><code class="lang-css">* {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
  <span class="hljs-attribute">font-family</span>: -apple-system, BlinkMacSystemFont, <span class="hljs-string">"Segoe UI"</span>, Roboto, Oxygen,
    Ubuntu, Cantarell, <span class="hljs-string">"Open Sans"</span>, <span class="hljs-string">"Helvetica Neue"</span>, sans-serif;
}

<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611903221705/9bJKrNPbH.png" alt="image.png" /></p>
<hr />
<h3 id="2-the-card">2. The Card</h3>
<p>Now to style the <code>card</code> div, we and add shadow, border radius and padding to it. </p>
<pre><code class="lang-css"><span class="hljs-selector-class">.card</span> {
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">1px</span> <span class="hljs-number">1px</span> <span class="hljs-number">10px</span> <span class="hljs-number">1px</span> <span class="hljs-number">#a1a1a1</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611903416325/0bSu-RwZQ.png" alt="image.png" /></p>
<hr />
<h3 id="3-main-profile">3. Main Profile</h3>
<p>Now as the <code>main-profile</code> contains the main details, we'll position it better using Flexbox.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.main-profile</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-between;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">20px</span>;
}
</code></pre>
<p>And then we will add some stylings to make the profile picture smaller, increase the size for the name, and change the color of the handle.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.user-info</span> <span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
}

<span class="hljs-selector-class">.user-info</span> <span class="hljs-selector-tag">h3</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.3rem</span>;
}

<span class="hljs-selector-class">.user-info</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#5b7083</span>;
}
</code></pre>
<p>This is the progress so far</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611903655250/lu7k43xYg.png" alt="image.png" /></p>
<p>Let's style the <strong>Follow</strong> button now.</p>
<p>Here, we set the <code>border</code> and the text to the twitter blue color, the <code>background</code> is set to the same color but transparent. We make the text <code>bold</code>, and add a hover effect with a <code>transition</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.follow-btn</span> <span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.5rem</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">3px</span> solid <span class="hljs-number">#1da1f2</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">25px</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">29</span>, <span class="hljs-number">161</span>, <span class="hljs-number">242</span>, <span class="hljs-number">0</span>);
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">8px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#1da1f2</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
  <span class="hljs-attribute">outline</span>: none;
  <span class="hljs-attribute">transition</span>: all <span class="hljs-number">0.2s</span> ease-in-out;
}

<span class="hljs-selector-class">.follow-btn</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">29</span>, <span class="hljs-number">161</span>, <span class="hljs-number">242</span>, <span class="hljs-number">0.2</span>);
}
</code></pre>
<p>Now we got the <em>perfect</em> button with the hover effect as well. Which change the background color's opacity.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611904039024/kTH9_5Z18.png" alt="image.png" /></p>
<hr />
<h3 id="4-user-bio">4. User bio</h3>
<p>The bio is fairly easy. We just change the color of the text, add some margin and change the color of the <code>&lt;a&gt;</code> tags like the styles of Twitter.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.user-bio</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#0f1419</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.user-bio</span> <span class="hljs-selector-tag">a</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#1da1f2</span>;
  <span class="hljs-attribute">text-decoration</span>: none;
}

<span class="hljs-selector-class">.user-bio</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">text-decoration</span>: underline;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1611904250550/Y0cucAkw0.png" alt="image.png" /></p>
<hr />
<h3 id="5-user-follows">5. User Follows</h3>
<p>This is the easiest part. We use flexbox, we add some margins to the <code>&lt;div&gt;</code>. And we change the color of the text.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.user-follows</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#5b7083</span>;
}

<span class="hljs-selector-class">.user-follows</span> <span class="hljs-selector-tag">div</span> {
  <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.user-follows</span> <span class="hljs-selector-tag">b</span> {
  <span class="hljs-attribute">color</span>: black;
}
</code></pre>
<p>And that is how you recreate Twitter's hover card using HTML and CSS. I hope you like this blog post. If you do, please leave a like comment down below about your experience.</p>
<p>Here's the source code.</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/max-programming/twitter-hovercard">https://github.com/max-programming/twitter-hovercard</a></div>
<p>Thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[✨ How to make your React app a PWA with Create React App 4]]></title><description><![CDATA[Welcome back developers 👋.
Create React App or react-scripts is a great tool to scaffold out our React Apps. And one of the best parts of it was that we got a readymade serviceWorker.js file with it which would help us make the React app offline so ...]]></description><link>https://blog.usmans.me/how-to-make-your-react-app-a-pwa-with-create-react-app-4</link><guid isPermaLink="true">https://blog.usmans.me/how-to-make-your-react-app-a-pwa-with-create-react-app-4</guid><category><![CDATA[React]]></category><category><![CDATA[PWA]]></category><category><![CDATA[Service Workers]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Usman Sabuwala]]></dc:creator><pubDate>Fri, 25 Dec 2020 04:44:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1608871466811/e5_5zDD81.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="welcome-back-developers">Welcome back developers 👋.</h2>
<p>Create React App or <code>react-scripts</code> is a great tool to scaffold out our React Apps. And one of the best parts of it was that we got a readymade <code>serviceWorker.js</code> file with it which would help us make the React app offline so easily.</p>
<p>But with the <code>react-scripts</code> version 4, whenever we use the command <code>npx create-react-app app-name</code>, we don't get the service worker file. </p>
<p>But no worries, we can easily generate a React App with the service worker file again, but we have to use a template. So instead of just running <code>create-react-app</code>, we should add a flag to it and this is how the new command looks like</p>
<h3 id="creating-a-new-app">Creating a new app</h3>
<pre><code class="lang-sh"><span class="hljs-comment"># JavaScript</span>
npx create-react-app app-name --template cra-template-pwa

<span class="hljs-comment"># TypeScript</span>
npx create-react-app app-name --template cra-template-pwa-typescript
</code></pre>
<p>And that will generate two service worker files, one of them will be for the registration, and the other one the service worker itself.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608870407516/txmAzwTVQ.png" alt="image.png" /></p>
<p>In the <code>index.js</code> file, you'll get the import and the <code>.unregister()</code> method as before</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608870545324/U33bSJkjz.png" alt="image.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608870552189/1EoRJ7qx_5.png" alt="image.png" /></p>
<p>You can simply change the <code>.unregister()</code> to <code>.register()</code> to register the service worker and now, when the app is built, it'll be capable to run offline. You'll see a button on the right side of your address bar if you are using Chrome or Edge or any other Chromium based browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608870691567/rWKeKE-XI.png" alt="image.png" /></p>
<p>On installing, it'll cache your app and it'll be able to run, even if you are online.</p>
<h3 id="converting-an-existing-app">Converting an existing app</h3>
<p>To convert an existing app, you can simply copy the code, create the required files and paste it from  <a target="_blank" href="https://gist.github.com/max-programming/3c2eb5647eec0f074f6fcc9cdecbc288">a gist</a> that I created.</p>
<p>Also consider checking out the video on this topic if you want.</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/Iur-3V2W3P4">https://youtu.be/Iur-3V2W3P4</a></div>
<p>I hope this post helped you, make sure to 💙 like it and share it to others.</p>
<p>💬 Let me know your React apps which are PWAs in the comments.</p>
<p>Thanks for reading! ✌</p>
]]></content:encoded></item></channel></rss>