<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kumar Abhirup</title>
    <description>The latest articles on DEV Community by Kumar Abhirup (@kumareth).</description>
    <link>https://dev.to/kumareth</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F139411%2F772f34cf-4790-44b6-bb06-a3d0dcdf90f0.jpg</url>
      <title>DEV Community: Kumar Abhirup</title>
      <link>https://dev.to/kumareth</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kumareth"/>
    <language>en</language>
    <item>
      <title>Implementing Google reCAPTCHA with React and Node.js</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Tue, 02 Jun 2020 11:00:25 +0000</pubDate>
      <link>https://dev.to/kumareth/implementing-google-recaptcha-with-react-and-node-js-1jgf</link>
      <guid>https://dev.to/kumareth/implementing-google-recaptcha-with-react-and-node-js-1jgf</guid>
      <description>&lt;p&gt;In this tutorial, we will learn how to use reCAPTCHA v2 with React and Node.&lt;/p&gt;

&lt;p&gt;Most of the tutorials online only cover the frontend part of this technology. The truth is, &lt;strong&gt;your captcha solution can only be useful, if it validates the input on backend.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's begin with how you can show the captcha checkbox on React Frontend by first setting up the Google reCAPTCHA console.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup Google reCAPTCHA Admin
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;a href="https://www.google.com/recaptcha/admin/create" rel="noopener noreferrer"&gt;this URL&lt;/a&gt; to create a reCAPTCHA app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give the reCAPTCHA a label.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;code&gt;reCAPTCHA v2&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the domain name of where this captcha checkbox will be used. To test this checkbox on your development server, add &lt;code&gt;localhost&lt;/code&gt; as your domain name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Submit.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you have created the app, you can get your reCAPTCHA keys.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that these keys are extremely important. The &lt;code&gt;SITE KEY&lt;/code&gt; can be used in the client, but the &lt;code&gt;SECRET KEY&lt;/code&gt; should be never used in the client. It should only be used in the backend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F7WFsKWr%2FSite-Key-Secret-Key-Google-re-CAPTCHA-Screenshot.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F7WFsKWr%2FSite-Key-Secret-Key-Google-re-CAPTCHA-Screenshot.jpg" alt="Get your Google reCAPTCHA Credentials"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Setup React Frontend
&lt;/h1&gt;

&lt;p&gt;Install the &lt;code&gt;react-google-recaptcha&lt;/code&gt; React Component. It will simplify this terrific process.&lt;/p&gt;

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

yarn add react-google-recaptcha


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

&lt;/div&gt;

&lt;p&gt;After you install the component, here's how you can display the reCAPTCHA checkbox on the frontend.&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReCAPTCHA&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-google-recaptcha&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Captcha value:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReCAPTCHA&lt;/span&gt; &lt;span class="na"&gt;sitekey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_CLIENT_SITE_KEY"&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Make sure you replace &lt;code&gt;YOUR_CLIENT_SITE_KEY&lt;/code&gt; with the real client site key that you got from the Google reCAPTCHA Console.&lt;/p&gt;

&lt;p&gt;With the correct usage of the above code, you should see something like this in the browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.cmnty.com%2Fsupport%2Fwp-content%2Fuploads%2F2017%2F07%2Fnocaptcha.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.cmnty.com%2Fsupport%2Fwp-content%2Fuploads%2F2017%2F07%2Fnocaptcha.gif" alt="Google reCAPTCHA GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if you check your console, you will see the &lt;code&gt;Captcha value: some_value&lt;/code&gt; logged on the console. That same value, will be sent to the backend to verify if the user is really not a robot.&lt;/p&gt;




&lt;h1&gt;
  
  
  Backend Verification
&lt;/h1&gt;

&lt;p&gt;To verify the value that the backend gets, after the user checks the box, you will have to make a POST request to Google reCAPTCHA API.&lt;/p&gt;

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

POST https://www.google.com/recaptcha/api/siteverify


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

&lt;/div&gt;

&lt;p&gt;Here's how you do it in Node.js 👇&lt;/p&gt;

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

&lt;span class="c1"&gt;// Install 'es6-promise' and 'isomorphic-fetch' from NPM or Yarn.&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;es6-promise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;polyfill&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isomorphic-fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RECAPTCHA_SERVER_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_SERVER_KEY&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;humanKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value_that_we_got_from_the_frontend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Validate Human&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isHuman&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://www.google.com/recaptcha/api/siteverify`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/x-www-form-urlencoded; charset=utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`secret=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_SERVER_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;response=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;humanKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Error in Google Siteverify API. &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;humanKey&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isHuman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`YOU ARE NOT A HUMAN.`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The code below will run only after the reCAPTCHA is succesfully validated.&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SUCCESS!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article does not tell you how to communicate between frontend and backend, this article only tells you what logic to use in backend, to verify the reCAPTCHA string value you get from the frontend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand the above code, we first need to understand what &lt;code&gt;fetch()&lt;/code&gt; function results.&lt;/p&gt;

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

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://www.google.com/recaptcha/api/siteverify`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/x-www-form-urlencoded; charset=utf-8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`secret=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;RECAPTCHA_SERVER_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;response=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;humanKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The above snippet makes a POST request to the Google reCAPTCHA API route to get a response (to know if the humanKey we got from the frontend is correct or not).&lt;/p&gt;

&lt;p&gt;We also supply &lt;code&gt;RECAPTCHA_SERVER_KEY&lt;/code&gt; and the &lt;code&gt;humanKey&lt;/code&gt; in the request body. Remember that the &lt;code&gt;RECAPTCHA_SERVER_KEY&lt;/code&gt; should be kept secret. Do not push it in GitHub Open Source. &lt;a href="https://www.freecodecamp.org/news/heres-how-you-can-actually-use-node-environment-variables-8fdf98f53a0a/#:~:text=env%20files%20allow%20you%20to,in%20there%20on%20different%20lines.&amp;amp;text=To%20read%20these%20values%2C%20there,the%20dotenv%20package%20from%20npm." rel="noopener noreferrer"&gt;Use Environment Variables&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's a Sample Response that the API gives us.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"challenge_ts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISODateString"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;challenge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(ISO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;yyyy-MM-dd'T'HH:mm:ssZZ)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;hostname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;site&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;where&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;reCAPTCHA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;solved&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;success: true&lt;/code&gt; is enough for us to understand that the user is not a robot. If &lt;code&gt;success: false&lt;/code&gt;, then the &lt;code&gt;humanKey&lt;/code&gt; we got was probably a wrong one or the user tried to hack in.&lt;/p&gt;




&lt;h1&gt;
  
  
  Aftermath
&lt;/h1&gt;

&lt;p&gt;Once you get &lt;code&gt;success: true&lt;/code&gt;, you would probably want to send your frontend a response that the reCAPTCHA was not botched and the user was not a robot.&lt;/p&gt;

&lt;p&gt;You must be using some kind of an Express/Koa API Route, or a GraphQL backend where you can get API requests from the frontend to give it some response.&lt;/p&gt;

&lt;p&gt;If you want to see it in practise, I have hosted my code here 🔥&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/KumarAbhirup/kumarabhirup/blob/0f883462652afc521d4938e1f06f0128f233e29f/src/components/mobirise/Contact.js#L270" rel="noopener noreferrer"&gt;Frontend reCAPTCHA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/KumarAbhirup/kumarabhirup-backend/blob/d0b9daa97e724c428ebdf3728f475d35ee7370de/src/resolvers/Mutation.js#L44" rel="noopener noreferrer"&gt;Backend reCAPTCHA Validation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this tutorial gave you decent information on how you can validate your reCAPTCHA input on backend using Node.js and React.&lt;/p&gt;

&lt;p&gt;Peace ✌️&lt;/p&gt;




&lt;h1&gt;
  
  
  🏆 About me
&lt;/h1&gt;

&lt;p&gt;I am &lt;strong&gt;Kumar Abhirup, a 16-year-old JavaScript React developer&lt;/strong&gt; from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/kumar_abhirup" rel="noopener noreferrer"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Love what I write? &lt;a href="https://kumarabhirup.me/subscribe" rel="noopener noreferrer"&gt;Subscribe to &lt;strong&gt;Kumar&amp;amp;Thoughts&lt;/strong&gt;&lt;/a&gt; and stay updated about the tech community, me and coding in general.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>A beginner's guide for setting up autocomplete on OhMyZsh &amp; Hyper with plugins &amp; themes!</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Mon, 27 Apr 2020 12:08:03 +0000</pubDate>
      <link>https://dev.to/kumareth/a-beginner-s-guide-for-setting-up-autocomplete-on-ohmyzsh-hyper-with-plugins-themes-47f2</link>
      <guid>https://dev.to/kumareth/a-beginner-s-guide-for-setting-up-autocomplete-on-ohmyzsh-hyper-with-plugins-themes-47f2</guid>
      <description>&lt;p&gt;Your normal bash might have functions you normally need, but &lt;strong&gt;if you are a regular terminal user, zsh will be changing the way you type commands.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Features that zsh, ohmyzsh and hyper together provide will simply blow your mind.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did you know you can control Spotify from your terminal? Yes, Hyper Plugins allow you to do that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Setting up this stuff can be overwhelming for a beginner, so here's a very simple guide to get started! 🤩&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Introduction
&lt;/h2&gt;

&lt;p&gt;If you are using a regular terminal like what you see below, you are missing a lot of features that OhMyZsh provides.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fflaviocopes.com%2Fmacos-terminal-setup%2FScreenshot%25202019-01-29%2520at%252018.34.04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fflaviocopes.com%2Fmacos-terminal-setup%2FScreenshot%25202019-01-29%2520at%252018.34.04.png" alt="Flaviocope's MacOS Terminal" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, you'll be doing a terminal makeover to make it look like this...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2ye7t3ly1p1o81jrhy5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2ye7t3ly1p1o81jrhy5.jpg" alt="My Hyper Terminal" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not just the looks, but OhMyZsh comes with ample of features to lighten up your programming journey.&lt;/p&gt;

&lt;p&gt;At the end of the tutorial, this is what you would be able to do in your terminal...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NPM, Git autocomplete&lt;/li&gt;
&lt;li&gt;Auto Suggestions while you type in the terminal&lt;/li&gt;
&lt;li&gt;Syntax Highlighting that tells if a command is defined&lt;/li&gt;
&lt;li&gt;Use the cursor to edit the terminal command&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;git branch&lt;/code&gt; and &lt;code&gt;git status&lt;/code&gt; of the current directory&lt;/li&gt;
&lt;li&gt;Open new tabs with the same directory as the current tab&lt;/li&gt;
&lt;li&gt;Use OhMyZsh features like navigating without using &lt;code&gt;cd&lt;/code&gt;, usage of &lt;code&gt;ll&lt;/code&gt;, easier tab-click based navigation, and much more!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ❤️ Get Started
&lt;/h2&gt;

&lt;p&gt;First, you have to install &lt;code&gt;zsh&lt;/code&gt;. In some cases (depends on the OS you are running), it would already be installed. Therefore, check if it's installed by running &lt;code&gt;zsh --version&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;The installation process for &lt;code&gt;zsh&lt;/code&gt; is different in different Operating Systems. Checkout the &lt;a href="https://github.com/robbyrussell/oh-my-zsh/wiki/Installing-ZSH" rel="noopener noreferrer"&gt;Zsh Installation Guide&lt;/a&gt; to install zsh.&lt;/p&gt;

&lt;p&gt;After you install Zsh, make sure you make it your default shell. Run the following in your terminal to do so.&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;chsh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which zsh&lt;span class="si"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Log out and Log in back to your default shell. Run &lt;code&gt;echo $SHELL&lt;/code&gt; and the output &lt;code&gt;/bin/zsh&lt;/code&gt; or similar is expected.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔰 Installing OhMyZsh
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that zsh and OhMyZsh are different.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Install &lt;code&gt;OhMyZsh&lt;/code&gt; by running the following command in terminal.&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;When you install OhMyZsh, many plugins come with it for your rescue!&lt;/p&gt;

&lt;p&gt;To add useful plugins, Open &lt;code&gt;~/.zshrc&lt;/code&gt; in TextEdit/Notepad/Vim/VSCode.&lt;/p&gt;

&lt;p&gt;In the list of plugins that you see in the file, just add a plugin named &lt;code&gt;npm&lt;/code&gt;, like this 👇&lt;/p&gt;

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

plugins=(
  git
  bundler
  dotenv
  osx
  rake
  rbenv
  ruby
  npm # you added this
)


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

&lt;/div&gt;

&lt;p&gt;Voila! You are done with OhMyZsh! To see the changes, run &lt;code&gt;source ~/.zshrc&lt;/code&gt; in the terminal, and now you have the features of an OhMyZsh shell.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔰 Installing HyperTerm by Zeit
&lt;/h2&gt;

&lt;p&gt;Zeit (the creator of now.sh and Next.js) has created an awesome terminal app for us that is built in Electron.&lt;/p&gt;

&lt;p&gt;Download Hyper from &lt;a href="https://hyper.is/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚛️ Configure Hyper with OhMyZsh
&lt;/h3&gt;

&lt;p&gt;Open Hyper Terminal. You won't see OhMyZsh running there. So, go to Hyper Settings. On OSX, it's &lt;code&gt;Hyper &amp;gt; Preferences&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That would open a &lt;code&gt;.hyper.js&lt;/code&gt; file in your favorite editor. This file contains all the settings of your terminal that are super easy to control!&lt;/p&gt;

&lt;p&gt;To enable OhMyZsh as a default shell in Hyper, make this change in &lt;code&gt;.hyper.js&lt;/code&gt; 👇&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="gd"&gt;- shell: '/bin/bash'
&lt;/span&gt;&lt;span class="gi"&gt;+ shell: '/bin/zsh'
&lt;/span&gt;&lt;span class="err"&gt;

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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;And that would make OhMyZsh your default Hyper Terminal shell!&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🤩 Autocomplete while you type a command
&lt;/h3&gt;

&lt;p&gt;Git Clone the &lt;code&gt;zsh-autocomplete&lt;/code&gt; plugin in the OhMyZsh plugin folder.&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-autosuggestions


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

&lt;/div&gt;

&lt;p&gt;Once that is done, add the plugin in the &lt;code&gt;~/.zshrc&lt;/code&gt; file's plugin list.&lt;/p&gt;

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

plugins=(
  ...
  zsh-autosuggestions
)


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  🎉 Zsh sytax highlighting
&lt;/h3&gt;

&lt;p&gt;Git Clone the &lt;code&gt;zsh-syntax-highlighting&lt;/code&gt; plugin in the OhMyZsh plugin folder.&lt;/p&gt;

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

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;git clone https://github.com/zsh-users/zsh-syntax-highlighting.git &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-syntax-highlighting


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

&lt;/div&gt;

&lt;p&gt;And once again add it in the plugins list of the &lt;code&gt;.zshrc&lt;/code&gt; file.&lt;/p&gt;

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

plugins=(
  ... 
  zsh-syntax-highlighting
)


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

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: To reflect every change you make, do &lt;code&gt;source ~/.zshrc&lt;/code&gt; in the terminal.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  📯 Enabling Hyper related features and themes
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;.hyper.js&lt;/code&gt; by toggling Settings of Hyper Terminal.&lt;/p&gt;

&lt;p&gt;Check out the &lt;code&gt;plugins: [...]&lt;/code&gt; section and paste these plugin names there.&lt;/p&gt;

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

&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hypercwd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyper-statusline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyper-alt-click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyperterm-safepaste&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyper-search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hypergoogle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyperborder&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyper-tab-icons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hyper-hide-title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shades-of-purple-hyper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Save the file and Hyper would automatically install those plugins and themes for you. To reflect the changes, just close and start Hyper Terminal again.&lt;/p&gt;

&lt;p&gt;Hooray! &lt;strong&gt;You now have all the features in your terminal which were listed in the start of this DEV.to article.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  BONUS: Setting up the same terminal configuration for Integrated Terminal in VSCode
&lt;/h2&gt;

&lt;p&gt;In the VSCode Settings, add the following JSON key-value pairs and you'll be good to go!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.shell.osx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/bin/zsh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"terminal.integrated.fontSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;And that is it folks!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ohmyz.sh" rel="noopener noreferrer"&gt;https://ohmyz.sh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hyper.is" rel="noopener noreferrer"&gt;https://hyper.is&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏆 About me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup" rel="noopener noreferrer"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh" rel="noopener noreferrer"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this article. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>bash</category>
    </item>
    <item>
      <title>6 Awesome JavaScript Snippets to read and learn from!</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Thu, 09 Apr 2020 11:35:19 +0000</pubDate>
      <link>https://dev.to/kumareth/6-awesome-javascript-snippets-to-read-and-learn-from-5c8f</link>
      <guid>https://dev.to/kumareth/6-awesome-javascript-snippets-to-read-and-learn-from-5c8f</guid>
      <description>&lt;p&gt;When I was a JavaScript newbie, I used to read a lot of code snippets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reading other people's code teaches us a lot.&lt;/strong&gt; So, I make sure I read and understand a code snippet every day and I also share them on Twitter!&lt;/p&gt;

&lt;p&gt;So, here are a few code-snippets I have read in the past few days!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Convert RGB colors to Hex Codes
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the gist&lt;/strong&gt; 🚀 &lt;a href="https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/RGBToHex.md"&gt;https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/RGBToHex.md&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Find the length of a string in bytes
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the gist&lt;/strong&gt; 🚀 &lt;a href="https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/byteSize.md"&gt;https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/byteSize.md&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Detect all kinds of Apple Devices
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Find factorial of any number
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the gist&lt;/strong&gt; 🚀 &lt;a href="https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/factorial.md"&gt;https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/factorial.md&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Function to deep clone an object
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the gist&lt;/strong&gt; 🚀 &lt;a href="http://bit.ly/deepclone"&gt;http://bit.ly/deepclone&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Convert any string into Camel Case
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's the gist&lt;/strong&gt; 🚀 &lt;a href="https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/toCamelCase.md"&gt;https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/toCamelCase.md&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔥 There are many more online!
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/30-seconds/30-seconds-of-code/"&gt;30 Seconds Of Code&lt;/a&gt; is a very awesome nifty project that has tons of JavaScript Snippets to look at! They have CSS Snippets as well. 🤩&lt;/p&gt;




&lt;h2&gt;
  
  
  🏆 About me
&lt;/h2&gt;

&lt;p&gt;I am &lt;strong&gt;Kumar Abhirup, a 16-year-old JavaScript React developer&lt;/strong&gt; from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this post. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Next.js + Docker. Made easy.</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Sat, 28 Mar 2020 09:31:08 +0000</pubDate>
      <link>https://dev.to/kumareth/next-js-docker-made-easy-2bok</link>
      <guid>https://dev.to/kumareth/next-js-docker-made-easy-2bok</guid>
      <description>&lt;p&gt;This week while starting to build a huge SaaS product, I had to make many decisions. The biggest decision I made was to build that SaaS product with the Microservices architecture.&lt;/p&gt;

&lt;p&gt;Thankfully, &lt;a href="https://dev.to/bettercodingacademy"&gt;Lucas Chen&lt;/a&gt; had &lt;a href="https://dev.to/bettercodingacademy/i-m-a-professional-react-developer-and-here-s-how-i-set-up-react-node-js-microservices-using-docker-and-graphql-20gk"&gt;this amazing series&lt;/a&gt; that explained the React + GraphQL + Docker Microservices architecture. In his series, the backends were microservices but React was not hosted on Docker. I wanted it all on Docker, so I had to research a lot, about integrating React (especially Next.js) with Docker.&lt;/p&gt;

&lt;p&gt;After a few days of research and setting up a Containerized Next.js App, I am here to share with you how to do it.&lt;/p&gt;

&lt;p&gt;Hope you like it :)&lt;/p&gt;




&lt;h1&gt;
  
  
  🦋 Getting Started
&lt;/h1&gt;

&lt;p&gt;Setting up a Next.js shouldn't be hard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Wait! We are not doing it all from scratch.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Instead, I would recommend you to clone &lt;a href="https://github.com/KumarAbhirup/dockerized"&gt;this repo&lt;/a&gt;. We will learn about containerized Next.js from there. In this way, you will be able to compare your progress to that repository so that you can ensure you don't get lost in a long tutorial.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/KumarAbhirup"&gt;
        KumarAbhirup
      &lt;/a&gt; / &lt;a href="https://github.com/KumarAbhirup/dockerized"&gt;
        dockerized
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Boilerplate to start with Docker setup (Next.js included)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
🏄 dockerized&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://github.com/KumarAbhirup/Emoji-Log/"&gt;&lt;img src="https://camo.githubusercontent.com/f1192c4f17b29fec0537b9127695ae2791d0cf1cea32dda7a140d15023932477/68747470733a2f2f63646e2e6a7364656c6976722e6e65742f67682f61686d616461776169732f737475666640636139373837343138333634313262356533336365383536316635663935633933333137373036372f656d6f6a692d6c6f672f666c61742e737667" alt="emoji-log"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/kumar_abhirup/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/f5c56fbd6a3bc617dc845d394184a64559ab7ec88baf90ec3003363cc1d1a55a/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6b756d61725f616268697275702e7376673f7374796c653d736f6369616c266c6162656c3d406b756d61725f61626869727570" alt="Twitter"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
📦 Setup&lt;/h2&gt;
&lt;h3&gt;
🖥️ Development environment&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Run&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight highlight-source-shell position-relative js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/KumarAbhirup/dockerized dockerized &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; to clone project&lt;/span&gt;
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; dockerized &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; enter in the project&lt;/span&gt;
docker-compose up&lt;/pre&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Rename all the &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the root of the directory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Visit &lt;code&gt;http://localhost:3000/&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
⚒️ Linting&lt;/h3&gt;
&lt;h4&gt;
In VSCode&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Install ESLint and Prettier VSCode extensions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Done! Now you have live linting and autofixing setup!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
In Any other IDE&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;yarn lint&lt;/code&gt; in indivisual &lt;code&gt;packages&lt;/code&gt; to check for linting errors.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;yarn lint:fix&lt;/code&gt; to fix the linting errors.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
🦄 Info&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;We are following the micro-services architechture. That means, to install npm modules, you'll have to run &lt;code&gt;yarn add&lt;/code&gt; in the respective packages.&lt;/li&gt;
&lt;li&gt;To customize the linter, use &lt;code&gt;.eslintrc&lt;/code&gt; and &lt;code&gt;.prettierrc&lt;/code&gt; file. &lt;a href="https://eslint.org" rel="nofollow"&gt;Learn more&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
📝 License&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;MIT © Kumar Abhirup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Created by &lt;a href="https://kumar.now.sh" rel="nofollow"&gt;Kumar Abhirup&lt;/a&gt; 👉 &lt;a href="https://twitter.com/kumar_abhirup/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/f5c56fbd6a3bc617dc845d394184a64559ab7ec88baf90ec3003363cc1d1a55a/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6b756d61725f616268697275702e7376673f7374796c653d736f6369616c266c6162656c3d406b756d61725f61626869727570" alt="Twitter"&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Peace ✌️&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/KumarAbhirup/dockerized"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;The above repository includes...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A setup that is scalable. You may append your dockerized backends to it later.&lt;/li&gt;
&lt;li&gt;ESLint + Prettier setup included.&lt;/li&gt;
&lt;li&gt;It's TypeScript. :)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔰 Things you need
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker Installed on your machine&lt;/li&gt;
&lt;li&gt;Some basic knowledge of Next.js&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🚀 Clone and Setup the repository
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run the below command
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/KumarAbhirup/dockerized dockerized
&lt;span class="nb"&gt;cd &lt;/span&gt;dockerized
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Rename all the &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;. You'll find it in &lt;code&gt;packages/landingpage&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in the root of the directory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you cloned the project, the Next.js App is ready to run.&lt;/p&gt;

&lt;p&gt;Just run the below command to fire up the development environment for the Next.js project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  👁 But Kumar, how does this thing even work?
&lt;/h3&gt;

&lt;p&gt;You might be wondering where your Next.js project is staying. &lt;/p&gt;

&lt;p&gt;It is in the &lt;code&gt;packages/landingpage&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r9lHJZqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/yqX1wSC/Screenshot-2020-03-27-at-5-18-48-PM.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r9lHJZqg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/yqX1wSC/Screenshot-2020-03-27-at-5-18-48-PM.jpg" alt="Next.js Project Folder Structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might be wondering why that Next.js project is kept deep inside the file system. &lt;/p&gt;

&lt;p&gt;I did it because no one dockerizes Next.js when they are only using Next.js... &lt;/p&gt;

&lt;p&gt;Dockerizing makes sense when you have a huge container architecture that connects your React frontends to the Containerized backends.&lt;/p&gt;

&lt;p&gt;So, the repository would not just contain a Next.js project but would have backends kept in the same &lt;code&gt;packages&lt;/code&gt; folder.&lt;/p&gt;




&lt;h3&gt;
  
  
  📦 How to containerize Next.js?
&lt;/h3&gt;

&lt;p&gt;To use Docker to containerize any code, we need to have a &lt;code&gt;Dockerfile&lt;/code&gt; in the package. Every container has its own &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next.js too, will have its own Dockerfile. Let us take a look at it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/KumarAbhirup/dockerized/blob/master/packages/landingpage/Dockerfile"&gt;&lt;strong&gt;&lt;code&gt;packages/landingpage/Dockerfile&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:12

ENV PORT 3000

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Installing dependencies
COPY package*.json /usr/src/app/
RUN npm install

# Copying source files
COPY . /usr/src/app

# Building app
RUN npm run build
EXPOSE 3000

# Running the app
CMD "npm" "run" "dev"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me explain what's happening here. Here, by &lt;code&gt;FROM node:12&lt;/code&gt;, we are telling Docker to work with the Node.js image.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ENV PORT 3000&lt;/code&gt; just exposes the environment variable &lt;code&gt;PORT=3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The below code snippet tells docker to create directories, namely &lt;code&gt;/usr/src/app&lt;/code&gt;. We also tell Docker to use that directory as its primary workspace (for carrying out processes) hereafter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The below code snippet copies &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt; from your local cloned repository to the Docker Container and then runs &lt;code&gt;npm install&lt;/code&gt; on it. I recommend you to take a look at &lt;a href="https://github.com/KumarAbhirup/dockerized/blob/master/packages/landingpage/package.json"&gt;&lt;strong&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; of the Next.js container so you get the idea.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;COPY package*.json /usr/src/app/
RUN npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have all the &lt;code&gt;node_modules&lt;/code&gt; ready, below code will copy our code from our local computer directory and will put it into the Docker Container Directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Copying source files
COPY . /usr/src/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the &lt;code&gt;Dockerfile&lt;/code&gt; builds the Next.js app, exposes port 3000 (where Next.js works by default), and runs the command &lt;code&gt;npm run dev&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Building app
RUN npm run build
EXPOSE 3000

# Running the app
CMD "npm" "run" "dev"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope you understood all that is happening due to the Dockerfile.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Now, we have successfully containerized the application with Next.js! But we are not yet done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For hot-reloading to work with Next.js and Docker, you need to have the below code snippet added to the &lt;code&gt;packages/landingpage/next.config.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  webpackDevMiddleware: config =&amp;gt; {
    config.watchOptions = {
      poll: 1000,
      aggregateTimeout: 300,
    }

    return config
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;We are still not done!&lt;/p&gt;

&lt;p&gt;To run all our containers (in this case only one) together successfully, we will need a &lt;code&gt;docker-compose.yml&lt;/code&gt; file in the root of the project.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/KumarAbhirup/dockerized/blob/master/docker-compose.yml"&gt;&lt;strong&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; in your folder structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.3"

services:
  nextjs:
    ports:
      - 3000:3000
    build:
      context: packages/landingpage
      dockerfile: Dockerfile
    volumes:
      - ./packages/landingpage:/usr/src/app
      - /usr/src/app/node_modules
      - /usr/src/app/.next
    env_file:
      - .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code snippet makes sure that port 3000 is exposed. The &lt;code&gt;docker-compose.yml&lt;/code&gt; file also tells Docker what services to build and which &lt;code&gt;Dockerfile&lt;/code&gt; to use.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;env_file&lt;/code&gt; tells the composer to use a &lt;code&gt;.env&lt;/code&gt; file which if you have not yet made in your project, please add it for it to work.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;volumes&lt;/code&gt; part is very important here. Without it, your Next.js will work, but the _Hot Reloading Developmental Feature` would not work.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔥 Hurray!
&lt;/h3&gt;

&lt;p&gt;If you surf through the repository carefully, you will understand how to containerize Next.js with Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are done!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To run the Dockerized Next.js app...&lt;/p&gt;

&lt;p&gt;Run &lt;strong&gt;&lt;code&gt;docker-compose up&lt;/code&gt;&lt;/strong&gt; and open &lt;code&gt;http://localhost:3000&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;p&gt;To make changes in code, make changes to &lt;code&gt;packages/landingpage/pages/index.tsx&lt;/code&gt; file to see your website development experience come alive.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚀 For production
&lt;/h3&gt;

&lt;p&gt;When deploying to production, just make sure that you make a small change in your &lt;code&gt;packages/landingpage/Dockerfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Change the last line (&lt;code&gt;CMD "npm" "run" "dev"&lt;/code&gt;) to &lt;strong&gt;&lt;code&gt;CMD "npm" "start"&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❤️ Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/KumarAbhirup/dockerized/"&gt;Source Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.codemochi.com/blog/2019-08-27-nextjs-hmr/"&gt;Docker + Next.js Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏆 About me
&lt;/h2&gt;

&lt;p&gt;I am &lt;strong&gt;Kumar Abhirup, a 16-year-old JavaScript React developer&lt;/strong&gt; from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this post. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>react</category>
      <category>devops</category>
      <category>javascript</category>
    </item>
    <item>
      <title>let vs const - Let's discuss.</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Sun, 22 Mar 2020 10:35:15 +0000</pubDate>
      <link>https://dev.to/kumareth/const-vs-let-let-s-discuss-34m9</link>
      <guid>https://dev.to/kumareth/const-vs-let-let-s-discuss-34m9</guid>
      <description>&lt;p&gt;We all are familiar with the difference between const, let and var. If not, please read this.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/sarah_chima" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qdWCqN6Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--gjNxKyFk--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/25491/0f47f931-df2d-473c-982c-4adbdc149e3c.jpg" alt="sarah_chima"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/sarah_chima/var-let-and-const--whats-the-difference-69e" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Var, let and const- what's the difference?&lt;/h2&gt;
      &lt;h3&gt;Sarah Chima ・ Oct 25 '17 ・ 5 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#es6&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascipt&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#newbie&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;





&lt;p&gt;For those who are familiar, should know that in the modern-day JavaScript, &lt;strong&gt;YOU SHOULD NEVER USE &lt;code&gt;var&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So now, what we are left with, is the &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 The two scenarios
&lt;/h2&gt;

&lt;p&gt;People believe their ways of using them both. Strongly.&lt;/p&gt;

&lt;p&gt;Here are the two types of people.&lt;/p&gt;

&lt;p&gt;1) Those who use &lt;code&gt;const&lt;/code&gt; for Constants (Like for &lt;code&gt;const PI = 3.14&lt;/code&gt;)&lt;br&gt;
2) Those who use &lt;code&gt;const&lt;/code&gt; for everything that won't be let&lt;/p&gt;
&lt;h3&gt;
  
  
  📯 const for Constants
&lt;/h3&gt;

&lt;p&gt;Some people believe that &lt;code&gt;const&lt;/code&gt; should only be used for strictly constant values like the Action Type Reducer Strings, Math values and constants like PI, etc.&lt;/p&gt;

&lt;p&gt;If you are that person, you are from &lt;strong&gt;team CONSTANT SPARINGLY&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  📯 const for everything that won't be let
&lt;/h3&gt;

&lt;p&gt;If you always use &lt;code&gt;const&lt;/code&gt;, no matter what, and only use &lt;code&gt;let&lt;/code&gt; when you change a variable, you are from &lt;strong&gt;team CONSTANT FOR ALL&lt;/strong&gt;.&lt;/p&gt;



&lt;p&gt;There has been a lot of talk around it on Twitter due to this tweet by Dan Abramov.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--gRLKVll4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1166344766210150401/amRnWzl-_normal.jpg" alt="Dan Abramov profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Dan Abramov
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/dan_abramov"&gt;@dan_abramov&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      TC39 members: const was a mistake.&lt;br&gt;Reddit: NO DAN YOU'RE WRONG YOU JUST DONT UNDERSTAND JAVASCRIPTS
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      12:53 PM - 21 Dec 2019
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1208369896880558080" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1208369896880558080" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1208369896880558080" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;The tweet pretty much sums up that he is from the team CONSTANT SPARINGLY.&lt;/p&gt;

&lt;p&gt;If you have been seeing WesBos' tutorials, he seems like he is from the team CONSTANT FOR ALL.&lt;/p&gt;

&lt;p&gt;Dan has provided &lt;a href="https://overreacted.io/on-let-vs-const/"&gt;a beautiful explanation&lt;/a&gt; for why he thinks const shouldn't be used.&lt;/p&gt;

&lt;p&gt;Also, &lt;a href="https://jamie.build/const"&gt;this writeup here&lt;/a&gt; focuses on easily concluding this discussion. But still, what's your opinion on it?&lt;/p&gt;




&lt;p&gt;What do you prefer? Let's Discuss!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>discuss</category>
    </item>
    <item>
      <title>async/await Crash Course</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Sat, 22 Feb 2020 11:41:38 +0000</pubDate>
      <link>https://dev.to/kumareth/async-await-crash-course-1453</link>
      <guid>https://dev.to/kumareth/async-await-crash-course-1453</guid>
      <description>&lt;p&gt;🔥 Learn async/await (very basics) here 👇&lt;/p&gt;

&lt;p&gt;When you learn async/await in #JavaScript,&lt;/p&gt;

&lt;p&gt;you quickly fall into words like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Synchronous &amp;amp; Asynchronous code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Event Loops&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Promises&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These things aren't easy to understand in one go.&lt;/p&gt;

&lt;p&gt;Complex theories gatekeep beginners.&lt;/p&gt;

&lt;p&gt;So, we will only learn about practical stuff.&lt;/p&gt;




&lt;p&gt;Let us first learn about "Promises"&lt;/p&gt;

&lt;p&gt;In the below snippet, what we are intending is to &lt;br&gt;
output &lt;code&gt;Done First&lt;/code&gt;&lt;br&gt;
and then output &lt;code&gt;Done Last&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the below snippet outputs "Done Last" first.&lt;/p&gt;

&lt;p&gt;That is now JavaScript behaves. It does not wait by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b8O7VhBx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/d0Nc65D/1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b8O7VhBx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/d0Nc65D/1.png" alt="Code Snippet"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;To make JavaScript wait for a second &lt;/p&gt;

&lt;p&gt;to output &lt;code&gt;Done First&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and then print &lt;code&gt;Done Last&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;Promise&lt;/code&gt; constructor. &lt;/p&gt;

&lt;p&gt;It accepts a function as the only argument. &lt;/p&gt;

&lt;p&gt;The function receives few params. 2 of them being &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ImSYqe_V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/4p2VXw9/2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ImSYqe_V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/4p2VXw9/2.png" alt="Code Snippet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;resolve&lt;/code&gt; accepts arguments.&lt;/p&gt;

&lt;p&gt;These arguments later become the params in the .then() function.&lt;/p&gt;

&lt;p&gt;So, the .then() function runs only after the promise is resolved.&lt;/p&gt;

&lt;p&gt;Well, don't create a Promise just for a "console.log after setTimeout".&lt;/p&gt;

&lt;p&gt;This was just for explanation. 🙂&lt;/p&gt;



&lt;p&gt;Now, here's the async/await part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done Last.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can also be written as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done Last.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like in the below snippet. It just works!&lt;/p&gt;

&lt;p&gt;Wondering what's the &lt;code&gt;async&lt;/code&gt; part in the below snippet?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vnOm9qW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/zs8X16s/3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vnOm9qW0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/zs8X16s/3.png" alt="Code Snippet"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The await keyword only happens to work inside an async function.&lt;/p&gt;

&lt;p&gt;An async function tells the compiler ahead of time that the function will be returning a Promise and will not have a value resolved right away.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0acBxtK0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/8D39DNp/4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0acBxtK0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/8D39DNp/4.png" alt="Code Snippet"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I hope that gives a basic idea about what async/await is and what it does.&lt;/p&gt;

&lt;p&gt;Here are two nice resources about it 🔥&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise"&gt;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261"&gt;https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-promise-27fc71e77261&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you spot a mistake, let everyone know 🙌&lt;/p&gt;




&lt;h3&gt;
  
  
  About me
&lt;/h3&gt;

&lt;p&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this post. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Top 5 Awesome Things to do in your README!</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Mon, 10 Feb 2020 10:16:12 +0000</pubDate>
      <link>https://dev.to/kumareth/5-must-have-badges-to-add-in-your-readme-14c3</link>
      <guid>https://dev.to/kumareth/5-must-have-badges-to-add-in-your-readme-14c3</guid>
      <description>&lt;p&gt;&lt;strong&gt;README.md is the landing page of your code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you are building an open-source repository, README is the most important file in the whole repository.&lt;/p&gt;

&lt;p&gt;It has to not just look good, but also read well. &lt;/p&gt;

&lt;p&gt;It should tell its readers everything.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Usage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Website&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Version&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Are tests failing or passing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Average Activity&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User Testimonies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;License&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Star Gazers on GitHub&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And much more...&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good news is, most of the above information can be expressed in just a few dynamic SVG elements!&lt;/p&gt;

&lt;p&gt;You have seen them already, everywhere... in every famous repository.&lt;/p&gt;

&lt;p&gt;I really like how &lt;a href="https://ahmadawais.com/" rel="noopener noreferrer"&gt;Mr. Ahmed Awais&lt;/a&gt; writes his READMEs. See an example &lt;a href="https://github.com/ahmadawais/create-guten-block" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  What are README Badges?
&lt;/h1&gt;

&lt;p&gt;See this 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F9vc2JjR%2FAdd-badges-for-Travis-CI-Coveralls-and-Code-Climate-to-your-Readme-ruby-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2F9vc2JjR%2FAdd-badges-for-Travis-CI-Coveralls-and-Code-Climate-to-your-Readme-ruby-4.png" alt="Example Badges"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your badges don't have to be that boring.&lt;/p&gt;

&lt;p&gt;You can check out all the badges you can use &lt;a href="https://shields.io" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  Here are 5 must-have README badges!
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;&lt;code&gt;🧪🧪🧪 Travis Tests Status&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is the current Travis status of &lt;a href="https://www.npmjs.com/package/bulk-mail-cli" rel="noopener noreferrer"&gt;my NPM Package&lt;/a&gt; 🔰 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Ftravis%2Fadventmail%2Fbulk-mail-cli" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Ftravis%2Fadventmail%2Fbulk-mail-cli" alt="Travis Status for bulk-mail-cli"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the badge in your readme by pasting the following syntax... &lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;:githubUsername&lt;/code&gt; and &lt;code&gt;:repository&lt;/code&gt; with real data.&lt;/p&gt;

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

&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Travis Status&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://img.shields.io/travis/:githubUsername/:repository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;&lt;code&gt;⭐️⭐️⭐️ Rate on pkgreview.dev&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pkgreview.dev" rel="noopener noreferrer"&gt;pkgreview.dev&lt;/a&gt; is an app where users can review and rate your NPM Package. Users can write testimonies of your package on the app.&lt;/p&gt;

&lt;p&gt;To encourage them to write the testimonies/reviews... You can add this in the README 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pkgreview.dev/npm/react" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2FHPTDdXH%2FScreenshot-2020-01-28-at-6-36-44-PM.jpg" alt="Review us on pkgreview.dev"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the badge in your readme by pasting the following syntax...&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;&amp;lt;package-name&amp;gt;&lt;/code&gt; with the real package name. You can check the package name and URL on &lt;a href="https://pkgreview.dev" rel="noopener noreferrer"&gt;pkgreview.dev&lt;/a&gt;.&lt;/p&gt;

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

| &lt;span class="gs"&gt;**Like us a lot?**&lt;/span&gt; Help others know why you like us! &lt;span class="gs"&gt;**Review this package on [pkgreview.dev](https://pkgreview.dev/npm/&amp;lt;package-name&amp;gt;)**&lt;/span&gt; | ➡   | &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;![Review us on pkgreview.dev&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://i.ibb.co/McjVMfb/pkgreview-dev.jpg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;](https://pkgreview.dev/npm/&lt;span class="nt"&gt;&amp;lt;package-name&amp;gt;&lt;/span&gt;) |
| ----------------------------------------------------------------------------------------------------------------------------------------- | --- | --------------------------------------------------------------------------------------------------------------------- |&lt;span class="sb"&gt;


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;&lt;code&gt;🔰🔰🔰 NPM Downloads Badge&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The below image shows the number of times &lt;strong&gt;React&lt;/strong&gt; was downloaded on NPM last week...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fnpm%2Fdw%2Freact" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fnpm%2Fdw%2Freact" alt="times React was downloaded on NPM last week"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the badge in your readme by pasting the following syntax... &lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;:packageName&lt;/code&gt; with the NPM Package slug/name.&lt;/p&gt;

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

&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;NPM Downloads&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://img.shields.io/npm/dw/:packageName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  4. &lt;strong&gt;&lt;code&gt;📝📝📝 License Badge&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;People should know what license your repository uses. If your repository uses NPM, you can fetch license dynamically and get a badge like this 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fnpm%2Fl%2Fbulk-mail-cli" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fnpm%2Fl%2Fbulk-mail-cli" alt="bulk-mail-cli License"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the badge in your readme by pasting the following syntax... &lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;:packageName&lt;/code&gt; with the NPM Package slug/name.&lt;/p&gt;

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

&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;NPM License&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://img.shields.io/npm/l/:packageName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="sb"&gt;


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  5. &lt;strong&gt;&lt;code&gt;🐦🐦🐦 Twitter Badge&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you have a Twitter account for your repository, or if you have a Twitter Account as a maintainer of the repository, you gotta show a dynamic Twitter badge!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Ftwitter%2Ffollow%2Fkumar_abhirup.svg%3Fstyle%3Dsocial%26label%3D%40kumar_abhirup" alt="Twitter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get the badge in your readme by pasting the following syntax... &lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;:twitterHandle&lt;/code&gt; with your Twitter username.&lt;/p&gt;

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

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;![Twitter&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://img.shields.io/twitter/follow/:twitterHandle.svg?style=social&amp;amp;label=@:twitterHandle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;](https://twitter.com/:twitterHandle)&lt;span class="sb"&gt;


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

&lt;/div&gt;




&lt;h3&gt;
  
  
  That was just a scratch on the surface!
&lt;/h3&gt;

&lt;p&gt;The possibilities with READMEs are endless if you use SVGs by &lt;a href="https://shields.io" rel="noopener noreferrer"&gt;shields.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can create all kinds of custom and dynamic README SVG badges with it... Take a look!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://shields.io" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ibb.co%2Fr6239Bj%2FScreenshot-2020-02-10-at-3-26-55-PM.jpg" alt="Shields.io Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  With it, you can create badges for the following...
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;NPM Packages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WordPress Plugins&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Travis Tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CircleCI tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discord badge with live &lt;code&gt;online&lt;/code&gt; count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Twitter follower count&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub Stats&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Funding by OpenCollective&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uptime Monitors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub Stargazers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And so much more!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;README badges are useful. They provide so many insights and also look cool on GitHub and Package Managers like NPM.&lt;/p&gt;




&lt;h3&gt;
  
  
  About me
&lt;/h3&gt;

&lt;p&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup" rel="noopener noreferrer"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh" rel="noopener noreferrer"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this post. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>pkgreview.dev - The Ratings and Review Website for NPM Packages 🎉</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Fri, 31 Jan 2020 12:22:46 +0000</pubDate>
      <link>https://dev.to/kumareth/pkgreview-dev-the-ratings-and-review-website-for-npm-packages-12ll</link>
      <guid>https://dev.to/kumareth/pkgreview-dev-the-ratings-and-review-website-for-npm-packages-12ll</guid>
      <description>&lt;p&gt;Hey all! 🙌&lt;/p&gt;

&lt;p&gt;I am very thrilled to announce the side-project I have been working on since last week...&lt;/p&gt;

&lt;p&gt;I named it &lt;strong&gt;&lt;a href="https://pkgreview.dev" rel="noopener noreferrer"&gt;pkgreview.dev&lt;/a&gt;&lt;/strong&gt;! The complete product was born out of one tweet.&lt;/p&gt;

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

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



&lt;/p&gt;




&lt;h1&gt;
  
  
  🎊 &lt;code&gt;pkgreview.dev&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;A lot of people find it very difficult to decide what NPM Package to use.&lt;/p&gt;

&lt;p&gt;There comes pkgreview.dev to your rescue!&lt;/p&gt;

&lt;p&gt;📦 0.3 Million NPM Packages with GitHub Stats listed!&lt;/p&gt;

&lt;p&gt;🎉 Helps analyze NPM Packages&lt;/p&gt;

&lt;p&gt;🚨 Write &amp;amp; Read Reviews&lt;/p&gt;

&lt;p&gt;⭐️ Star Ratings like &lt;em&gt;rottentomatoes&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fph-files.imgix.net%2F7dc59a54-0d54-4804-8c9d-301482cafb0a%3Fauto%3Dformat%26auto%3Dcompress%26codec%3Dmozjpeg%26cs%3Dstrip%26w%3D582.330383480826%26h%3D380%26fit%3Dmax%26dpr%3D2" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fph-files.imgix.net%2F7dc59a54-0d54-4804-8c9d-301482cafb0a%3Fauto%3Dformat%26auto%3Dcompress%26codec%3Dmozjpeg%26cs%3Dstrip%26w%3D582.330383480826%26h%3D380%26fit%3Dmax%26dpr%3D2" alt="React @ pkgreview.dev"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🕹 The idea
&lt;/h2&gt;

&lt;p&gt;A lot of people find it very difficult to decide what NPM Package, React Component, Module or Library to use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;They end up checking on GitHub&lt;/strong&gt; to see how active the community is. GitHub does not tell you a clear picture. It is just a part of the picture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What people often miss&lt;/strong&gt;, is the first-hand experience of the users who have used the library.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pkgreview.dev&lt;/code&gt; displays all sorts of important metadata of a package (&lt;em&gt;reviews, ratings, last updated, stargazers, etc.&lt;/em&gt;) and also shows &lt;code&gt;other developers' opinion&lt;/code&gt; about them.&lt;/p&gt;

&lt;p&gt;And you can &lt;strong&gt;contribute by posting your review&lt;/strong&gt; about the NPM Package. 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Building a Community
&lt;/h2&gt;

&lt;p&gt;The app that you are currently seeing is in its MVP phase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To be useful to the masses, we need more reviews.&lt;/strong&gt; You, as a developer, can contribute a lot in this process by just posting a review to any useful package.&lt;/p&gt;

&lt;p&gt;This project needs the support of the &lt;strong&gt;JavaScript Community&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://pkgreview.dev/npm/react" rel="noopener noreferrer"&gt;Login with GitHub (takes two seconds) and write your first review!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;This is my first fast-shipped side project. Please do give me feedback on it! 🙌&lt;/strong&gt; This is just a start.&lt;/p&gt;

&lt;h2&gt;
  
  
  In my Todolist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add support for other package managers like PHP Composer, Docker Hub for Images, PIP for Python, and much more!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Give maintainers of the package special permissions like replying to the review or reporting it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use AI for creating reviews by reading about the package on the web (eg. GitHub issues, Blogposts, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make UI better and less gimmicky.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will be able to achieve the goals in the todo list only by your support. &lt;/p&gt;

&lt;p&gt;I love positive as well as critical feedback 🙌&lt;/p&gt;




&lt;h3&gt;
  
  
  About me
&lt;/h3&gt;

&lt;p&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup" rel="noopener noreferrer"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh" rel="noopener noreferrer"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this product. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>npm</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>This is how you should build and publish a Modern React Component!</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Sun, 26 Jan 2020 11:45:23 +0000</pubDate>
      <link>https://dev.to/kumareth/this-is-how-you-should-build-and-publish-react-components-4i4n</link>
      <guid>https://dev.to/kumareth/this-is-how-you-should-build-and-publish-react-components-4i4n</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_8rhNTLU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1280/1%2AEnkcn-vHRL596oFyvBW9Hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_8rhNTLU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1280/1%2AEnkcn-vHRL596oFyvBW9Hw.png" alt="React Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;React developers use similar component code day in and day out. But not all of them streamline the React Component building and publishing workflow.&lt;br&gt;
Before we discuss the building and publishing workflow, here's why we need to have it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Before we discuss the building and publishing workflow, here's why we need to have it.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reason 1:&lt;/strong&gt; Most of our React code is reusable and there's a high chance that we need the same React Component in another project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reason 2:&lt;/strong&gt; To keep a code uniformity among all of our React Projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reason 3:&lt;/strong&gt; An opportunity to contribute to the open-source. We can publish the component, and have others use it as well!&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You know how NPM packages are built. Yet, when it comes to publishing the React Component we use in a project, we hesitate.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reasons why you hesitate
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Building a new React Component that is publishable on NPM takes a lot of efforts.&lt;/li&gt;
&lt;li&gt;You feel it is not worthy to waste time installing and updating the published package in your project.&lt;/li&gt;
&lt;li&gt;You want your component in your components folder, and when component code is changed, you want your project to "live reload".&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  When I was a novice, I used to publish a React Component like this…
&lt;/h2&gt;

&lt;p&gt;I used to create a new Git Repository.&lt;/p&gt;

&lt;p&gt;Then setup all the babel and webpack stuff.&lt;/p&gt;

&lt;p&gt;Then I would write the React Component code.&lt;/p&gt;

&lt;p&gt;Then I would compile it manually and publish it to npm using &lt;code&gt;npm publish&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To test the React Component, I would manually install the component in my project directory using &lt;code&gt;npm i -S that-react-component&lt;/code&gt;. That had no "Live Reload"… &lt;/p&gt;

&lt;p&gt;I had to update the package in the Component Repository and Update the module back in my project.&lt;/p&gt;
&lt;h4&gt;
  
  
  How shitty that procedure was. I knew it was shitty. So, I stopped open sourcing React Components. I let them lie in my Project Directories. If I would need a component, I copy-pasted the component files to another project. And that went on. Until I learned about…
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;create-react-library&lt;/code&gt; and &lt;code&gt;npm link&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;I was just strolling through the GitHub search box typing weird stuff, and then I found &lt;code&gt;create-react-library&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--149C9fw8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2560/1%2Att-8-gpw-xLZu0heaMZ57g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--149C9fw8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2560/1%2Att-8-gpw-xLZu0heaMZ57g.png" alt="React Workflow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Here's the much better way of doing it!
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;So, every time you know you are building a component for the ongoing project, think…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you might need the component for other projects.&lt;/li&gt;
&lt;li&gt;If the component can be useful for other devs out there.&lt;/li&gt;
&lt;li&gt;If your component logic and use-case is not very project-specific.&lt;/li&gt;
&lt;li&gt;Or for the sanity sake, you want your project files to be less cluttered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you see any of those reasons valid, you should consider building the component as a reusable component that is packaged as a module.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If yes, then move to Step 2.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Visit the master folder where you store all your projects via terminal and run the following 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npx create-react-library &amp;lt;COMPONENT_NAME&amp;gt; &lt;span class="c"&gt;# then answer few basic prompts&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;COMPONENT_NAME&amp;gt; &lt;span class="c"&gt;# enter in that directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;And voila! You got your React Component Boilerplate Code setup.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Do the following in the terminal 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i &lt;span class="c"&gt;# this will install your component modules&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;example &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i &lt;span class="c"&gt;# install CRA modules&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running above commands will install the modules that your React Component and Create React App Example will need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Let us browse the file structure of the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project
│   README.md
│   package.json
|   ...   
│
└───example
│   │   package.json
│   │   ...
│
└───src
    │   package.json
    │   ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, anytime you make a change to your library in &lt;code&gt;src/&lt;/code&gt; or to the example app's &lt;code&gt;example/src&lt;/code&gt;, &lt;code&gt;create-react-app&lt;/code&gt; will live-reload your local dev server so you can iterate on your component in real-time!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q-jNGlbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AmgIabNcs-qtTnzsf72SO2Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q-jNGlbt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/800/1%2AmgIabNcs-qtTnzsf72SO2Q.gif" alt="It's magic!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5
&lt;/h3&gt;

&lt;p&gt;Well, what if &lt;strong&gt;you want the component to work live with your ongoing project&lt;/strong&gt; without having to update and publish on npm?&lt;/p&gt;

&lt;p&gt;Here, &lt;code&gt;npm link&lt;/code&gt; comes for the rescue!&lt;/p&gt;

&lt;p&gt;In your the root of your component directory, run &lt;code&gt;$ npm link&lt;/code&gt;. That makes your component available globally to all projects!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6
&lt;/h3&gt;

&lt;p&gt;Now via terminal, reach the ongoing project directory, and run &lt;br&gt;
&lt;code&gt;$ npm link &amp;lt;COMPONENT_NAME&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That is it. You have connected both the worlds!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let both of your component directory and ongoing project watch and compile the code live.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 7
&lt;/h3&gt;

&lt;p&gt;It's time to use the component in your project! &lt;br&gt;
You can import and use the component in a normal way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ThatAwesomeComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;COMPONENT_NAME&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you update your component code and refresh your project in the browser, you'll see things come alive!&lt;/p&gt;

&lt;h4&gt;
  
  
  Go! Try that yourself!
&lt;/h4&gt;




&lt;h2&gt;
  
  
  Publishing your React Component
&lt;/h2&gt;

&lt;p&gt;Now that you want to publish/deploy/ship your React Component…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Make sure you have good documentation supporting your code.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Also, check your version number. If you feel it's all right and working, it's time to publish!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it. Your files will be built and published on NPM Registry!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want your build to be less bloated, publish the component with the following &lt;code&gt;.npmignore&lt;/code&gt; file.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# it is also configured for TypeScript Components&lt;/span&gt;
src
example
.vscode
.eslintrc
.prettierrc
package-lock.json
tsconfig.json
tsconfig.test.json
.gitignore
node_modules
.travis.yml
rollup.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  You forgot one thing!
&lt;/h2&gt;

&lt;p&gt;Do not forget to &lt;code&gt;npm unlink&lt;/code&gt; the component from your ongoing project directory so that you can use the "real" and "published" component. When do develop the component, you may link it again.&lt;/p&gt;

&lt;p&gt;To unlink, do &lt;code&gt;$ npm unlink &amp;lt;COMPONENT_NAME&amp;gt;&lt;/code&gt; from the project directory.&lt;/p&gt;




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

&lt;p&gt;&lt;a href="https://github.com/transitive-bullshit/create-react-library"&gt;https://github.com/transitive-bullshit/create-react-library&lt;/a&gt;&lt;br&gt;
&lt;a href="https://codurance.com/2016/12/21/how-to-use-npm-link"&gt;https://codurance.com/2016/12/21/how-to-use-npm-link&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;React components can be more awesome if built and published the right way.&lt;/p&gt;

&lt;h3&gt;
  
  
  About me
&lt;/h3&gt;

&lt;p&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this article. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>npm</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CodeSnip: Assign types to deconstructed parameters</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Sat, 04 Jan 2020 11:05:56 +0000</pubDate>
      <link>https://dev.to/kumareth/codesnip-assign-types-to-deconstructed-parameters-1lb3</link>
      <guid>https://dev.to/kumareth/codesnip-assign-types-to-deconstructed-parameters-1lb3</guid>
      <description>&lt;p&gt;This is a very small post.&lt;/p&gt;

&lt;p&gt;I'll be writing many such posts to enlighten new developers a little by using simple Code Snippets.&lt;/p&gt;

&lt;p&gt;Such writeups will be small and will yet teach a lot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tweet
&lt;/h2&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;h2&gt;
  
  
  Snippet
&lt;/h2&gt;

&lt;p&gt;Here's how you &lt;strong&gt;assign types to deconstructed parameters&lt;/strong&gt; in TypeScript functions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sGaRXfuB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/2hmNVVt/assigning-types-to-deconstructed-parameters.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sGaRXfuB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.ibb.co/2hmNVVt/assigning-types-to-deconstructed-parameters.png" alt="Code Snippet by Kumar Abhirup"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  About me
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do you like such CodeSnip posts? If yes, let me know in the comments section! That'll boost me to make more of these. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>How I built an awesome email-marketing Command Line App with TypeScript</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Wed, 01 Jan 2020 11:15:57 +0000</pubDate>
      <link>https://dev.to/kumareth/how-i-built-an-awesome-email-marketing-command-line-app-with-typescript-3f25</link>
      <guid>https://dev.to/kumareth/how-i-built-an-awesome-email-marketing-command-line-app-with-typescript-3f25</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/adventmail"&gt;
        adventmail
      &lt;/a&gt; / &lt;a href="https://github.com/adventmail/bulk-mail-cli"&gt;
        bulk-mail-cli
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Do quick, hassle-free email marketing with this small but very powerful tool! 🔥
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
&lt;br&gt;
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/80f6fd5d3b0df796d9f7b1a3dae8927899c32587f77e047261bfca33063e0cc2/68747470733a2f2f6c68332e676f6f676c6575736572636f6e74656e742e636f6d2f56734b50715844762d7877755861304c6b39794a6b796a66336f72733031585152577a6230676131466351333043787762776e396955575050366a744c784a744f6d4637354f6c4353684b49304a6b32637867346f70797233746b334d345030444658586d685679326b77394e7677574978745450534d516e76474b327433496a304631554e4267447930425930586e3065674c7163736877644d484e37645369425f524e74327153425f64317633726c55364777785266455a314b623545337a5f764967585034334d4933546165496b52633330446e336d59392d5463614375514978567a64556a325468435a2d2d52786164342d724747396747574c76344a71513348654b504b4673777257674d7244547977465539495737516e5f736375733353385733756e43484833506b7557374c6765556531345961597a6672784466687a2d366a4f7032696b337a34642d6d614e7349487a327278714e424e5a32677170675f6e525867457431397355516a6545516269703756355a617a525044367566633554717a554b49484f39786d495646315747595f5632753766393875667852566c34504c78692d4173374a46356b5743355049485030474c42794859353872676645756f4e797250646d79367065396b75512d57544a7a6c47617549467857755935775a6572636a6833544a2d433163585f56496f7252397162352d54433063307a4b46536d4e5a625566386e6830576f52304c42756c65537845696d744c67764365647a6949757749686952344b3958447a4c337a6a4233385130334169533163547469327a6166534142543471704a68614b4441775356466c526e416c745330506e344654515444376144374d54354674674e7a374533496168574d5a4367574e447637314b586333523051324b6933417779384155486c7450774d426973636a552d3378327648674d515649736e796d6d3073754671466e2d415541755f5066596f6839795f38564958385a70664b597546534433796977714338593d77313238302d683330352d6e6f"&gt;&lt;img width="650" src="https://camo.githubusercontent.com/80f6fd5d3b0df796d9f7b1a3dae8927899c32587f77e047261bfca33063e0cc2/68747470733a2f2f6c68332e676f6f676c6575736572636f6e74656e742e636f6d2f56734b50715844762d7877755861304c6b39794a6b796a66336f72733031585152577a6230676131466351333043787762776e396955575050366a744c784a744f6d4637354f6c4353684b49304a6b32637867346f70797233746b334d345030444658586d685679326b77394e7677574978745450534d516e76474b327433496a304631554e4267447930425930586e3065674c7163736877644d484e37645369425f524e74327153425f64317633726c55364777785266455a314b623545337a5f764967585034334d4933546165496b52633330446e336d59392d5463614375514978567a64556a325468435a2d2d52786164342d724747396747574c76344a71513348654b504b4673777257674d7244547977465539495737516e5f736375733353385733756e43484833506b7557374c6765556531345961597a6672784466687a2d366a4f7032696b337a34642d6d614e7349487a327278714e424e5a32677170675f6e525867457431397355516a6545516269703756355a617a525044367566633554717a554b49484f39786d495646315747595f5632753766393875667852566c34504c78692d4173374a46356b5743355049485030474c42794859353872676645756f4e797250646d79367065396b75512d57544a7a6c47617549467857755935775a6572636a6833544a2d433163585f56496f7252397162352d54433063307a4b46536d4e5a625566386e6830576f52304c42756c65537845696d744c67764365647a6949757749686952344b3958447a4c337a6a4233385130334169533163547469327a6166534142543471704a68614b4441775356466c526e416c745330506e344654515444376144374d54354674674e7a374533496168574d5a4367574e447637314b586333523051324b6933417779384155486c7450774d426973636a552d3378327648674d515649736e796d6d3073754671466e2d415541755f5066596f6839795f38564958385a70664b597546534433796977714338593d77313238302d683330352d6e6f" alt="bulk-mail-cli by Kumar Abhirup"&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/bulk-mail-cli" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a42357f61c82400d0650debe372b1104fb56fe1a444460a972438e58191f69ab/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f747970652d434c492d79656c6c6f772e7376673f7374796c653d666c61742d737175617265" alt="Type"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/bulk-mail-cli" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a469c71d6aac525d345e4e65b69c68e02fd926eb746acaa7342fc8afe0f3b215/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6e706d2d62756c6b2d2d6d61696c2d2d636c692d4342333833372e7376673f7374796c653d666c61742d737175617265" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/bulk-mail-cli" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/8ff884fd1acc670a9445f4c08032b0e10ea58348a64ff77637fbd146731b1257/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f62756c6b2d6d61696c2d636c693f6c6162656c3d76657273696f6e267374796c653d666c61742d737175617265" alt="Version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/KumarAbhirup/bulk-mail-cli"&gt;&lt;img src="https://camo.githubusercontent.com/4141a15cb0336a956ab85c7048ff545f593ac3627f25239535ebc1496065f5b2/68747470733a2f2f7472617669732d63692e636f6d2f616476656e746d61696c2f62756c6b2d6d61696c2d636c692e7376673f6272616e63683d6d6173746572" alt="Tests"&gt;&lt;/a&gt;
&lt;a href="https://twitter.com/kumar_abhirup/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/f5c56fbd6a3bc617dc845d394184a64559ab7ec88baf90ec3003363cc1d1a55a/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f6b756d61725f616268697275702e7376673f7374796c653d736f6369616c266c6162656c3d406b756d61725f61626869727570" alt="Twitter"&gt;&lt;/a&gt;
&lt;a href="https://github.com/KumarAbhirup/bulk-mail-cli"&gt;&lt;img src="https://camo.githubusercontent.com/8b1cef14ee3f219753501a8c92da3d53de2bc2636ef2d9fb22a975affc14fc61/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f4b756d6172416268697275702f62756c6b2d6d61696c2d636c692e7376673f7374796c653d736f6369616c266c6162656c3d5374617273" alt="GitHub stars"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href="https://pkgreview.dev/npm/bulk-mail-cli" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/8c6beab519d94197c7f6ec4347aae5ad1f2e21eab344176e8f5abe589961b046/68747470733a2f2f696d672e736869656c64732e696f2f706b677265766965772f73746172732f6e706d2f62756c6b2d6d61696c2d636c693f6c6162656c3d706b677265766965772e6465762532305374617273267374796c653d666f722d7468652d6261646765" alt="pkgreview.dev Rating"&gt;&lt;/a&gt;
&lt;a href="https://pkgreview.dev/npm/bulk-mail-cli" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/b0f3a3f82c978168cae50e23a7a7db03af471c252bae92e8ac5df1d1791cc82f/68747470733a2f2f696d672e736869656c64732e696f2f706b677265766965772f726174696e672f6e706d2f62756c6b2d6d61696c2d636c693f6c6162656c3d706b677265766965772e646576253230526174696e67267374796c653d666f722d7468652d6261646765" alt="pkgreview.dev Rating"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;strong&gt;Like us a lot?&lt;/strong&gt; Help others know why you like us! &lt;strong&gt;Review this package on &lt;a href="https://pkgreview.dev/npm/bulk-mail-cli" rel="nofollow"&gt;pkgreview.dev&lt;/a&gt;&lt;/strong&gt;
&lt;/th&gt;
&lt;th&gt;➡&lt;/th&gt;
&lt;th&gt;&lt;a href="https://pkgreview.dev/npm/bulk-mail-cli" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/26819814f1c4f105306fe5fc60d004b8513d56b913f7fe4d2e7c011a9283ef75/68747470733a2f2f692e6962622e636f2f4d636a564d66622f706b677265766965772d6465762e6a7067" alt="Review us on pkgreview.dev"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;h1&gt;
📦 &lt;code&gt;bulk-mail-cli&lt;/code&gt;
&lt;/h1&gt;
&lt;h3&gt;
&lt;strong&gt;Do quick, hassle-free email marketing with this small but very powerful tool! 🔥&lt;/strong&gt;
&lt;/h3&gt;
&lt;h4&gt;
It sends automated, dynamic and beautifully designed HTML emails to your mailing list via your terminal! 😎
&lt;/h4&gt;
&lt;p&gt;Ever felt a quick need to shoot a fabulous mail to your subscribers? Without any inconvenience of creating complex campaigns with MailChimp and MailGun? Just open your terminal, input the CSV and HTML file with dynamic text, and just shoot the mails with &lt;strong&gt;bulk-mail-cli&lt;/strong&gt;!&lt;/p&gt;
&lt;h2&gt;
Features&lt;/h2&gt;
&lt;p&gt;💃    &lt;strong&gt;Active on Slack.&lt;/strong&gt; Join the &lt;a href="http://bit.ly/bulkmailcli" rel="nofollow"&gt;bulk-mail-cli Slack group&lt;/a&gt; for suggestions, bugs reports, support, and core development.&lt;/p&gt;
&lt;p&gt;📦    &lt;strong&gt;Shoot mails using CSV&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;📝    Mail &lt;strong&gt;dynamic HTML Templates&lt;/strong&gt; using the &lt;code&gt;{{fname|lname}}&lt;/code&gt; syntax.&lt;/p&gt;
&lt;p&gt;⏰    Set the sending &lt;strong&gt;interval time&lt;/strong&gt; in Cron Expressions! Eg. &lt;code&gt;*/10 * * * * *&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;📌    &lt;strong&gt;Unlimited attachments!&lt;/strong&gt; Attach any files on…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/adventmail/bulk-mail-cli"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;I just created &lt;a href="https://github.com/KumarAbhirup/bulk-mail-cli"&gt;bulk-mail-cli&lt;/a&gt; and this post demonstrates how and why I created it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  What is &lt;a href="https://github.com/KumarAbhirup/bulk-mail-cli"&gt;bulk-mail-cli&lt;/a&gt;?
&lt;/h1&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4IJWRa9I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/ENME_8DUwAAj15v.png" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--iISNvqah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1188475111172644865/0ZyV67Dw_normal.jpg" alt="Kumar Abhirup profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Kumar Abhirup
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @kumar_abhirup
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      I just made something awesome last week.&lt;br&gt;&lt;br&gt;Introducing bulk-mail-cli v2 ✨&lt;br&gt;&lt;br&gt;🔥 Do hassle-free email marketing with this powerful tool.&lt;br&gt;&lt;br&gt;It sends &lt;br&gt;...automated&lt;br&gt;...dynamic&lt;br&gt;...beautifully designed HTML emails &lt;br&gt;...to your mailing list via your terminal!&lt;br&gt;&lt;br&gt;New features in v2 🔥 &lt;br&gt;&lt;br&gt;1/n 👇 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      10:22 AM - 01 Jan 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1212318232561848321" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1212318232561848321" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1212318232561848321" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;



&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--iISNvqah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1188475111172644865/0ZyV67Dw_normal.jpg" alt="Kumar Abhirup profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Kumar Abhirup
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @kumar_abhirup
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Features...&lt;br&gt;&lt;br&gt;📦    Shoot mails using CSV.&lt;br&gt;&lt;br&gt;📝    Mail dynamic HTML Templates using the {{fname}} syntax.&lt;br&gt;&lt;br&gt;⏰    Set the sending interval time in Cron Expressions!&lt;br&gt;&lt;br&gt;📌    Unlimited email attachments!&lt;br&gt;&lt;br&gt;⛅️    Runs on any cloud server!&lt;br&gt;&lt;br&gt;2/n
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      10:22 AM - 01 Jan 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1212318235539861504" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1212318235539861504" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1212318235539861504" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;



&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wx7AwZhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/media/ENMFA45UcAAQiiY.jpg" alt="unknown tweet media content"&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--iISNvqah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1188475111172644865/0ZyV67Dw_normal.jpg" alt="Kumar Abhirup profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Kumar Abhirup
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        @kumar_abhirup
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      🔰    It saves your campaign progress!&lt;br&gt;&lt;br&gt;✨    Use .env variables to not hardcode credentials&lt;br&gt;&lt;br&gt;👨‍🏫    Contentful demo files provided! You get many beautiful email templates to pick from!&lt;br&gt;&lt;br&gt;𝔀    WordPress and other CMS' friendly.&lt;br&gt;&lt;br&gt;🧪    Tested on MacOS and Linux.&lt;br&gt;&lt;br&gt;🎉 OSS &amp;amp; Free&lt;br&gt;&lt;br&gt;3/n 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      10:22 AM - 01 Jan 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1212318247225155585" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1212318247225155585" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1212318247225155585" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;I hope the tweets above give a fair idea about what bulk-mail-cli is.&lt;/p&gt;

&lt;h1&gt;
  
  
  Journey
&lt;/h1&gt;

&lt;p&gt;Being a student, I wasn't able to afford MailChimp and MailGun. Also the fact that creating &lt;code&gt;bulk-mail-cli&lt;/code&gt; will do good to my portfolio. &lt;/p&gt;

&lt;p&gt;So, I created the tool by myself which has all the important features that MailChimp has. &lt;em&gt;Except the Mail Analytics feature. I am currently building it into the CLI.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I created v1 of &lt;code&gt;bulk-mail-cli&lt;/code&gt; in Jan 2019. &lt;a href="https://www.producthunt.com/posts/bulk-mail-cli"&gt;See on Product Hunt&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Since then, I got a decent number of people (20-25) to use it on a regular basis. &lt;/p&gt;

&lt;p&gt;I also got a lot of emails about suggestions to improve it.&lt;/p&gt;

&lt;p&gt;There were important features missing... &lt;/p&gt;

&lt;p&gt;Like for example, Configuration of time interval to wait for each consequent email to send.&lt;/p&gt;

&lt;p&gt;Also, there was no way to send attachments to the email list.&lt;/p&gt;

&lt;p&gt;Also, the CLI did not run on cloud servers. It is necessary that these CLI tools run on Cloud so that the tool usage can be automated by the users.&lt;/p&gt;

&lt;p&gt;Few feedbacks I received 👇&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/adventmail/bulk-mail-cli/issues/19#issuecomment-480658002"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#19&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/febr3s"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s---4Sxor01--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars1.githubusercontent.com/u/33102833%3Fu%3Dfeaa35f61078a7e3ae3b98008ed37703e9154a12%26v%3D4" alt="febr3s avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/febr3s"&gt;febr3s&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/adventmail/bulk-mail-cli/issues/19#issuecomment-480658002"&gt;&lt;time&gt;Apr 08, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Hi! This app's user experience is great! Although without the interval feature cannot be used for advanced purposes. I would like to know if you're still working on it, to figure out whether I switch to another app or wait for the update. I tried myself but it was a waste of time, I guess. My best.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/adventmail/bulk-mail-cli/issues/19#issuecomment-480658002"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/adventmail/bulk-mail-cli/issues/14#issuecomment-446464305"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#14&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/Suleman-Elahi"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--7lmmBogH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars0.githubusercontent.com/u/24384996%3Fu%3D90177099406421796e2d8e24676de0c6c925b25e%26v%3D4" alt="Suleman-Elahi avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/Suleman-Elahi"&gt;Suleman-Elahi&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/adventmail/bulk-mail-cli/issues/14#issuecomment-446464305"&gt;&lt;time&gt;Dec 12, 2018&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/24384996/49848285-77e5cb80-fdfa-11e8-90c1-c0830a71668d.png" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FeASzO4R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/24384996/49848285-77e5cb80-fdfa-11e8-90c1-c0830a71668d.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/adventmail/bulk-mail-cli/issues/14#issuecomment-446464305"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  And I started creating...
&lt;/h2&gt;

&lt;p&gt;I created the &lt;code&gt;v2&lt;/code&gt; in a week or two in my Highschool Xmas Vacations.&lt;/p&gt;

&lt;p&gt;In the meanwhile, I also shared what I learned about creating Command Line Apps in the below DEV posts.&lt;/p&gt;

&lt;p&gt;If you wanna learn how to create CLIs, the Starter Blogpost of mine might help :)&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;div class="ltag__link__content"&gt;
    &lt;div class="missing"&gt;
      &lt;h2&gt;Article No Longer Available&lt;/h2&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Now that the &lt;code&gt;v2&lt;/code&gt; is out... You can use it on everyday basis and you can also read all the code in &lt;a href="https://github.com/KumarAbhirup/bulk-mail-cli/"&gt;this GitHub Repository&lt;/a&gt;. The repository contains documentation about how to use it.&lt;/p&gt;

&lt;p&gt;Install &lt;code&gt;bulk-mail-cli&lt;/code&gt; 👉 &lt;code&gt;npm i -g bulk-mail-cli&lt;/code&gt; and type &lt;code&gt;bulkmail&lt;/code&gt; in the terminal for support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Features
&lt;/h1&gt;

&lt;p&gt;💃 &lt;strong&gt;Active on Slack.&lt;/strong&gt; Join the &lt;a href="http://bit.ly/bulkmailcli"&gt;bulk-mail-cli Slack group&lt;/a&gt; for suggestions, bugs reports, support, and core development.&lt;/p&gt;

&lt;p&gt;📦 &lt;strong&gt;Shoot mails using CSV&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;📝 Mail &lt;strong&gt;dynamic HTML Templates&lt;/strong&gt; using the &lt;code&gt;{{fname|lname}}&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;⏰ Set the sending &lt;strong&gt;interval time&lt;/strong&gt; in Cron Expressions! Eg. &lt;code&gt;*/10 * * * * *&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Unlimited attachments!&lt;/strong&gt; Attach any files on your local computer or you may just provide a direct URL in configuration and &lt;code&gt;bulk-mail-cli&lt;/code&gt; will download and send the attachment under dynamic filenames and pathnames.&lt;/p&gt;

&lt;p&gt;⛅️ &lt;strong&gt;Runs on cloud!&lt;/strong&gt; Can be run on AWS EC2 servers and on any Node.js droplet on DigitalOcean.&lt;/p&gt;

&lt;p&gt;🔰 &lt;strong&gt;It saves your campaign progress!&lt;/strong&gt; You can pause and resume the Mail Campaign from where you left the last time.&lt;/p&gt;

&lt;p&gt;✨ &lt;strong&gt;Use .env variables&lt;/strong&gt; to not hardcode the emails and passwords in configuration files.&lt;/p&gt;

&lt;p&gt;👨‍🏫 &lt;strong&gt;Contentful demo files provided!&lt;/strong&gt; You get many beautiful email templates to pick from!&lt;/p&gt;

&lt;p&gt;𝔀 &lt;strong&gt;WordPress and other CMS' friendly.&lt;/strong&gt; Just export the list of your users, change the email containing column name to &lt;code&gt;email&lt;/code&gt; and you are good to go!&lt;/p&gt;

&lt;p&gt;🧪 &lt;strong&gt;Tested on MacOS and Linux&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Technologies and Libraries used
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Nodemailer&lt;/li&gt;
&lt;li&gt;SimpleSmpt&lt;/li&gt;
&lt;li&gt;csvtojson&lt;/li&gt;
&lt;li&gt;ncp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The complete app is only based on &lt;a href="https://www.npmjs.com/package/nodemailer"&gt;nodemailer&lt;/a&gt; yet does so much!&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/KumarAbhirup/bulk-mail-cli/blob/master/src/cli/start.ts"&gt;This is the prime file that runs bulk-mail-cli&lt;/a&gt;. Please take time to read it and you'll understand how straight forward the process is, to create a CLI.&lt;/p&gt;




&lt;p&gt;Thank you for reading this post! &lt;/p&gt;

&lt;p&gt;Make sure you try out &lt;code&gt;bulk-mail-cli&lt;/code&gt;... If you spot bugs/errors, please DM me on &lt;a href="https://twitter.com/KumarAbhirup"&gt;Twitter (@kumar_abhirup)&lt;/a&gt;... The tool is tested on MacOS and Linux. If you are a Windows user, please let me know if things are working fine there!&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__"&gt;
  
    .ltag__user__id__ .follow-action-button {
      background-color: #19063A !important;
      color: #dce9f3 !important;
      border-color: #19063A !important;
    }
  
    &lt;div class="ltag__user__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b_Q_OnuL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--diPD5F8K--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://thepracticaldev.s3.amazonaws.com/i/99mvlsfu5tfj9m7ku25d.png" alt="[deleted user] image"&gt;
    &lt;/div&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;[Deleted User]&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  About me
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this article. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>Creating a command-line app in Node.js: Argument Parsing</title>
      <dc:creator>Kumar Abhirup</dc:creator>
      <pubDate>Sat, 28 Dec 2019 10:09:14 +0000</pubDate>
      <link>https://dev.to/kumareth/creating-a-command-line-app-in-node-js-argument-parsing-40ph</link>
      <guid>https://dev.to/kumareth/creating-a-command-line-app-in-node-js-argument-parsing-40ph</guid>
      <description>&lt;p&gt;This article is in the continuity of &lt;a href="https://dev.to/kumar_abhirup/a-starter-guide-to-create-a-command-line-app-in-node-js-41hn"&gt;part 1&lt;/a&gt;. So before you proceed, please make sure you have followed the steps in part 1. :)&lt;/p&gt;

&lt;p&gt;In Part 1, we learned about how a Node App can be run like it is a CLI. In this post, we will learn about &lt;strong&gt;Argument parsing in command-line app&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is &lt;code&gt;argument parsing&lt;/code&gt; in a CLI?
&lt;/h2&gt;

&lt;p&gt;If you have ever used CLIs like &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;yarn&lt;/code&gt;, you know you have to pass a &lt;code&gt;--flag&lt;/code&gt; as a suffix to the CLI command.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For eg. &lt;code&gt;npm install&lt;/code&gt;.&lt;/em&gt; Here, &lt;code&gt;install&lt;/code&gt; is an argument passed to the &lt;code&gt;npm&lt;/code&gt; command that tells Node Package Manager to install a package.&lt;/p&gt;

&lt;p&gt;In the same way, your CLI might need a different set of predefined arguments (also called 'parameters') to work properly. It is often used for doing different tasks and features in a CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Argument parsing in Node.js
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a file named &lt;code&gt;index.js&lt;/code&gt;...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the file, paste the below code.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now, in the terminal, run the following command to get the given output.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;node index.js wow this is an argument

&lt;span class="c"&gt;# Output 👇&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'node'&lt;/span&gt;,
  &lt;span class="s1"&gt;'/home/username/Desktop/index.js'&lt;/span&gt;,
  &lt;span class="s1"&gt;'wow'&lt;/span&gt;,
  &lt;span class="s1"&gt;'this'&lt;/span&gt;,
  &lt;span class="s1"&gt;'is'&lt;/span&gt;,
  &lt;span class="s1"&gt;'an'&lt;/span&gt;,
  &lt;span class="s1"&gt;'argument'&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now, you can use the output you get to detect what argument is passed and you can make your CLI behave accordingly.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Argument Parsing
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;process.argv&lt;/code&gt; is the very fundamental line of code to know what argument is being passed.&lt;/p&gt;

&lt;p&gt;In a CLI, you'll have to make users use a combination of commands to do certain things. &lt;em&gt;For eg. &lt;code&gt;npm install -g bulk-mail-cli&lt;/code&gt;.&lt;/em&gt; Here, &lt;code&gt;install&lt;/code&gt; is passed as an argument and &lt;code&gt;-g&lt;/code&gt; (&lt;code&gt;--global&lt;/code&gt;) as a flag.&lt;/p&gt;

&lt;p&gt;Computing what all the combinations will do in a CLI can be a hefty task. Therefore, it is recommended that you use &lt;strong&gt;tried and tested libraries for argument parsing and its detection.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries to parse arguments and flags.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/commander"&gt;Commander&lt;/a&gt; (I recommend this)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/minimist"&gt;Minimist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/sindresorhus/meow"&gt;Meow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Commander
&lt;/h2&gt;

&lt;p&gt;Let us see how &lt;code&gt;Commander&lt;/code&gt; works. In Part 1, we created a demo CLI project. Continue coding in the &lt;code&gt;index.js&lt;/code&gt; of the same coding project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The tutorial below will be relevant only if you have read Part 1 of the series.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Define the module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commander&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commander&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use it in your program, paste the following code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;commander&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v0.0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a dummy demo CLI.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-n, --name &amp;lt;type&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;To input a name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;To output demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above lines of code will now help you parse and read the &lt;code&gt;--version&lt;/code&gt;, &lt;code&gt;-n&lt;/code&gt;, &lt;code&gt;--name&lt;/code&gt;, &lt;code&gt;demo&lt;/code&gt; arguments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reading the arguments
&lt;/h3&gt;

&lt;p&gt;To read the argument, you now have to simply do the following...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Runs only if `name` argument is passed with a `&amp;lt;type&amp;gt;`...&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commander&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Your name is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;commander&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Runs only if `demo` argument is passed...&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commander&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`This is a DEMO.`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it out!
&lt;/h2&gt;

&lt;p&gt;If you have continued from Part 1, then you have a &lt;code&gt;package.json&lt;/code&gt; already created. &lt;code&gt;cd&lt;/code&gt; in the directory where your code is stored and run the following in the terminal...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;thisDemoCli demo
This is a DEMO.

&lt;span class="nv"&gt;$ &lt;/span&gt;thisDemoCli &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"Kumar Abhirup"&lt;/span&gt;
Your name is Kumar Abhirup.

&lt;span class="nv"&gt;$ &lt;/span&gt;thisDemoCli &lt;span class="nt"&gt;--version&lt;/span&gt;
v0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Hooray! Now you are successfully parsing the arguments and doing something with it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I hope this article helps you understand the fundamentals of how a Command-Line app works in Node.js.&lt;/p&gt;




&lt;h1&gt;
  
  
  About me
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;I am Kumar Abhirup, a 16-year-old JavaScript React developer from India who keeps learning a new thing every single day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kumar_abhirup"&gt;Connect with me on Twitter 🐦&lt;/a&gt;&lt;br&gt;
&lt;a href="https://kumar.now.sh"&gt;My personal website and portfolio 🖥️&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Comment below your better ways, and suggestions to improve this article. :)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>npm</category>
      <category>node</category>
    </item>
  </channel>
</rss>
