{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/2","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Securing your web applications from unauthorized users is very important. You can increase the security with One Time Password (OTP…","fields":{"slug":"/engineering/guest-post/multi-factor-authentication-using-redis-cache-and-otp/"},"html":"<p>Securing your web applications from unauthorized users is very important. You can increase the security with One Time Password (OTP) authentication in addition to the login credentials. An OTP is sent to the user’s email when they want to log in. This is a form of <a href=\"https://www.loginradius.com/blog/identity/what-is-multi-factor-authentication/\">multi-factor authentication (MFA)</a>.</p>\n<p>It is essential to learn how to apply Multi-Factor authentication in real-world applications, and this tutorial got you covered. This tutorial explains how to store users’ sessions in the Redis Store and send OTP using <a href=\"https://www.npmjs.com/package/nodemailer\">Nodemailer</a> for authentication.</p>\n<h2 id=\"goal\" style=\"position:relative;\"><a href=\"#goal\" aria-label=\"goal permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Goal</h2>\n<p>This tutorial helps you understand:</p>\n<ul>\n<li>What is Redis?</li>\n<li>How to utilize the Redis Store?</li>\n<li>How to set up an SMTP service using Nodemailer?</li>\n<li>How to protect routes?</li>\n</ul>\n<h2 id=\"prerequisites\" style=\"position:relative;\"><a href=\"#prerequisites\" aria-label=\"prerequisites permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Prerequisites</h2>\n<p>To follow this tutorial, make sure you have:</p>\n<ul>\n<li><a href=\"https://nodejs.org/en/download/\">Node Version 16.0+</a></li>\n<li>Basic knowledge of Node.js</li>\n<li>A Text Editor, preferably <a href=\"https://code.visualstudio.com/download\">Visual Studio Code</a></li>\n</ul>\n<p>As everything is in place, let’s jump right in.</p>\n<h2 id=\"set-up-the-server\" style=\"position:relative;\"><a href=\"#set-up-the-server\" aria-label=\"set up the server permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Set Up the Server</h2>\n<p>In this section, you will learn how to start an Express server.</p>\n<ol>\n<li>Create a new folder and open it in a text editor. In this tutorial, this folder is named <code>Multi-Factor Auth</code>, but you can decide to call it anything you want.</li>\n<li>\n<p>Open the terminal in the project’s path and run the following code to install the dependencies needed to start the Express server.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm init --y</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">npm i express</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">npm i -D nodemon</span></span></code></pre>\n<p>The Express dependency will be used to set up the backend server and nodemon, installed as a devDependency, which will watch the file system and restart the server when a change is made.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 748px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50.46153846153846%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAcqJYB//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAEFAl//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAWEAEBAQAAAAAAAAAAAAAAAAAQATH/2gAIAQEAAT8hbj//2gAMAwEAAgADAAAAEK8//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAAICAwAAAAAAAAAAAAAAAQAhEFERMZH/2gAIAQEAAT8QSuom08lbieWf/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Express and Nodemon Installation\"\n        title=\"Express and Nodemon Installation\"\n        src=\"/static/fdc242e8fe1904ee4b79a43cc2dd035b/2551b/express-and-nodemon-install.jpg\"\n        srcset=\"/static/fdc242e8fe1904ee4b79a43cc2dd035b/6aca1/express-and-nodemon-install.jpg 650w,\n/static/fdc242e8fe1904ee4b79a43cc2dd035b/2551b/express-and-nodemon-install.jpg 748w\"\n        sizes=\"(max-width: 748px) 100vw, 748px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>Create a new file named <code>server.js</code> in the project’s directory. For simplicity, this file will contain all the server code for this application.</li>\n<li>\n<p>Add the following codes in the <code>server.js</code> file to set up an Express server to listen on port <code>5000</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">express</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;express&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">express</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">PORT</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">5000</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">(</span><span class=\"mtk12\">PORT</span><span class=\"mtk1\">, () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">`Server running on port </span><span class=\"mtk4\">${</span><span class=\"mtk12\">PORT</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n</li>\n<li>\n<p>Open <code>package.json</code> and add the following code to start the server.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"json\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;name&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;multi-factor-auth&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;version&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;1.0.0&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;description&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;main&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;server.js&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;scripts&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;start&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;node server.js&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;dev&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;nodemon server.js&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;keywords&quot;</span><span class=\"mtk1\">: [],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;author&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;license&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;ISC&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;dependencies&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;express&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;^4.18.1&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">&quot;devDependencies&quot;</span><span class=\"mtk1\">: {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">&quot;nodemon&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;^2.0.16&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n</li>\n<li>\n<p>Start the server in development mode by running <code>npm run dev</code> in your terminal.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 458px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.47161572052402%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHlzpKQK//EABYQAAMAAAAAAAAAAAAAAAAAAAEQIP/aAAgBAQABBQKCv//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABgQAQEAAwAAAAAAAAAAAAAAAAEQABFh/9oACAEBAAE/IU5mmNf/2gAMAwEAAgADAAAAEM8//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Qp//EABkQAQADAQEAAAAAAAAAAAAAAAEAETFBgf/aAAgBAQABPxBbqj3WPYD2JU6jQKZuz//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Express server\"\n        title=\"Express server\"\n        src=\"/static/5db0c94a42c2f52c79bad8de25e9ea6e/f7c3c/npm-run-dev.jpg\"\n        srcset=\"/static/5db0c94a42c2f52c79bad8de25e9ea6e/f7c3c/npm-run-dev.jpg 458w\"\n        sizes=\"(max-width: 458px) 100vw, 458px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n</ol>\n<h2 id=\"set-up-nodemailer\" style=\"position:relative;\"><a href=\"#set-up-nodemailer\" aria-label=\"set up nodemailer permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Set Up Nodemailer</h2>\n<p><a href=\"https://www.npmjs.com/package/nodemailer\">Nodemailer</a> is a Node.js module that allows you to send emails using an email service or an <a href=\"https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol\">SMTP</a> server.</p>\n<p>To set up Nodemailer, you need to provide your email or SMTP service credentials.</p>\n<blockquote>\n<p>Google mailing service (Gmail) will not support the use of third-party apps or devices like Nodemailer starting from May 30, 2022.</p>\n</blockquote>\n<p>For this tutorial, we will use Microsoft’s <a href=\"https://outlook.live.com/\">Outlook Maling Service</a> to send emails.</p>\n<h3 id=\"set-up-outlook\" style=\"position:relative;\"><a href=\"#set-up-outlook\" aria-label=\"set up outlook permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Set Up Outlook</h3>\n<ol>\n<li>Navigate to <a href=\"https://outlook.live.com/owa/?nlp=1&#x26;signup=1\">Outlook’s sign-up page</a> to register for an Outlook account if you don’t have one.</li>\n<li>\n<p>Add your phone number if you are prompted to do so. </p>\n<blockquote>\n<p>This step can be skipped.</p>\n</blockquote>\n</li>\n</ol>\n<h3 id=\"sending-emails\" style=\"position:relative;\"><a href=\"#sending-emails\" aria-label=\"sending emails permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Sending Emails</h3>\n<p>After setting up your Outlook account, the next step is to use your Outlook account’s credential to send emails through Nodemailer.</p>\n<ol>\n<li>\n<p>Open your terminal and install the <code>nodejs-nodemailer-outlook</code> dependency.</p>\n<p>This module only needs your Outlook account credentials and message to send emails.</p>\n<p>Now, run the code below in your terminal to install the <code>nodejs-nodemailer-outlook</code> dependency:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm i nodejs-nodemailer-outlook</span></span></code></pre>\n</li>\n<li>\n<p>Import the <code>nodejs-nodemailer-outlook</code> module into <code>server.js</code> and add the configurations needed to send emails:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">express</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;express&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">express</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">express</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">());</span><span class=\"mtk3\">//Enabling the body attribute.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">PORT</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">5000</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Post request to &#39;http://localhost:3000&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">nodeoutlook</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;nodejs-nodemailer-outlook&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Importing the module</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">nodeoutlook</span><span class=\"mtk1\">.</span><span class=\"mtk11\">sendEmail</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">auth:</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Outlook Account Credentials </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">user:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookEmail@outlook.com&gt;&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">pass:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookPassword&gt;&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Password</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">from:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookEmail@outlook.com&gt;&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">to:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">email</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Getting the email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">subject:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;OTP&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">text:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Getting the Message</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">onError</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">500</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`an error occurred </span><span class=\"mtk4\">${</span><span class=\"mtk12\">e</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\"> }),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">onSuccess</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">i</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">200</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> }),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">(</span><span class=\"mtk12\">PORT</span><span class=\"mtk1\">, () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">`Server running on port </span><span class=\"mtk4\">${</span><span class=\"mtk12\">PORT</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n</li>\n<li>\n<p>To test the application, use an API testing application like <a href=\"https://www.postman.com/\">Postman</a> and make a POST request to <code>http://localhost:5000/auth</code>, passing <code>email</code> and <code>message</code> to the body of the request.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAECAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHddchiD//EABYQAQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAQABBQLaqv/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABgQAQEBAQEAAAAAAAAAAAAAAAEAERAh/9oACAEBAAE/ITOAHgZCtWr/2gAMAwEAAgADAAAAEMsP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHBABAAIBBQAAAAAAAAAAAAAAAQARITFBUWGh/9oACAEBAAE/EAqb8lHEHBA2CoJErJBjQnUT/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Postman\"\n        title=\"Postman\"\n        src=\"/static/4197cef78cd8c610043170be62153b11/212bf/postman.jpg\"\n        srcset=\"/static/4197cef78cd8c610043170be62153b11/6aca1/postman.jpg 650w,\n/static/4197cef78cd8c610043170be62153b11/212bf/postman.jpg 768w,\n/static/4197cef78cd8c610043170be62153b11/6c0a0/postman.jpg 1062w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n</ol>\n<h2 id=\"generate-otps\" style=\"position:relative;\"><a href=\"#generate-otps\" aria-label=\"generate otps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Generate OTPs</h2>\n<p>In the previous section, you've successfully configured Nodemailer and used it to send emails. This section will show you how to generate a random number and how to add this random number to the message sent to the user.</p>\n<p>You can generate this random number using: </p>\n<ol>\n<li><code>Math.trunc(Math.random() * 1000000)</code></li>\n<li>A NodeJS module like <em>UUID, shortid, nanoid</em>, etc.</li>\n</ol>\n<p>This tutorial uses the <code>nanoid</code> module to generate random numbers.</p>\n<ol>\n<li>\n<p>In the terminal, install the <code>nanoid</code> module. This module will create a random set of characters as the OTP. Run the following command in your terminal:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm i nanoid@3.3.4 </span><span class=\"mtk3\">#Version compatible with Nodejs</span></span></code></pre>\n</li>\n<li>\n<p>After installing the <code>nanoid</code> module, import it into <code>server.js</code> and use it to generate six random digits.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">nanoid</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;nanoid&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Importing the naonid module</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">nanoid</span><span class=\"mtk1\">.</span><span class=\"mtk11\">customAlphabet</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;1234567890&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">6</span><span class=\"mtk1\">)();</span><span class=\"mtk3\">//Generating </span></span></code></pre>\n</li>\n<li>\n<p>Add the OTP to the message sent to the user’s email.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">express</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;express&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">nanoid</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;nanoid&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">express</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span><span class=\"mtk12\">express</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">PORT</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">5000</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">nanoid</span><span class=\"mtk1\">.</span><span class=\"mtk11\">customAlphabet</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;1234567890&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">6</span><span class=\"mtk1\">)();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">nodeoutlook</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;nodejs-nodemailer-outlook&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">nodeoutlook</span><span class=\"mtk1\">.</span><span class=\"mtk11\">sendEmail</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">auth:</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Outlook Account Credentials </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">user:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookEmail@outlook.com&gt;&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">pass:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookPassword&gt;&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Password</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">from:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookEmail@outlook.com&gt;&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">to:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">email</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Getting the email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">subject:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;OTP&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">text:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`Your One Time Password is </span><span class=\"mtk4\">${</span><span class=\"mtk12\">OTP</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Adding the OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">onError</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">500</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`an error occurred </span><span class=\"mtk4\">${</span><span class=\"mtk12\">e</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\"> }),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">onSuccess</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">i</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">200</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> }),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">listen</span><span class=\"mtk1\">(</span><span class=\"mtk12\">PORT</span><span class=\"mtk1\">, () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">`Server running on port </span><span class=\"mtk4\">${</span><span class=\"mtk12\">PORT</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n</li>\n<li>\n<p>Make a POST request to <code>http://localhost:5000/auth</code>, passing only the email address.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAMABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAIBAwX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHdmphhQ//EABYQAQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAQABBQLaqv/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABgQAQEBAQEAAAAAAAAAAAAAAAEAERAh/9oACAEBAAE/ITOAHgZDt27/2gAMAwEAAgADAAAAEPPP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxABAQACAwEAAAAAAAAAAAAAAQARUSExQWH/2gAIAQEAAT8QCxuwahwYPAxARA5IQ6L4F//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Email test\"\n        title=\"Email test\"\n        src=\"/static/cd5632b95fa43c22a5c5b859f3c7e34a/212bf/email-test.jpg\"\n        srcset=\"/static/cd5632b95fa43c22a5c5b859f3c7e34a/6aca1/email-test.jpg 650w,\n/static/cd5632b95fa43c22a5c5b859f3c7e34a/212bf/email-test.jpg 768w,\n/static/cd5632b95fa43c22a5c5b859f3c7e34a/97cd8/email-test.jpg 1060w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>\n<p>Check the email address for which the OTP is sent.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 47.84615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIBBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAe7WiVD/xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAEFAl//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAYEAACAwAAAAAAAAAAAAAAAAABEBEgIf/aAAgBAQABPyEStp//2gAMAwEAAgADAAAAEIMP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGhABAAEFAAAAAAAAAAAAAAAAAQARICFx8P/aAAgBAQABPxABySrxNLP/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Gmail\"\n        title=\"Gmail\"\n        src=\"/static/1f422b3c7377a14d799ddd3304c82514/212bf/gmail.jpg\"\n        srcset=\"/static/1f422b3c7377a14d799ddd3304c82514/6aca1/gmail.jpg 650w,\n/static/1f422b3c7377a14d799ddd3304c82514/212bf/gmail.jpg 768w,\n/static/1f422b3c7377a14d799ddd3304c82514/4cc1c/gmail.jpg 1069w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n</ol>\n<h2 id=\"redis\" style=\"position:relative;\"><a href=\"#redis\" aria-label=\"redis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Redis</h2>\n<p>Now that the OTP part of the authentication is settled, let’s set up the next part of the authentication. This section covers what Redis is and how to use the Redis Store to cache data.</p>\n<h3 id=\"what-is-redis\" style=\"position:relative;\"><a href=\"#what-is-redis\" aria-label=\"what is redis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Redis?</h3>\n<p><a href=\"https://redis.io\">Redis</a>, also known as Remote Dictionary Server, is an open-source (BSD licensed), in-memory data structure store. Developers use it as a database, cache, and message broker. It is a fast, lightweight database that structures data in key-value pairs.</p>\n<h3 id=\"redis-cache\" style=\"position:relative;\"><a href=\"#redis-cache\" aria-label=\"redis cache permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Redis Cache</h3>\n<p>Storing and retrieving cached data from Redis is faster than traditional databases as it retrieves and stores data in the main memory (the RAM). The data can be users’ sessions or responses to requests.</p>\n<p>The only downside is that data can be lost if the computer crashes.</p>\n<h3 id=\"setting-up-redis\" style=\"position:relative;\"><a href=\"#setting-up-redis\" aria-label=\"setting up redis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up Redis</h3>\n<p>Setting up Redis locally for Linux and Mac computers is simply straightforward.</p>\n<p>Follow the official documentation for <a href=\"https://redis.io/docs/getting-started/installation/install-redis-on-linux/\">Linux</a> and <a href=\"https://redis.io/docs/getting-started/installation/install-redis-on-mac-os/\">macOS</a></p>\n<p>For <a href=\"https://redis.io/docs/getting-started/installation/install-redis-on-windows/\">Windows</a>, you need to install <a href=\"https://learn.microsoft.com/en-us/windows/wsl/install\">Windows Subsystem for Linux</a> Version 2 (WSL 2) and a <a href=\"https://docs.microsoft.com/en-us/windows/wsl/install-manual#downloading-distributions\">Linux Distro</a> on your local machine.</p>\n<p>This tutorial uses <a href=\"https://redis.com/\">Redis Cloud</a> to set up the Redis database. Redis Cloud starts with <em>Free</em> a subscription fee that grants 30MB of storage. This is perfect for this simple application.</p>\n<ol>\n<li>\n<p>Create a new Redis Cloud account if you don’t have one.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 63.69230769230769%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHtaSSgv//EABgQAAIDAAAAAAAAAAAAAAAAABARAAEC/9oACAEBAAEFAipeWP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABcQAAMBAAAAAAAAAAAAAAAAABAgQZH/2gAIAQEABj8CS6P/xAAaEAACAgMAAAAAAAAAAAAAAAABERAgIVGR/9oACAEBAAE/Ic7oAr4IR//aAAwDAQACAAMAAAAQT8//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAcEAEAAQQDAAAAAAAAAAAAAAABABARQVEhcfH/2gAIAQEAAT8QG7TUFvhnOZ2jSQQ8hp//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Redis Cloud Set Up\"\n        title=\"Redis Cloud Set Up\"\n        src=\"/static/f07076f26865c6b41d8c47e6fa803a99/212bf/redis-cloud-sign-in.jpg\"\n        srcset=\"/static/f07076f26865c6b41d8c47e6fa803a99/6aca1/redis-cloud-sign-in.jpg 650w,\n/static/f07076f26865c6b41d8c47e6fa803a99/212bf/redis-cloud-sign-in.jpg 768w,\n/static/f07076f26865c6b41d8c47e6fa803a99/29b94/redis-cloud-sign-in.jpg 897w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>Click on <strong>Let’s start free</strong> and let Redis create a cloud database.</li>\n<li>\n<p>Click on <strong>Configurations</strong> and copy your <strong>Public endpoint.</strong> This endpoint will be used to set up the Redis application.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 40.92307692307692%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQL/2gAMAwEAAhADEAAAAd2Agz//xAAXEAEBAQEAAAAAAAAAAAAAAAAAEQEh/9oACAEBAAEFAo4mP//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAEDAQE/AQn/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAY/An//xAAZEAACAwEAAAAAAAAAAAAAAAAAAREhMZH/2gAIAQEAAT8haQJ4vhdmn//aAAwDAQACAAMAAAAQ/wD/AP/EABYRAQEBAAAAAAAAAAAAAAAAAAEQEf/aAAgBAwEBPxAHZ//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxC1r//EABkQAQEBAQEBAAAAAAAAAAAAAAERACFRYf/aAAgBAQABPxBgJzVgfB1kkxVX67//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Public endpoint\"\n        title=\"Public endpoint\"\n        src=\"/static/c1d2a98a8779a290bd8d1cc075bd0354/212bf/fredrick-free-db.jpg\"\n        srcset=\"/static/c1d2a98a8779a290bd8d1cc075bd0354/6aca1/fredrick-free-db.jpg 650w,\n/static/c1d2a98a8779a290bd8d1cc075bd0354/212bf/fredrick-free-db.jpg 768w,\n/static/c1d2a98a8779a290bd8d1cc075bd0354/6533e/fredrick-free-db.jpg 1160w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>\n<p>Still on the <strong>Configurations</strong> tab, copy your <strong>Default user password</strong>.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 64.46153846153845%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdyghZP/xAAWEAEBAQAAAAAAAAAAAAAAAAARECD/2gAIAQEAAQUCIY//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAQIEH/2gAIAQEABj8CFT//xAAZEAADAAMAAAAAAAAAAAAAAAAAAREgQZH/2gAIAQEAAT8hTW1kFO+sP//aAAwDAQACAAMAAAAQsz//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPxBX/8QAGRAAAwEBAQAAAAAAAAAAAAAAAAERIWFB/9oACAEBAAE/EEmq54Uadq7rsVW0vBn/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Password\"\n        title=\"Password\"\n        src=\"/static/11d8dcde84b28d38b3d116f22e6b71e0/212bf/password.jpg\"\n        srcset=\"/static/11d8dcde84b28d38b3d116f22e6b71e0/6aca1/password.jpg 650w,\n/static/11d8dcde84b28d38b3d116f22e6b71e0/212bf/password.jpg 768w,\n/static/11d8dcde84b28d38b3d116f22e6b71e0/fc6fd/password.jpg 902w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n<li>\n<p>Run <code>npm i redis</code> in your terminal. Import the <code>redis</code> dependency into <code>server.js</code>, and set up the <code>redisClient</code> using the <strong>Redis cloud endpoint</strong>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redis</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;redis&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">redisConnect</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//This function will be removed later in the tutorial</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">try</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redisClient</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">redis</span><span class=\"mtk1\">.</span><span class=\"mtk11\">createClient</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">url:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;redis://redis-12345.c80.us-east-1-2.ec2.cloud.redislabs.com:12345&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">//This is an incorrect end point, insert your Public endpoint</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">port:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">12345</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//The PORT is the last five digits in the url</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">username:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;default&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">password:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;1234567890ABCDEFGHIJKLMNOPQRSTUV&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Input your Default_user_password</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redisClient</span><span class=\"mtk1\">.</span><span class=\"mtk11\">connect</span><span class=\"mtk1\">();</span><span class=\"mtk3\">//Connecting to Redis Cloud</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redisClient</span><span class=\"mtk1\">.</span><span class=\"mtk11\">set</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Hello&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Hello from LoginRadius&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//key=Hello, value=Hello from LoginRadius</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Hello</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redisClient</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Hello&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Getting the value using its key=Hello</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Hello</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  } </span><span class=\"mtk15\">catch</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">error</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk3\">//Running the function again when there is a network error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">error</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\"> ===</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;getaddrinfo ENOTFOUND redis-12345.c80.us-east-1-2.ec2.cloud.redislabs.com:12345&quot;</span><span class=\"mtk1\"> ||</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">error</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\"> ===</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;getaddrinfo EAI_AGAIN redis-12345.c80.us-east-1-2.ec2.cloud.redislabs.com&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk11\">redisConnect</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n</li>\n<li>\n<p>Start up the server in your terminal and view the result.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 483px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 50.103519668737064%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMBAgX/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABy6sXZAB//8QAFxAAAwEAAAAAAAAAAAAAAAAAAAEQEf/aAAgBAQABBQIyuf/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABcQAAMBAAAAAAAAAAAAAAAAAAAQETH/2gAIAQEAAT8hhT0v/9oADAMBAAIAAwAAABDkP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABwQAQACAQUAAAAAAAAAAAAAAAEAIREQQVFhcf/aAAgBAQABPxBqFNdx4A8iYcQDLUdzbT//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Redis Test\"\n        title=\"Redis Test\"\n        src=\"/static/96be8c30a6963a15c31fd105503b3652/aaf15/redis-test.jpg\"\n        srcset=\"/static/96be8c30a6963a15c31fd105503b3652/aaf15/redis-test.jpg 483w\"\n        sizes=\"(max-width: 483px) 100vw, 483px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n</ol>\n<h2 id=\"sessions\" style=\"position:relative;\"><a href=\"#sessions\" aria-label=\"sessions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Sessions</h2>\n<p>Now that Redis has been added to the application, let’s set up users’ sessions using <em>Express Sessions</em>.</p>\n<h3 id=\"set-up-express-sessions\" style=\"position:relative;\"><a href=\"#set-up-express-sessions\" aria-label=\"set up express sessions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Set Up Express Sessions</h3>\n<ol>\n<li>\n<p>Install the <code>express-session</code> and <code>connect-redis</code> modules in your terminal.</p>\n<p>The <code>express-session</code> module allows you to create <a href=\"https://www.loginradius.com/blog/engineering/guest-post/local-storage-vs-session-storage-vs-cookies/\">a session in the client’s browser</a>. And the <code>connect-redis</code> module enables you to set Redis as the session store. Run the following command in your terminal.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm i express-session connect-redis</span></span></code></pre>\n</li>\n<li>\n<p>Import <code>express-session</code> and <code>connect-redis</code> into <code>server.js</code> and configure the session store.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">express</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;express&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">app</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">express</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redis</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;redis&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">session</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;express-session&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Importing express session</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">RedisStore</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;connect-redis&quot;</span><span class=\"mtk1\">)(</span><span class=\"mtk12\">session</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Importing connect-redis and passing the session</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redisClient</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">redis</span><span class=\"mtk1\">.</span><span class=\"mtk11\">createClient</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">url:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;redis://redis-12345.c80.us-east-1-2.ec2.cloud.redislabs.com:12345&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk3\">//This is an incorrect end point, insert your Public endpoint</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">port:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">12345</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//The PORT is the last five digits in the url</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">username:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;default&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">password:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;1234567890ABCDEFGHIJKLMNOPQRSTUV&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Input your Default_user_password</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">legacyMode:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">true</span><span class=\"mtk1\">, </span><span class=\"mtk3\">//Very important for Redis V4</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">redisClient</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">connect</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;connected&quot;</span><span class=\"mtk1\">))</span><span class=\"mtk3\">//Logs out connected on successful</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">((</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\">));</span><span class=\"mtk3\">//Logs out the error</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">use</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">session</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">secret:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;LoginRadius&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//session secret key</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">resave:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">false</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">saveUninitialized:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">false</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">store:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">RedisStore</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">client:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">redisClient</span><span class=\"mtk1\"> }),</span><span class=\"mtk3\">//Setting the store</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//The Rest of the code</span></span></code></pre>\n</li>\n</ol>\n<h3 id=\"storing-otps\" style=\"position:relative;\"><a href=\"#storing-otps\" aria-label=\"storing otps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Storing OTPs</h3>\n<p>Attributes stored in a session without a database are removed after the server refreshes. With the help of Redis cache, attributes in a session can be retrieved fast and saved even when the server restarts.</p>\n<p>The user’s OTP should be saved in the session before sending it to the user’s email.</p>\n<p>Open your <code>server.js</code> file and add the code as follows.</p>\n<p>The following code stores the OTP in the session, redirects when the email has been sent, and verifies the OTP provided with the one stored in the session.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">nanoid</span><span class=\"mtk1\">.</span><span class=\"mtk11\">customAlphabet</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;1234567890&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">6</span><span class=\"mtk1\">)();</span><span class=\"mtk3\">//Changing the OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">session</span><span class=\"mtk1\">.</span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\">;</span><span class=\"mtk3\">//Storing the OTP in the </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">nodeoutlook</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;nodejs-nodemailer-outlook&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">nnodeoutlook</span><span class=\"mtk1\">.</span><span class=\"mtk11\">sendEmail</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">auth:</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Outlook Account Credentials </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">user:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookEmail@outlook.com&gt;&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">pass:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookPassword&gt;&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Password</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">from:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;&lt;yourOutlookEmail@outlook.com&gt;&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">to:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\">.</span><span class=\"mtk12\">email</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Getting the email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">subject:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;OTP&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">text:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`Your One Time Password is </span><span class=\"mtk4\">${</span><span class=\"mtk12\">OTP</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">onError</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">500</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`an error occurred </span><span class=\"mtk4\">${</span><span class=\"mtk12\">e</span><span class=\"mtk4\">}</span><span class=\"mtk8\">, Please try again`</span><span class=\"mtk1\"> }),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">onSuccess</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">i</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">redirect</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/verify&quot;</span><span class=\"mtk1\">),</span><span class=\"mtk3\">//Redirecting the user to verify the token</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/verify&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">send</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Welcome to the verify route&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Welcome Message</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">session</span><span class=\"mtk1\">.</span><span class=\"mtk12\">OTP</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Logging out the OTP stored in the session.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/verify&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> } = </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk1\">;</span><span class=\"mtk3\">//Getting the user provided OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">OTPSession</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">session</span><span class=\"mtk1\">.</span><span class=\"mtk12\">OTP</span><span class=\"mtk1\">;</span><span class=\"mtk3\">//Getting the stored OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">OTPSession</span><span class=\"mtk1\">) {</span><span class=\"mtk3\">//Checking if the OTP exist in the session</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> === </span><span class=\"mtk12\">OTPSession</span><span class=\"mtk1\">) {</span><span class=\"mtk3\">//Verifying the similarity of the OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">session</span><span class=\"mtk1\">.</span><span class=\"mtk12\">isAuth</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span><span class=\"mtk3\">//Setting auth to true</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">200</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;OTP is correct&quot;</span><span class=\"mtk1\"> });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">401</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Incorrect OTP&quot;</span><span class=\"mtk1\"> });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">status</span><span class=\"mtk1\">(</span><span class=\"mtk7\">404</span><span class=\"mtk1\">).</span><span class=\"mtk11\">json</span><span class=\"mtk1\">({ </span><span class=\"mtk12\">message:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;OTP not found&quot;</span><span class=\"mtk1\"> });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<h2 id=\"protecting-routes\" style=\"position:relative;\"><a href=\"#protecting-routes\" aria-label=\"protecting routes permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Protecting Routes</h2>\n<p>Preventing unauthorized/unauthenticated users from accessing a specific route or a piece of important information is essential in various applications. In this section, you'll learn how to create a middleware that will authenticate the users accessing a specific route.</p>\n<blockquote>\n<p>In this tutorial, the protected route is <code>/home</code></p>\n</blockquote>\n<ol>\n<li>\n<p>Create a <code>GET</code> route to <code>/home</code> in <code>server.js</code> and add the middleware <code>auth</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/home&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">auth</span><span class=\"mtk1\"> , (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">send</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;You have Successfully been Authenticated&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n</li>\n<li>\n<p>Create the <code>auth</code> middleware function and verify if the user is authenticated.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">auth</span><span class=\"mtk1\"> = (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">, </span><span class=\"mtk12\">next</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//auth middleware function</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">session</span><span class=\"mtk1\">.</span><span class=\"mtk12\">isAuth</span><span class=\"mtk1\">) {</span><span class=\"mtk3\">//Checking if `isAuth` = true</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk11\">next</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">redirect</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Redirecting the Login route</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Login route</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">send</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Login&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/home&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">auth</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//The Home route</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">send</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;You have Successfully been Authenticated&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n</li>\n</ol>\n<h3 id=\"logout\" style=\"position:relative;\"><a href=\"#logout\" aria-label=\"logout permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Logout</h3>\n<p>The logout route will also be protected using the <code>auth</code> middleware to prevent requests from users who are not signed in.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/logout&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">auth</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">req</span><span class=\"mtk1\">.</span><span class=\"mtk12\">session</span><span class=\"mtk1\">.</span><span class=\"mtk11\">destroy</span><span class=\"mtk1\">();</span><span class=\"mtk3\">//Destroying the session</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">redirect</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<h2 id=\"set-up-the-frontend\" style=\"position:relative;\"><a href=\"#set-up-the-frontend\" aria-label=\"set up the frontend permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Set Up the Frontend</h2>\n<p>It’s time to put the backend code into actual functionality. This tutorial makes use of <a href=\"https://ejs.co/\">Embedded JavaScript Template (EJS)</a> as the frontend of this application.</p>\n<h3 id=\"setting-up-ejs\" style=\"position:relative;\"><a href=\"#setting-up-ejs\" aria-label=\"setting up ejs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting up EJS</h3>\n<ol>\n<li>\n<p>Install the EJS Module</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"bash\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm i ejs</span></span></code></pre>\n</li>\n<li>\n<p>Once the installation is complete, open your <code>server.js</code> and use <code>ejs</code> as the default view engine</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">set</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;view engine&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;ejs&quot;</span><span class=\"mtk1\">)</span></span></code></pre>\n</li>\n<li>\n<p>In this application, there are only three routes. The <em>login, verify,</em> and <em>home</em> routes. You need to render an <code>ejs</code> file when accessing the routes.</p>\n<p>Modify the <code>GET</code> routes using the code as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"17\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">render</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;login&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Rendering the login ejs file</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/verify&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">render</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;verify&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk12\">Rendering</span><span class=\"mtk1\"> </span><span class=\"mtk12\">the</span><span class=\"mtk1\"> </span><span class=\"mtk12\">verify</span><span class=\"mtk1\"> </span><span class=\"mtk12\">ejs</span><span class=\"mtk1\"> </span><span class=\"mtk12\">file</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">app</span><span class=\"mtk1\">.</span><span class=\"mtk11\">get</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/home&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">auth</span><span class=\"mtk1\">, (</span><span class=\"mtk12\">req</span><span class=\"mtk1\">, </span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">render</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;home&quot;</span><span class=\"mtk1\">);</span><span class=\"mtk12\">Rendering</span><span class=\"mtk1\"> </span><span class=\"mtk12\">the</span><span class=\"mtk1\"> </span><span class=\"mtk12\">home</span><span class=\"mtk1\"> </span><span class=\"mtk12\">ejs</span><span class=\"mtk1\"> </span><span class=\"mtk12\">file</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n</li>\n<li>\n<p>Create a folder named <code>views</code>, and inside, create the various <code>ejs</code> files.</p>\n<blockquote>\n<p>When the server is rendering an ejs file, it checks in the views folder for the file. So, this name is not optional.</p>\n</blockquote>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 317px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 90.85173501577287%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACH0lEQVQ4y41U2W7aQBTlI/rQSAS8gc14mfGOjSGhEaRS1KZSpPYT+tSnPuVD+r2n914CAsT2cGWDx8dnm+kNPQN7nGMcTWlquJMSo3Aqw/95kwojVcvw2oGr5XpuegIWtyhnLwjCJfy4Q9F+RVJ8Qd6s5ZrWK8T5I6xRugM8B9yTB24KV2m8/V4hKTtiXMKPGmEu7JgtjRuU1xnyAsvLYIcGP/++oV6s6cUaysxJcgOl53S/QJQ9iAVXAYe0YEBMwnGK9xXJzOYYEdAk6eD4Ofp2jHsn/rgmO7kXJVsE6HoJ/ry+oJk+wQ4qkWzRAgbZf/kmyfbI4PPQIC1CfF8r8q0RySw1pAkotIGbXAQ6ZEjp3TsGYWSQZVrC4Po4QQFPVeRpcZXZIUPy784y6FqN1+eYzG+lLhxInC/Fy2t1OclwEmoKhT3NJGEutUe1sen3MdDFUIQheTirE/x4jqh3LcL0QSYmph7J56R57X5Ip0B7Q4+LbYilgapy8i2TArvETrahqnf3jl/Is/0dcwJw8yVrbJAvcwS6Fmbsny6fqI8zSnm2KTf9H2WPB56eBySG6Zy2WlgQq81W4y5yysySZQ+PenlG8scDAgymfFBUxGpOh8RM2CjdEeOFgN8UCnvICY8nGv/eFYqCOqhaKTNLZd+2226f2WVACsX1NX59i6HinGQ2chAE5N/xCXNDD/mGv2jwqW/QdzbV2M6thd7Of/VJGV0jfuCyAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Folder Structure\"\n        title=\"Folder Structure\"\n        src=\"/static/35c47b77aff210613270620127987b41/a5d70/folder-structure.png\"\n        srcset=\"/static/35c47b77aff210613270620127987b41/a5d70/folder-structure.png 317w\"\n        sizes=\"(max-width: 317px) 100vw, 317px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n</li>\n</ol>\n<blockquote>\n<p>Style these various routes as you like</p>\n</blockquote>\n<h3 id=\"login-route\" style=\"position:relative;\"><a href=\"#login-route\" aria-label=\"login route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Login Route</h3>\n<p>Add the following code to <code>login.ejs</code> to set up the Login route.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ejs\" data-index=\"18\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;!</span><span class=\"mtk4\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;UTF-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">http-equiv</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;X-UA-Compatible&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;IE=edge&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Login</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Login Page</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Please Sign in</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk17\">/&gt;</span><span class=\"mtk3\">&lt;!-- Email input --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;submit&quot;</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">form</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;form&#39;</span><span class=\"mtk1\">)</span><span class=\"mtk3\">//Getting the form</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">email</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;.email&#39;</span><span class=\"mtk1\">)</span><span class=\"mtk3\">//Getting the email</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">form</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;submit&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">async</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Listening for a submit</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk11\">preventDefault</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = { </span><span class=\"mtk12\">email:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">email</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\"> }</span><span class=\"mtk3\">//Getting the email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/auth&quot;</span><span class=\"mtk1\">, {</span><span class=\"mtk3\">//Making a POST request to http://localhost:5000/auth</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">method:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">headers:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk8\">&quot;Content-Type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;application/json&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">redirect:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;follow&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Permiting redirects</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">body:</span><span class=\"mtk1\"> </span><span class=\"mtk10\">JSON</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stringify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">),</span><span class=\"mtk3\">//Sending the email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">res</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(</span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">redirected</span><span class=\"mtk1\">) </span><span class=\"mtk12\">location</span><span class=\"mtk1\">.</span><span class=\"mtk12\">href</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">url</span><span class=\"mtk3\">//Redirecting the user on success</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">((</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk12\">email</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\">);</span><span class=\"mtk3\">//Logging out error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<h3 id=\"verify-route\" style=\"position:relative;\"><a href=\"#verify-route\" aria-label=\"verify route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Verify Route</h3>\n<p>Open <code>verify.ejs</code> and set up the verify page as follows.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ejs\" data-index=\"19\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;!</span><span class=\"mtk4\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;UTF-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">http-equiv</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;X-UA-Compatible&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;IE=edge&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Login</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Verify Page</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;message&quot;</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Enter your OTP</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk3\">&lt;!-- Message alert --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;number&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;OTP&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk3\">&lt;!-- OTP input --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;submit&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">form</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;form&#39;</span><span class=\"mtk1\">)</span><span class=\"mtk3\">//Getting the form</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;.OTP&#39;</span><span class=\"mtk1\">)</span><span class=\"mtk3\">//Getting the OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">message</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;.message&#39;</span><span class=\"mtk1\">)</span><span class=\"mtk3\">//Getting the message alert</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">form</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;submit&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Listening for a submit</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk11\">preventDefault</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = { </span><span class=\"mtk12\">OTP:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\"> }</span><span class=\"mtk3\">//Getting the OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/verify&quot;</span><span class=\"mtk1\">, {</span><span class=\"mtk3\">//Making a POST request to http://localhost:5000/verify</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">method:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">headers:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk8\">&quot;Content-Type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;application/json&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">redirect:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;follow&quot;</span><span class=\"mtk1\">,</span><span class=\"mtk3\">//Permitting redirects</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">body:</span><span class=\"mtk1\"> </span><span class=\"mtk10\">JSON</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stringify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">),</span><span class=\"mtk3\">//Sending the OTP</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk4\">async</span><span class=\"mtk1\">(</span><span class=\"mtk12\">res</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ok</span><span class=\"mtk1\">){</span><span class=\"mtk3\">//Checking for errors</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">message</span><span class=\"mtk1\">.</span><span class=\"mtk12\">textContent</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk3\">//Alerting the error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">redirected</span><span class=\"mtk1\">) </span><span class=\"mtk12\">location</span><span class=\"mtk1\">.</span><span class=\"mtk12\">href</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">url</span><span class=\"mtk3\">//Redirecting the user on success</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }).</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">((</span><span class=\"mtk12\">e</span><span class=\"mtk1\">) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk12\">OTP</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<h3 id=\"home-route\" style=\"position:relative;\"><a href=\"#home-route\" aria-label=\"home route permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Home Route</h3>\n<p>This is the route that is protected. The page can contain sensitive information that must not be accessible to unauthenticated users.</p>\n<p>Open <code>home.ejs</code> and configure the home route as follows.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ejs\" data-index=\"20\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk17\">&lt;!</span><span class=\"mtk4\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;UTF-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">http-equiv</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;X-UA-Compatible&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;IE=edge&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Login</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Home Page</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Hello authenticated user, This is a secret information for your eyes only😉</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> Want to be unauthenticated, </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Sign Out</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span><span class=\"mtk3\">&lt;!-- Sign Out button --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">button</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;button&#39;</span><span class=\"mtk1\">)</span><span class=\"mtk3\">//Getting the sign out button</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   </span><span class=\"mtk12\">button</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;click&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">async</span><span class=\"mtk1\">()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span><span class=\"mtk3\">//Listening for a click</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;/logout&#39;</span><span class=\"mtk1\">, {</span><span class=\"mtk3\">//Making a POST request to http://localhost:5000/logout</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk12\">method:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;POST&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk12\">headers:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk8\">&quot;Content-Type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;application/json&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk12\">redirect:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;follow&quot;</span><span class=\"mtk3\">//Permitting redirects</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     }).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">((</span><span class=\"mtk12\">res</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">redirected</span><span class=\"mtk1\">) </span><span class=\"mtk12\">location</span><span class=\"mtk1\">.</span><span class=\"mtk12\">href</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk12\">url</span><span class=\"mtk1\"> </span><span class=\"mtk3\">//Redirecting the user on success</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     }).</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">message</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>This tutorial taught you how to set up Nodemailer, Redis Cloud, and Multi-Factor Authentication. With these, you've learned to secure your applications from unauthenticated users.</p>\n<p>Do you think you can use this to build complex and scalable applications?</p>\n<h2 id=\"mfa-with-loginradius\" style=\"position:relative;\"><a href=\"#mfa-with-loginradius\" aria-label=\"mfa with loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>MFA with LoginRadius</h2>\n<p>You can also set up MFA with LoginRadius instead of setting up everything manually with Redis. You can <a href=\"https://accounts.loginradius.com/auth.aspx?action=register\">sign up for a free account here</a>.</p>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Refer to this developer-friendly documentation to get started with your MFA setup</a>docs/guide/mfa/) for your web and mobile apps.</p>\n<h2 id=\"resources\" style=\"position:relative;\"><a href=\"#resources\" aria-label=\"resources permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Resources</h2>\n<p><a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/NodeJs/Multi-FactorAuth\">Click here to access the sample code used in this tutorial on GitHub</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk17 { color: #808080; }\n</style>","frontmatter":{"date":"June 30, 2022","updated_date":null,"description":"Want to implement Multi-Factor Authentication (MFA)? Follow this tutorial to implement MFA using Redis Cache and OTP in your applications.","title":"Multi-Factor Authentication (MFA) with Redis Cache and OTP","tags":["Node.js","Redis","Authentication"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/2d03da6d57630fa5c217227a0ca59a08/ee604/mfa-with-redis-cache-and-otp.png","srcSet":"/static/2d03da6d57630fa5c217227a0ca59a08/69585/mfa-with-redis-cache-and-otp.png 200w,\n/static/2d03da6d57630fa5c217227a0ca59a08/497c6/mfa-with-redis-cache-and-otp.png 400w,\n/static/2d03da6d57630fa5c217227a0ca59a08/ee604/mfa-with-redis-cache-and-otp.png 800w,\n/static/2d03da6d57630fa5c217227a0ca59a08/f3583/mfa-with-redis-cache-and-otp.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Fredrick Emmanuel","github":"divofred","avatar":null}}}},{"node":{"excerpt":"SolidJS is a declarative JavaScript framework used for building UIs and web applications pragmatically and performatively. Even though it's…","fields":{"slug":"/engineering/guest-post/introduction-to-solidjs/"},"html":"<p>SolidJS is a declarative JavaScript framework used for building UIs and web applications pragmatically and performatively. Even though it's relatively new, its similarity with other JavaScript frameworks like React and Svelte has made it more adoptable for the developer community. </p>\n<p>So in this tutorial, I'll give you a complete walkthrough of SolidJS and help you understand the essentials. You'll also build a simple web application with SolidJS to get a better hang of the basics. Finally, I'll compare and contrast it with the most popular framework in town — React. </p>\n<h2 id=\"what-is-solidjs\" style=\"position:relative;\"><a href=\"#what-is-solidjs\" aria-label=\"what is solidjs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is SolidJS?</h2>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACW0lEQVQoz0VS21LTUBTNv+mL4wX1wTd/wtEZuTkD+sqLIwpPchmh0wtpGUQotKU0UOy9ITlNStI2acmlhfETlvucQnlYZycnZ6+z1tqRPm2e48y6RssL0PKH2FPO8WNrC+vJFDZSKSSOM1iTkwQZq5GI+Labz2MhqeGI9WFQX6xoY+XIwFKyAWn5QIfhh4LQGo6oeqhZFuq2jYplo9S2Ub7i1ULJ5Gij2XOQ0zrQrwOYwVD0m0EIbRBAyuiueFFaPexX2kjXLRw3OzisE4k9oG8jMG8o1OteiGLbpbMOLq5cFFhX9F32fSLz6QIfEl/s0QiffxXw+EMEr+bieD2/g0fvtrEUv0Dv9gZNxxMqTkjVk5kdTM3u4MVsAs+m43g5l0C1O46Mk0qc3RwNsZ9l+Pb1FIflNvZLGuRCDQqzSV04UdB0fRweHGEtncPGnyJ+7p0idlJDozcQ9gUhXxhZLmsOjtMt6O41FFVFrlKB5vZhhjyjAMboBlemjWF6HoqZxUmlgXytCqWpot5xiDAEu7cs/PMph+FdFsFDXkYPZwIOFL1D1YI68IRqtT+u4jz1HZg0lLJDRER6SRv31hiRV7sDvF2UMTUdxfOZcVZPP8bwZiGF2iQzwp1VRlXWSeFvY7zJBPwHhUS+UrKwXjQRzVaxzZGpIFFoisvvM+O4JGLT85GxQ0jf811EVZ/YA2StAOMIxqp3g38ohreUr4a/jFGmLl30MIBJXMJViE2lDWkhpuKLrGFRZtht8H8yEAo4qUFZcaUaBc4z5cFrE7I7y/Rs0FDj5Q7er2bxH3UH7eTP28LLAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Features of SolidJS\"\n        title=\"Features of SolidJS\"\n        src=\"/static/9d5253ce2f2f38b45c825b4c98ea94ca/e5715/features-of-solidjs.png\"\n        srcset=\"/static/9d5253ce2f2f38b45c825b4c98ea94ca/a6d36/features-of-solidjs.png 650w,\n/static/9d5253ce2f2f38b45c825b4c98ea94ca/e5715/features-of-solidjs.png 768w,\n/static/9d5253ce2f2f38b45c825b4c98ea94ca/7b67d/features-of-solidjs.png 2240w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>SolidJS takes the syntax and developer experience of React and combines it with the performance of Svelte to give you the best of both worlds.</p>\n<p>Just like React, Solid uses JSX to render HTML in the browser. It also uses similar syntax for reactivity to update DOM in real-time. However, unlike React, it uses a compiled DOM instead of virtual DOM. </p>\n<p>This means you get a smaller size pure JavaScript bundle, much like the production bundle of your Svelte or Vanilla JS application. This makes it blazingly fast and highly performant.</p>\n<h2 id=\"solidjs-essentials\" style=\"position:relative;\"><a href=\"#solidjs-essentials\" aria-label=\"solidjs essentials permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>SolidJS Essentials</h2>\n<p>Let's now understand the fundamentals of SolidJS using some code examples. To follow along, you can directly run these snippets in the <a href=\"https://playground.solidjs.com/\">SolidJS playground</a>. </p>\n<h3 id=\"architecture\" style=\"position:relative;\"><a href=\"#architecture\" aria-label=\"architecture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Architecture</h3>\n<p>Solid follows the component architecture for modularity and reusability. Let's see how you can create an entry component and render it to the DOM. </p>\n<p><a href=\"https://playground.solidjs.com/?hash=1358759546&#x26;version=1.4.1\">Here's a component <code>HelloWorld</code></a> that is injected into the DOM inside an HTML element that has an id <code>app</code>:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">HelloWorld</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Hello World</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">HelloWorld</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;app&quot;</span><span class=\"mtk1\">)!);</span></span></code></pre>\n<p>From the above code, it's also clear that components are functions that return the HTML template using JSX.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 38.76923076923077%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAABdElEQVQoz3WS604CMRCF9yVUFmi3ewe5hOBuYW+KAvG3oGjUxMdQwEviix9nihpj9MeX6ZlOz3S6a509vGNy+4LJ3Sv08gl68YTRck1QvNwgWz1TXCNdPCK9eDTrbLVFcb3F+GqDk9tXlDfPRp/ev8Eqqwmy8gRZVqLIcuREkmokSYpkVCDLK0xnc8zm5zibzlFWx5QroEdjpHqEo0RjTPqI6ouyguW4HoLQh+cqiEYDTaJerxsaxP7+Hnq9HrTWGA6HcF0XtdrBZ429i7YNm/A8D1YYhIjCmIQPISWEELtISOkYfdjp0Fqaw0JIOI5j9r5gzfkoimF5vktdPShydxwFpVgrg1IKzWYTHTLk7tI0+RtuHEURrCjywWMrGtv1fQTUJY5DQ0CaDbvdrhmVb8j6N2zWoKcKggCWELvEN6ZIGFjzgXa7jTAM0Wq1DHEcG9iA4T2O/X4flpQCUvw/CnfmG6ZpSn9CZj7MYDAwsMFP8jzHB4lL8V3B7Cf1AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"HelloWorld Example\"\n        title=\"HelloWorld Example\"\n        src=\"/static/fcef69bea460903232532ef90c48da89/e5715/hello-world-example.png\"\n        srcset=\"/static/fcef69bea460903232532ef90c48da89/a6d36/hello-world-example.png 650w,\n/static/fcef69bea460903232532ef90c48da89/e5715/hello-world-example.png 768w,\n/static/fcef69bea460903232532ef90c48da89/d9ed5/hello-world-example.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Solid components allow only a single JSX element at the top level. To combat this, you can use special JSX elements called fragments: </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Hello World </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">This is my first solid app </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/&gt;</span></span></code></pre>\n<h4 id=\"nesting-components\" style=\"position:relative;\"><a href=\"#nesting-components\" aria-label=\"nesting components permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Nesting Components</h4>\n<p>Components can be nested inside one another. For instance, here you have a <code>&#x3C;Header/></code>component:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Header</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     Header</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Header</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>That is rendered inside the main <code>&#x3C;App/></code>component:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Header</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./header&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Header</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      Hello World</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">App</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;app&quot;</span><span class=\"mtk1\">)!);</span></span></code></pre>\n<p>That should give you both the components on the DOM like this:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 62.46153846153847%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABpUlEQVQoz5WRWVPCMBSF8zMUuqTpikJLYRwp4IYVF0oRBkd9dRkd3P//w/EmiKDoOD58c5Obk3vvSVgyfEZzMMHW8AlJ/oBKeoXw4BoREdK62r1BfHiLjd49NgeP2Mju0MxfkYzf0Mgn2Bm/ok13t0YvaJ0+gaXZBbr5JdL+BXYPR8QQ291TtNIB2oSMrf0+mgdjdHrnSLNzJJ0MrU4fe8dnSit1O0cj0uZgDucoldYQBAF8y4TDdRjaKrTCypziNOoUt9sJst4JanFE+286ggnbhU1wi0M3DIVhmDBMcxoX1ibFer2GWq2u4JY113/ABCW9UgnCdaDrNJ0SzJnlZOTkpry+hkKhoFg8m+mZbdtwXA8y6poGTaErFoXTgibK5XW1N9XUxhIsCHwIIZQtLmzYDjVwBDUQ4JT7OuG0oEZrrVj8aP4VJotZZNskO38XlB8YkF7A9/1PPM+jOw5c1wWTwjmL3ZYtS5thWKGPqaPRaCCOY0W1WkUURSrPfnqH3z5FFoyiUE0k31y6myH3kj8LLk1YKX9elja/8/+CZFm+1U/FJO9tJ2BDgIGOqAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Header and HelloWorld\"\n        title=\"Header and HelloWorld\"\n        src=\"/static/414b0805fab01839d7fc5a7b677f3d4a/e5715/header-and-hello-world.png\"\n        srcset=\"/static/414b0805fab01839d7fc5a7b677f3d4a/a6d36/header-and-hello-world.png 650w,\n/static/414b0805fab01839d7fc5a7b677f3d4a/e5715/header-and-hello-world.png 768w,\n/static/414b0805fab01839d7fc5a7b677f3d4a/d9ed5/header-and-hello-world.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"props\" style=\"position:relative;\"><a href=\"#props\" aria-label=\"props permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Props</h4>\n<p>Props are data and functions you can pass from one component to another to share data and features between the two components. In the previous example, you can pass a <code>title</code> prop to the <code>&#x3C;Header/></code> component:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Header</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Header&quot;</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">...</span></span></code></pre>\n<p>Then consequently consume this prop inside the child component: </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Header</span><span class=\"mtk1\">({</span><span class=\"mtk12\">title</span><span class=\"mtk1\">}) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk4\">{</span><span class=\"mtk12\">title</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Header</span><span class=\"mtk1\">;</span></span></code></pre>\n<h3 id=\"reactivity-and-events\" style=\"position:relative;\"><a href=\"#reactivity-and-events\" aria-label=\"reactivity and events permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Reactivity and Events</h3>\n<p>Reactivity allows you to create variables that dynamically trigger a DOM update when changed.</p>\n<p>SolidJS allows you to create reactive variables called <em>signals</em> using the <code>createSignal</code> function. This function takes in the initial value of the variable as a parameter. And it returns an array where the first element is the variable itself and the second element is a function used to mutate that variable.</p>\n<p><a href=\"https://playground.solidjs.com/?hash=776620219&#x26;version=1.4.1\">Here's an example</a> that changes the reactive variable called <code>name</code>:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">DisplayName</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">name</span><span class=\"mtk1\">, </span><span class=\"mtk12\">setName</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;fuzzysid&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">changeName</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk11\">setName</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;siddhant&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">{</span><span class=\"mtk12\">name</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">changeName</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Change Name </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">DisplayName</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;app&quot;</span><span class=\"mtk1\">)!);</span></span></code></pre>\n<p>Initially, the name outputs the string 'fuzzysid':</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 43.84615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABf0lEQVQoz32R2VLCQBBF8xMoBMgkmS1BEQIChiWIKL5R5Vr6rp/ggnz8tadDyQvlw6k7vcydTscrXreYE7OXH5zffTDD+08M7kqGTikePWyIL6p9sY6fN7h4/EbxskX+tMHk+Ydjb7FYYUrMiiXm8yvSBYb5DKPxnuG4wPhyheXNLabzJeUKFItrPl9MqDa9xITuuV5PqQSnWRdpqwUdhdCxQKPuo+7X4NeqjDsfH1WgZIT3tzemTj3V6vFfT22nnk7baGcdmNYJTk5TnLVTtIxGGIYIggCBEBBEs9lEklis12usVrecP4SnlYGyKSKpEEYxG7GZKA2dkdNGowFrDdcqlUr5WEA1ru/xnEmsE0ht2VgqBa00RCTRPGCYJMnO7DA0oaTLEYSWCOMY0hgYI2GNop3Ff417Qwvf9zk+hOf2I+gzBP0QpyGZR3R2hG4vO0M3qaXdGqac1FrLaK0Zl/dc43+UuykndGa9Xg95nmMwGKDb7SLLMnQ6Habf7+MXDOYPVqQlEeoAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Reactivity Before Update\"\n        title=\"Reactivity Before Update\"\n        src=\"/static/41c08d39e8885ee93e09ebbd571bf0b1/e5715/reactivity-before-update.png\"\n        srcset=\"/static/41c08d39e8885ee93e09ebbd571bf0b1/a6d36/reactivity-before-update.png 650w,\n/static/41c08d39e8885ee93e09ebbd571bf0b1/e5715/reactivity-before-update.png 768w,\n/static/41c08d39e8885ee93e09ebbd571bf0b1/39148/reactivity-before-update.png 2876w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>A click event is used on the button that fires a function called <code>changeName</code>. When you press the <em>Change Name</em> button, the <code>changeName</code> function updates the <code>name</code> signal to 'siddhant':</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 43.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABkklEQVQoz32S61LbMBCF9RRp6pts62I5cRLiOLYcSEj7CLQDbXmFzJQ/LYXw7qcrmQDDdPrjm5296MzqSOzT7RM+3x5x+f0R7dUvdFe/Yb+85x6b6yPOrx/Qf733bG8efb7/ccTFzQN231z+B6y3GzREt7Y4txa2bbGsa9T16pVVg3W3wXZ7gd3uEtb26Dd0prPUW2HVUL/t/DmmTYWzdYNyWqGQgsiRxBHCMEQQBJ4wDDAef0CWpTgcDvh5dwfOOdXGCJ9nguCjj0xPZpidzaFMiaoymE0NSiWRpimSJPG4w3Eco9Aa+/0efd/72qk/MORMCYVMFUhzgYSTCA1yzyDohFyMoghaK+R5jtFo9CI09F9hTkhoA0GisighpISSCjwTiN8JFiRYlual9i+YFDl4noErQVvmkHQtrclLLSEoj58HT4LGGO9VFIXeZ4frnWD+euQXJ8NdTLPMm+9I3/jktnJXLgrtRatqislk4jGmoN5QZ27wfyRvNtT0WMvlEi19rYa+ynw+x2Kx8NFR07f5C0B4DgyWnkafAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Reactivity After Update\"\n        title=\"Reactivity After Update\"\n        src=\"/static/a7867711b63ad1711fe106153ac7b921/e5715/reactivity-after-update.png\"\n        srcset=\"/static/a7867711b63ad1711fe106153ac7b921/a6d36/reactivity-after-update.png 650w,\n/static/a7867711b63ad1711fe106153ac7b921/e5715/reactivity-after-update.png 768w,\n/static/a7867711b63ad1711fe106153ac7b921/d9ed5/reactivity-after-update.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>What a <code>state</code> is to React components, a <code>signal</code> is to Solid components. <a href=\"https://playground.solidjs.com/?hash=-1579873004&#x26;version=1.4.1\">Here's another useful and typical example</a> of reactive variables:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Counter</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">count</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setCount</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Counter: </span><span class=\"mtk4\">{</span><span class=\"mtk12\">count</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">count</span><span class=\"mtk1\">-</span><span class=\"mtk7\">1</span><span class=\"mtk1\">)</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">  Decrement </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">&nbsp;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">count</span><span class=\"mtk1\">+</span><span class=\"mtk7\">1</span><span class=\"mtk1\">)</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">  Increment </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Counter</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;app&quot;</span><span class=\"mtk1\">)!);</span></span></code></pre>\n<p>You can take the current value of a signal inside the signal's mutation's callback function. The above code used the present value of <code>count</code> to increment and decrement it accordingly. </p>\n<h3 id=\"effects\" style=\"position:relative;\"><a href=\"#effects\" aria-label=\"effects permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Effects</h3>\n<p>Effects are triggers or watchers that can help you fire a function when a signal updates.</p>\n<p>Let's say, in the previous example, you want to throw an alert when the count becomes greater than 5.</p>\n<p>To do so, you can create an effect using the <code>createEffect</code> function. It takes a callback function as a parameter. This callback function is fired whenever a signal invoked inside it changes. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk11\">createEffect</span><span class=\"mtk1\">(()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(</span><span class=\"mtk11\">count</span><span class=\"mtk1\">()&gt;</span><span class=\"mtk7\">5</span><span class=\"mtk1\">) </span><span class=\"mtk11\">alert</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;Count is greater than five&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">})</span></span></code></pre>\n<p>So now, if you click on the <em>Increment</em> button, you should get an alert when it becomes greater than 5:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 44.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABwklEQVQoz2WSTW/TQBCG/SMgIk2y6/3wer3xR6K0dRPHcVNXBHIBIaCIUzkA14gDtEL89pdZG0IkDo9mPLN658tB/fEXNh8e0RDLt9+xePUNF2/I7r+iXK6xrq+xOC+RuAxummOaFjh/+QXV3U96/wP13SPW7x+weveAigja9gWa7XPUxKZp0Vy3qOotLsoVbJJ2xNbBGAuXztC+/oyy2uJyWWHd3GBFBctVjWpzg2XVIAi5hIos4jSFUBo6iiA4h2ATcLKTyQSMMTDyh8Mh2ttbHA4HfLq/x2xWYPD0Cc7OhpR71hEoHSGlhCtmJBwjNhpxbBDysBfq6EVHoxGuri6x3++x2+1QFAXG474w+0OglYI1EbSW0FJAUlCJsPM5Z32HxN9Op1OHwWDQ4Qv4WJ/rIUGNiEbWkYHU1JlUlKBR6aGv3FVn/NhtnmcncfYfgRQCOqELFgskaY4sc7TPHIauahNLV6XdRslxdC84Ho+77jzePyWIjYEgURaG4ISQEtKPTlb42EmH3k9pZEVrSqmQc64jSRL6CwystTQy7U4pCU6EJKJNTEl/GA1F3/921I9UFDnm8znKsqRu8yNZlnXx37VcDjNxtfqhAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Effects Example\"\n        title=\"Effects Example\"\n        src=\"/static/5bfec53557d129d8aae31fb9f40f7a0a/e5715/effects-example.png\"\n        srcset=\"/static/5bfec53557d129d8aae31fb9f40f7a0a/a6d36/effects-example.png 650w,\n/static/5bfec53557d129d8aae31fb9f40f7a0a/e5715/effects-example.png 768w,\n/static/5bfec53557d129d8aae31fb9f40f7a0a/d9ed5/effects-example.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"conditionals\" style=\"position:relative;\"><a href=\"#conditionals\" aria-label=\"conditionals permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conditionals</h3>\n<p>Solid provides special components called <code>&#x3C;Show></code> to render a template based on a condition or the value of a signal. <a href=\"https://playground.solidjs.com/?hash=1279589651&#x26;version=1.4.1\">Here's an example of that</a>:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">,</span><span class=\"mtk12\">Show</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Counter</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">count</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setCount</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Counter: </span><span class=\"mtk4\">{</span><span class=\"mtk12\">count</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">count</span><span class=\"mtk1\">-</span><span class=\"mtk7\">1</span><span class=\"mtk1\">)</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">  Decrement </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">&nbsp;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">count</span><span class=\"mtk1\">+</span><span class=\"mtk7\">1</span><span class=\"mtk1\">)</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">  Increment </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Show</span><span class=\"mtk1\"> </span><span class=\"mtk12\">when</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk11\">count</span><span class=\"mtk1\">()&gt;</span><span class=\"mtk7\">5</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Count is greater than five </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">Show</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Counter</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;app&quot;</span><span class=\"mtk1\">)!);</span></span></code></pre>\n<p>Once the <code>count</code> becomes greater than 5, the <code>&#x3C;p></code> will start showing on the DOM:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 44.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABpklEQVQoz22QyZLTMBCG/Q6Qg+NNsuQtXmKHxGsSE4ZjcmGn4BGGW2pgAgfe/Kel1LgCxeGrbnW3/l6M8etvHL78witi+PCIzZsHNIq33//m3Q907x/RklUMHy9Uf8H+80/sPl30e0cY4/6AbtijHUYM/Q7bYYu27bDeNDfUWDdb9LsRd3evUTcdXlC87beo217XtN2ATd3C4EwgiBdIiiWEDCE5h/QZbMvCfG4Sc20tYvb8GQ4vR5zPZ3y7v0dT15jNZrAsqjFNXWcIGSCMU4goBhcBglBCSgHXdeE4Ckf7nse03/cdjscjTqcTqmoF27Yp58FVuB4J+j5kuECcFYgWGeIkhgivBEGAKIrAqJESVWRZCtOc68mV2LWxanrF8GnFIC+RrxssyxJZvkCYpJNg+I9gkWeT/z8Mnyb06aMMaFUhwBnXo1t0QzWBwnHsafVlkeuYyt/yFDPCMADndB9GN2CM7igghE/TCfg+nzo/CaZpQnmBPM9p/YzeqUadJkmS64SMBD1anRG+lFpQEpwa3IopW5YFVqsVmqZBURQTqkFVVfgDaqIRVH3BTXQAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Conditionals Example\"\n        title=\"Conditionals Example\"\n        src=\"/static/7aec3c908829756166d7e070b184627d/e5715/conditionals-example.png\"\n        srcset=\"/static/7aec3c908829756166d7e070b184627d/a6d36/conditionals-example.png 650w,\n/static/7aec3c908829756166d7e070b184627d/e5715/conditionals-example.png 768w,\n/static/7aec3c908829756166d7e070b184627d/d9ed5/conditionals-example.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"loops\" style=\"position:relative;\"><a href=\"#loops\" aria-label=\"loops permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Loops</h3>\n<p>Just like <code>&#x3C;Show></code>, Solid also provides a special component called <code>&#x3C;For></code> to render a list on the DOM from an array. </p>\n<p>In the <a href=\"https://playground.solidjs.com/?hash=195732488&#x26;version=1.4.1\">following example</a>, you use the <code>&#x3C;For></code> component to render a list of fruits from the <code>fruits</code> signal. Inside the opening brackets of the <code>&#x3C;For></code> component, you specify the variable name that will be used to extract items to loop through using the <code>each</code> prop. </p>\n<p>Then, you can take a callback inside which you get the individual item as the first parameter and an optional index of the iteration as a second parameter.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">, </span><span class=\"mtk12\">For</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Counter</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">fruits</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setFruits</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">([</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&#39;Mango 🥭&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&#39;Apple 🍎&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&#39;Banana 🍌&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&#39;Melon 🍈&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&#39;Watermelon 🍉&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ]);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> Fruits </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">For</span><span class=\"mtk1\"> </span><span class=\"mtk12\">each</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk11\">fruits</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk1\">(</span><span class=\"mtk12\">fruit</span><span class=\"mtk1\">,</span><span class=\"mtk12\">index</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk11\">index</span><span class=\"mtk1\">()+</span><span class=\"mtk7\">1</span><span class=\"mtk4\">}</span><span class=\"mtk1\">: </span><span class=\"mtk4\">{</span><span class=\"mtk12\">fruit</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">For</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Counter</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;app&quot;</span><span class=\"mtk1\">)!);</span></span></code></pre>\n<p>Here's what the list looks like when rendered in the DOM:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 46.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAABc0lEQVQoz2VSaVLCMBjtMaRLmjahQFLaWqBlsQp4ApFBdMZT4IZ/PPozSa1sP968b98Sa/H6g+XL3qDafKB82GG82mGyeqvxqFnp609U229M1+8Yq5hqo/SnL8yf90a+2+5xo/KtSTFGWUwwGs8Ul5gWBYrhAFmWIU3TA64HGA5HuF8uUFW3yHOtD//j8jw3bNGAod3ro5ukCHiEiDN0Ig7XdWHbNhzHMdCy3WqhKAvMZxM4rSu0tF/b/+A4NqyQcRRZjFREcIkPSimCIIDv+ycghgnKssRyXoGHFB4hIGewOGNIuhFEm8FTU3medwFCaqbUhxQ9JRP4Krn2nRfkHCzkZjIziXY0fJTQFIxjeVHkpGAYBgijDrLBAEJKRKIP3uldBNYFKaQU5qau65g7N9B+zWZC39ysSfbrVd3jlQ8TCrWylLF54eYHJEmibNKw1Y7a5hGI6k5UAg1C6KkZC2u7aVIX1k2zLDVfRUMIcYI4jvELgJEL+TBslwEAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"For Example\"\n        title=\"For Example\"\n        src=\"/static/4f38c58718891a069960d064d57822f9/e5715/for-example.png\"\n        srcset=\"/static/4f38c58718891a069960d064d57822f9/a6d36/for-example.png 650w,\n/static/4f38c58718891a069960d064d57822f9/e5715/for-example.png 768w,\n/static/4f38c58718891a069960d064d57822f9/d9ed5/for-example.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"lifecycle-methods\" style=\"position:relative;\"><a href=\"#lifecycle-methods\" aria-label=\"lifecycle methods permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Lifecycle Methods</h3>\n<p>Most frameworks provide several lifecycle methods for different purposes. This often leads to a steeper learning curve as well as unnecessary complexity.</p>\n<p>Solid stays truly reactive: it gives you the <code>createEffect</code> and signals to build whatever interaction you want. However, to simplify things further, it gives you two primary lifecycle methods. </p>\n<h4 id=\"onmount\" style=\"position:relative;\"><a href=\"#onmount\" aria-label=\"onmount permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>onMount</h4>\n<p>The <code>onMount</code> method is fired just once in the entire lifecycle of a Solid component. It runs only the first time your component mounts on the DOM. It's an excellent place to make any API calls your application needs.</p>\n<p>For instance, consider the <a href=\"https://playground.solidjs.com/?hash=-1837326429&#x26;version=1.4.1\">following example</a> that uses the <code>onMount</code> method to fetch and render some data:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">, </span><span class=\"mtk12\">onMount</span><span class=\"mtk1\">, </span><span class=\"mtk12\">For</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">posts</span><span class=\"mtk1\">, </span><span class=\"mtk12\">setPosts</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">([]);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">onMount</span><span class=\"mtk1\">(</span><span class=\"mtk4\">async</span><span class=\"mtk1\"> () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk8\">`https://jsonplaceholder.typicode.com/posts`</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">setPosts</span><span class=\"mtk1\">(</span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">res</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Effects: onMount</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">For</span><span class=\"mtk1\"> </span><span class=\"mtk12\">each</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk11\">posts</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk1\"> </span><span class=\"mtk12\">post</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">{</span><span class=\"mtk12\">post</span><span class=\"mtk1\">.</span><span class=\"mtk12\">body</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">For</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/&gt;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">App</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;app&#39;</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>It renders a list of posts fetched from a dummy API:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.92307692307692%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB3klEQVQoz22S6W7aQBSF/RSNABvwMh6DcTF4X7CxA83vtuki5TmapGmlPvrpmSmpUNUfR/eONXP83cXoH35hePiJkWo+f0f+/huKj4/Uk1b5qvtn1J9edJ5/eGT+jOr+Cd3XH1rtlxccGI3+MKBqOpRNj6Zu0TYtiqJClhdIM6UcaUoVjb53fneH43CLpu1wOt+hrBrs9ilyvkl4z7CXLoRcww9D2K6A47pwljbs+Ryz2RSTyQRTpekENzdvkCZ7nE5ndF2H4/GI7XYLz/MgBN86DgyXSbjbQ25iiGCFVSAoH45N0+WScanjYrGAZVkkz2g0kHJEziryokBV1ajrBkmSwhB0X29CBDLEehUg8D1I18FKuAgoFQXPcxKbpomShuN4i74/YqBp1/Vo24P+SRS9JaFLXI9EDolsByYp/sq8iPmrYUXDYRy12eHQkTLXpBmjlBKGqtvxJSk3kEHAPnr68f80m81Ql4UmVGaKTEVFqYiTJKEhe+UIHzKM9EDm7NW1ieqbdSFUcbeLda8UWZZlWmmaIY7jP4Z6Op6AxXJMEqiyrsv8V9ttpCerjKIowoaVKYXcEvXdkFJw7C4WpPPlCiEHE619hNLX07WujFUex1yTy4oouWrNKB15/g3IWjYPDF+mngAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"onMount Example\"\n        title=\"onMount Example\"\n        src=\"/static/c0f0e6692797e95e552866929aabc018/e5715/on-mount-example.png\"\n        srcset=\"/static/c0f0e6692797e95e552866929aabc018/a6d36/on-mount-example.png 650w,\n/static/c0f0e6692797e95e552866929aabc018/e5715/on-mount-example.png 768w,\n/static/c0f0e6692797e95e552866929aabc018/d9ed5/on-mount-example.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h4 id=\"oncleanup\" style=\"position:relative;\"><a href=\"#oncleanup\" aria-label=\"oncleanup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>onCleanup</h4>\n<p><code>onCleanup</code> is the exact opposite of <code>onMount</code>. It's fired whenever a component unmounts from the DOM completely. Ideally, you can use this method to clear any event listeners you may have added to your DOM elements. </p>\n<p>Here's an example that does that:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">render</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js/web&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {  </span><span class=\"mtk12\">onMount</span><span class=\"mtk1\">, </span><span class=\"mtk12\">onCleanup</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;solid-js&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleMouseEnter</span><span class=\"mtk1\">=()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;Entered the box&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">onCleanup</span><span class=\"mtk1\">(()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">box</span><span class=\"mtk1\">=</span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;#box&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box</span><span class=\"mtk1\">.</span><span class=\"mtk11\">removeEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;mouseenter&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk12\">handleMouseEnter</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">onMount</span><span class=\"mtk1\">(</span><span class=\"mtk4\">async</span><span class=\"mtk1\"> () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">box</span><span class=\"mtk1\">=</span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">querySelector</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;#box&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onMouseEnter</span><span class=\"mtk1\">=</span><span class=\"mtk12\">box</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;mouseenter&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk12\">handleMouseEnter</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  });</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Effects</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;box&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">style</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk1\">{</span><span class=\"mtk12\">height:</span><span class=\"mtk8\">&#39;200px&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk12\">width:</span><span class=\"mtk8\">&#39;200px&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk12\">border:</span><span class=\"mtk8\">&#39;1px solid red&#39;</span><span class=\"mtk1\">}</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/&gt;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">render</span><span class=\"mtk1\">(() </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">App</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">document</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getElementById</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;app&#39;</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>When you enter the red box, the <code>mouseenter</code> event fires, and you get a message on the console. As a cleanup, when the component unmounts, we remove this event listener from that <code>&#x3C;div></code>. </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 57.38461538461538%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAAByElEQVQoz21S2W7bMBDUXzSNdZIURVGSJVk1/JAUTtLjOW2aAP2GHk4L9Puns4QiGEIeBpR2ydmZ3Y0+fv+Hu6dn3D2ecHz4hav7HwHX9z9x/WWGxL6ecPv0F8dvp5A/Pvzm/x/c8t0NYzePzyEWvRsGTMOIfjdh5Pd+7DH1LVrvUDu7wPsaTe1wfH+Fz58+YOg7tA1j8z35ljPKco3SefjWQ5clslwhTRIkxGYTL4jjGG8uLjC0DfqmQZGkSN5eMrcJ+cv5jJRSMI6VGgdfGRitEQshCYQ0TdMFEh8bjzzLsIkTFIxlZ3lBZIxB09EibdfBFu1VFsZWKLQJl16INywykNAURXChJC7FzwlL2nTsTUWUtqRCBa0KqNJCzYSLQhL2tCyEGYnW6mZCg9K3MN0Evx0wDA26toYzGpoPDftrqnoh7EiY5XnoXTz3+gWSDwpLQzXs5WsV1wpl2l3XYb/fY5om7HY7jOMYYnJGmkPQ1sFxMKZyoXeWfTVSiJDTqJxtUEHVwNU6HA7o+55v3IKqqljMI7LWIqe19URfg6zFdtsFAnEUxJxBYiQUJQY5h2E4CF/TkueickmVFFpZFkJRIwSyIWv8B8IsQ45K/nRYAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"OnCleanup Example\"\n        title=\"OnCleanup Example\"\n        src=\"/static/3589ae72ca32c795711c4a5671315e4b/e5715/on-cleanup-example.png\"\n        srcset=\"/static/3589ae72ca32c795711c4a5671315e4b/a6d36/on-cleanup-example.png 650w,\n/static/3589ae72ca32c795711c4a5671315e4b/e5715/on-cleanup-example.png 768w,\n/static/3589ae72ca32c795711c4a5671315e4b/fd561/on-cleanup-example.png 2866w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"build-a-todo-app-with-solidjs\" style=\"position:relative;\"><a href=\"#build-a-todo-app-with-solidjs\" aria-label=\"build a todo app with solidjs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Build a Todo App with SolidJS</h2>\n<p>Let's combine all that knowledge to build a small todo application with Solid.</p>\n<h3 id=\"setup\" style=\"position:relative;\"><a href=\"#setup\" aria-label=\"setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setup</h3>\n<p>To get started, you'll create a new SolidJS project configured with <a href=\"https://vitejs.dev/\">Vite</a> by running:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npx degit solidjs/templates/js my-app</span></code></pre>\n<p>That should create a new Solid project for you. Navigate inside this project and open it in a code editor (like VS Code):</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">cd my-app && code .</span></code></pre>\n<p>Next, install the dependencies by running:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npm i</span></code></pre>\n<p>And finally, kickstart the app by running:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npm run start</span></code></pre>\n<p>That should open the project for you at <code>http://localhost:3000</code>. Awesome!</p>\n<h3 id=\"architecture--boilerplate-code\" style=\"position:relative;\"><a href=\"#architecture--boilerplate-code\" aria-label=\"architecture  boilerplate code permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Architecture &#x26; Boilerplate Code</h3>\n<p>Your initial project structure gives the <code>&#x3C;App/></code> component by default. This is going to be your entry point component. For starters, clean everything that's inside it:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"17\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">styles</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./App.module.css&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">styles</span><span class=\"mtk1\">.</span><span class=\"mtk12\">App</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">App</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Notice that you also have an <code>App.module.css</code> file being imported here. It's then referenced inside the <code>&#x3C;div></code> container. You'll add all our styles inside this <code>App.module.css</code> file and reference it the same way. </p>\n<p>Now let's create some boilerplate files. Here's what the architecture of our Todo app would look like:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACtUlEQVQozzWT228TVxDG/TfyVCRaJCQQqloQ15YHWplY3JQIRBICAsSlaQRx4tgh4A0hBMe54QQw2F6v7V17fd2ztkNA5AGefszZiIfRzNkz881835wN/fvfGquVNkXPx1I9jI0Mo+PjPIwnuDM5ydjEBBPPk9yPzXBT4jvRqSC+G42SXN+Qmj6T6xVuLVgMxbOERo0CloDlWx5l5VPxFPl6A6vd5l3F4b1j43SlWadD2etg+x45uc/W6hSkpqS6VHxfvmsMRWixIMUCkpPDw7dNhlJVhlfrDC67GHaf0cQmh64+4++7S5wce8nhwefENkqMvWlyPmkRNiwuLDUY2eoJhkeo2FHBdGbHZ3StztVXNtfTVS4vOTwtKgafrPDrxVnO3l7kz+F5fpP48XJemtb4K5EjPF8iku4wvNXlY1MANZhGLsuURr5J7G2VcsOm3G5gK4/6tk//21ecXg+1+5lP37+KLG3MZpNNM0/GdlkwW+QErNBWGlBRbHuikRdQf7xqcWZsgfP3U2KvOSVxZDwtyR5Xnqzx+3WDfx6kODGS5MiVaQaiGYxCC83UlJyQTsy4irTjsdXqMZ2x2Tcwxx835jk+8oLDQ0nO3XsddA8/SvHLhXhwd/SawYGLcyTeWMH0mqVREsB3zT3tjiVKnJotcnquxKV0g1K3T63fp9BwyVZrTG25mF43oKx2v1Drevi7O7S+7OztQAabKQjgM0ux7vosO4qVqiIlPmV7gcAf6i1S2TzreZPZbI3pzSoHInH2DyQ4eCkh085IHCfjNKkoxaLtE7qZksScx1PTIy2Apc6enloKTVNvvyCm3+iHeltoLxP5P83Q1Ib4leD83tU/RpdHK2VC4ehHIrE84ZhJItsIHrnemF6WpvLTtEa6gftpm9p2P9BNe1dMP+6pTYfTt1/xA/FE3HC767xPAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Todo App Architecture\"\n        title=\"Todo App Architecture\"\n        src=\"/static/9c267ef542e8d1c595072b7702a549b4/e5715/todo-app-architecture.png\"\n        srcset=\"/static/9c267ef542e8d1c595072b7702a549b4/a6d36/todo-app-architecture.png 650w,\n/static/9c267ef542e8d1c595072b7702a549b4/e5715/todo-app-architecture.png 768w,\n/static/9c267ef542e8d1c595072b7702a549b4/7b67d/todo-app-architecture.png 2240w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>You'll have your top-most parent <code>&#x3C;App/></code> component that would store all the todos and the functions to manipulate these todos. This <code>&#x3C;App/></code> component will have two child components. </p>\n<p>First, the <code>&#x3C;AddTodo></code> component will be responsible for adding a new todo.</p>\n<p>Second, the <code>&#x3C;Todos/></code> component will be responsible for rendering the list of todos via its own child — <code>&#x3C;TodoItem/></code> component. </p>\n<p>Create a JSX file for each of the above components. </p>\n<h3 id=\"the-addtodo-component\" style=\"position:relative;\"><a href=\"#the-addtodo-component\" aria-label=\"the addtodo component permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The <AddTodo/> Component</h3>\n<p>The <code>&#x3C;AddTodo/></code> component will render an input field and a button. The input field is where the user types a new todo. The button will be used to send this new todo back to a function in the parent <code>&#x3C;App/></code> component to add this todo to the todos list. This function will be taken as props inside the <code>&#x3C;AddTodo/></code> component.</p>\n<p>To store the <code>newTodo</code>, create a signal since you want this property to be reactive based on what the user enters in the input. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"18\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setNewTodo</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>Now let's add the template inside the component's JSX:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"19\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;solid-js&#39;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">AddTodo</span><span class=\"mtk1\">({</span><span class=\"mtk12\">addTodo</span><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setNewTodo</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleChange</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk11\">newTodo</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text&quot;</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Type a new todo...&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleClick</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Add Todo</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">AddTodo</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>You bind the input field to the <code>newTodo</code> signal. You now need to create the <code>handleChange</code> function that updates the <code>newTodo</code> signal based on the <code>onChange</code> event. </p>\n<p>You also need to create the <code>handleClick</code> function that passes the <code>newTodo</code> signal to the <code>addTodo</code> function prop and clears the input state.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"20\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleChange</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setNewTodo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleClick</span><span class=\"mtk1\">=()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">addTodo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setNewTodo</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> }</span></span></code></pre>\n<p>Here's how the entire <code>&#x3C;AddTodo/></code> component looks like:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"21\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;solid-js&#39;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">AddTodo</span><span class=\"mtk1\">({</span><span class=\"mtk12\">addTodo</span><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setNewTodo</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleChange</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setNewTodo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleClick</span><span class=\"mtk1\">=()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">addTodo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setNewTodo</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleChange</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk11\">newTodo</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text&quot;</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Type a new todo...&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleClick</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Add Todo</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">AddTodo</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>You also need to render this inside the <code>&#x3C;App/></code> component:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"22\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">styles</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./App.module.css&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;solid-js&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">AddTodo</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./AddTodo&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">addTodo</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">deleteTodo</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">styles</span><span class=\"mtk1\">.</span><span class=\"mtk12\">App</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">styles</span><span class=\"mtk1\">.</span><span class=\"mtk12\">heading</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Todos</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">AddTodo</span><span class=\"mtk1\"> </span><span class=\"mtk12\">addTodo</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">addTodo</span><span class=\"mtk4\">}</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">App</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Once you do that, you should see an input field with a submit button rendered by the <code>&#x3C;AddTodo/></code> component on the screen:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABUElEQVQoz6WRzWrCQBSF5xmsDRQTTap113ZTSu3DKdn4eFmFJM1fFyKiqGiCGmPGY+5YRdIIlgY+7sz9OXMuYe12A2/vH+h0PvH88grtsYlK5e5MtXoPSZIgywoUrYFa7QENuQnlqY26WoemaVAUGaqqotVqgbmuB8d2YOdYliWgs+Pkd9sWOM4XPM+DF/h5dBH4IfzwG35+D4IAvn+MYQ7jnGO/3/+C8mUf1TKegWcER0aRHyPB1us1iqxWK6RpKl42DAPj8RhhGGI6nSKOY2w2G5TNESxJEhShAjmhtfv9PnRdR7fbRa/Xg2mawin1lM2WCpKD7XYrXJLbKIoE5I7qlKeemwRPjYvFAsvl8kcoEnlaeTgcYj6f5w8mpaLsmrvZbIbJZHKGnA4GA7iui9FoJHpuEiyufILyu91O/Mk/rXwpekkxd22OFQf/AwkeAP2xF5/Nus2WAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"AddTodo Component\"\n        title=\"AddTodo Component\"\n        src=\"/static/ea4ec890d45584376fe6c1a67d026846/e5715/add-todo-component.png\"\n        srcset=\"/static/ea4ec890d45584376fe6c1a67d026846/a6d36/add-todo-component.png 650w,\n/static/ea4ec890d45584376fe6c1a67d026846/e5715/add-todo-component.png 768w,\n/static/ea4ec890d45584376fe6c1a67d026846/23814/add-todo-component.png 2856w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"rendering-todos\" style=\"position:relative;\"><a href=\"#rendering-todos\" aria-label=\"rendering todos permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Rendering Todos</h3>\n<p>Now let's work on two simple components responsible for rendering the todos. First is the <code>&#x3C;Todos/></code> component. As you already know, this component takes in two props — a list of todos called the <code>todos</code> signal and the <code>deleteTodo</code> method. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"23\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">For</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;solid-js&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">TodoItem</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./TodoItem&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Todos</span><span class=\"mtk1\">({</span><span class=\"mtk12\">todos</span><span class=\"mtk1\">,</span><span class=\"mtk12\">deleteTodo</span><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk11\">todos</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">For</span><span class=\"mtk1\"> </span><span class=\"mtk12\">each</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk11\">todos</span><span class=\"mtk1\">()</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk1\">(</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">,</span><span class=\"mtk12\">ind</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">           </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">For</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Todos</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>You use the <code>&#x3C;For/></code> component to loop through the list of todos. Now, you need to pass each todo item and the <code>deleteTodo</code> method further down to your <code>&#x3C;TodoItem/></code> component. This component is responsible for rendering each list item. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"24\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">TodoItem</span><span class=\"mtk1\">({</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">,</span><span class=\"mtk12\">deleteTodo</span><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleDelete</span><span class=\"mtk1\">=()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">deleteTodo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleDelete</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk4\">{</span><span class=\"mtk12\">todo</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">TodoItem</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>When you click on an item, you invoke the <code>deleteTodo</code> function and pass the clicked todo item as a parameter. </p>\n<p>Finally, render the <code>&#x3C;Todos/></code> component inside the root <code>&#x3C;App/></code> component.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"25\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">styles</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./App.module.css&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">createSignal</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;solid-js&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Todos</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./Todos&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">AddTodo</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./AddTodo&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">todos</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setTodos</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">createSignal</span><span class=\"mtk1\">([])</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">addTodo</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">deleteTodo</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">styles</span><span class=\"mtk1\">.</span><span class=\"mtk12\">App</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h1</span><span class=\"mtk1\"> </span><span class=\"mtk12\">class</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">styles</span><span class=\"mtk1\">.</span><span class=\"mtk12\">heading</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Todos</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h1</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">AddTodo</span><span class=\"mtk1\"> </span><span class=\"mtk12\">addTodo</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">addTodo</span><span class=\"mtk4\">}</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Todos</span><span class=\"mtk1\"> </span><span class=\"mtk12\">deleteTodo</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">deleteTodo</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">todos</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">todos</span><span class=\"mtk4\">}</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">App</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Great! Let's complete the todo app by writing the logic for adding and deleting a todo.</p>\n<h3 id=\"adding-and-deleting-todos\" style=\"position:relative;\"><a href=\"#adding-and-deleting-todos\" aria-label=\"adding and deleting todos permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Adding and Deleting Todos</h3>\n<p>To add a new todo, you only need to complete the logic inside the <code>addTodo</code> function in the <code>&#x3C;App/></code> component. This function already takes a <code>newTodo</code> parameter, the new todo item you need to add. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"26\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">addTodo</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">newTodo</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">setTodos</span><span class=\"mtk1\">([</span><span class=\"mtk11\">newTodo</span><span class=\"mtk1\">(),...</span><span class=\"mtk11\">todos</span><span class=\"mtk1\">()]);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>You'll add the <code>newTodo</code> in the <code>todos</code> signal that is an array using its setter function <code>setTodos</code>. Use JavaScript array destructuring here to ensure to keep the previous todos intact. Let's give this a whirl now:</p>\n<p><video controls width=\"600\" align=\"center\" src=\"/ee1e93cf316cf6b97e0ebabed82c67bf/add-todos-demo.mp4\"> </video> <br></p>\n<p>It looks like you're able to add todos now. Awesome! </p>\n<p>To delete the todo when they're clicked, populate your <code>deleteTodo</code> function:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"27\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">deleteTodo</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">newTodos</span><span class=\"mtk1\">=</span><span class=\"mtk12\">todos</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">newTodos</span><span class=\"mtk1\">=</span><span class=\"mtk11\">newTodos</span><span class=\"mtk1\">().</span><span class=\"mtk11\">filter</span><span class=\"mtk1\">(</span><span class=\"mtk12\">_todo</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">_todo</span><span class=\"mtk1\">!=</span><span class=\"mtk12\">todo</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">setTodos</span><span class=\"mtk1\">(</span><span class=\"mtk12\">newTodos</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span></code></pre>\n<p>First, make a copy of the current todos array. Then, filter through this copy to remove the todo you wish to delete. Finally, update your original <code>todos</code> signal with this copy using the <code>setTodos</code> setter. Let's test it out now:</p>\n<p><video controls width=\"600\" align=\"center\" src=\"/ba95b63a0a55ccc16cee9ce827c28811/delete-todos-demo.mov\"> </video> <br></p>\n<p>You can delete todos as well; fantastic! </p>\n<h3 id=\"styling-the-app\" style=\"position:relative;\"><a href=\"#styling-the-app\" aria-label=\"styling the app permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Styling the App</h3>\n<p>Functionally your app is complete, but it surely misses some aesthetics. Let's add some simple yet neat-looking styles. You can directly update the styles in our <code>App.module.css</code> file:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"28\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">*</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">margin</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.App</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">text-align</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100vh</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#F8F8F8</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">display</span><span class=\"mtk1\">:</span><span class=\"mtk8\">flex</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">flex-direction</span><span class=\"mtk1\">: </span><span class=\"mtk8\">column</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">align-items</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.heading</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">96px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">margin-bottom</span><span class=\"mtk1\">: </span><span class=\"mtk7\">20px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">input</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">12px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">outline</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">20px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">20px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">60px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">400px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">24px</span><span class=\"mtk1\">; </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.05</span><span class=\"mtk1\">) </span><span class=\"mtk7\">0px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">button</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">65px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">150px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">outline</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">12px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">24px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">15px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.05</span><span class=\"mtk1\">) </span><span class=\"mtk7\">0px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">cursor</span><span class=\"mtk1\">: </span><span class=\"mtk8\">pointer</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-weight</span><span class=\"mtk1\">: </span><span class=\"mtk7\">600</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background</span><span class=\"mtk1\">:</span><span class=\"mtk8\">#2e3136</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">color</span><span class=\"mtk1\">:</span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">p</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">60px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">white</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">600px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">text-align</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">flex</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">align-items</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">justify-content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">12px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">24px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">margin</span><span class=\"mtk1\">: </span><span class=\"mtk7\">20px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.05</span><span class=\"mtk1\">) </span><span class=\"mtk7\">0px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">p:hover</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk11\">rgb</span><span class=\"mtk1\">(</span><span class=\"mtk7\">232</span><span class=\"mtk1\">, </span><span class=\"mtk7\">169</span><span class=\"mtk1\">, </span><span class=\"mtk7\">146</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">color</span><span class=\"mtk1\">:</span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">cursor</span><span class=\"mtk1\">: </span><span class=\"mtk8\">pointer</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">.header</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">background-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#282c34</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">min-height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100vh</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">flex</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">flex-direction</span><span class=\"mtk1\">: </span><span class=\"mtk8\">column</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">align-items</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">justify-content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk11\">calc</span><span class=\"mtk1\">(</span><span class=\"mtk7\">10px</span><span class=\"mtk1\"> + </span><span class=\"mtk7\">2vmin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">white</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>And that should give us a much better-looking todo app now:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.61538461538461%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAABlElEQVQoz4WRy07CQBiF+wTCSqhIBNyqcaELfCA3bnwMVy58D3YGTAwkmphAiAu5lNLahoWmGGLLxba0pRxn/ogBbHCSr+fM5T+di7CfS+H45BT5/BkODo+QzeYQi8WxFYuREvE4EokEkqkdJJPb2BX3IGazSKVTSKfTEEWRNJPJQFAUFbIso8OQJIngfVnuQup0SN/e3mEYBox+H6qqQFN1aL0edF0nNE379UIYhpjP55HwVqlUUCgUUCwWUa1WsWh8fjabETxjoYLjOIhiPBrBZaoqCu5KJZTLZdRYIN9Ns9GEaZqYTqd/6gQ+6LouTbqMKfeeD2tiY2Q7WG9X1zc4v7hEqy3RLnnIcsZqIFffhz0wYNXuYdXL+KxXYD4/ENx/PJVgPN7CNge0dqU2MtDz4AxNjNUGJloL49cWzO4Lwf2XLsHW23AnI1q7MXDhPT9AyC+e4bPP2HGJgPXDH/i1rNetBC7/yWM6CwL2cgF5iz3A0LLgsx3ROGP9ZCuBUXismMO9bdvE+ngUwiJ9E8vH+o9vF9kR7clrkQwAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Updated-app\"\n        title=\"Updated-app\"\n        src=\"/static/e24ed975dd640e252975fc4230a62301/e5715/updated-app.png\"\n        srcset=\"/static/e24ed975dd640e252975fc4230a62301/a6d36/updated-app.png 650w,\n/static/e24ed975dd640e252975fc4230a62301/e5715/updated-app.png 768w,\n/static/e24ed975dd640e252975fc4230a62301/9f75f/updated-app.png 2858w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"solidjs-vs-react\" style=\"position:relative;\"><a href=\"#solidjs-vs-react\" aria-label=\"solidjs vs react permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>SolidJS vs. React</h2>\n<p>If you're coming from a React background, building the todo app must feel like a piece of cake to you! This is because, in terms of syntax and architecture, Solid is strikingly similar to React. It uses the same structure of using functional components, returning JSX, fragments, one-way data binding, etc. </p>\n<p>Using effects, refs and events are also much similar to React in Solid. So it's safe to say that Solid provides almost the same if not slightly different syntactic sugar as React. Then why do we need another React-like framework for building web applications?</p>\n<p>Solid differs from React in terms of performance, developer experience, rendering algorithm, and reactivity. Let's skim through the key differences:</p>\n<h3 id=\"performance\" style=\"position:relative;\"><a href=\"#performance\" aria-label=\"performance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Performance</h3>\n<p>At the beginning of this tutorial, we discussed how Solid doesn't use a virtual DOM. Instead, it uses a compiled DOM. This gives it a significant edge over React and any other framework in terms of run-time performance. It generates a blazingly fast production bundle that is aimed to provide a more rich user experience for your users. </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 75.53846153846155%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAACD0lEQVQ4y5WUyW4TQRCG8xygeDz75tm3MFvbDihRhMIlXJDCIUJISOFAIpQLIEQQPAZvwSnv9lPV1lgZLwcOv6q6xv1NbZ4DTdPAUlUVhmHAdV1Mp1M4loE0cJEEjhT7lqHK3w13dulgcCTEcVCUJTRVQdyd4cXVDxy//YIl6eTdPfLnF5gcPoWm63vBW8A8L+B7DsLmVILmb+4gSOyL80sYOmX5PxnmeY4oihH4DtqjDE2VkjLURQLR1kjTDJPJZN2mvUB+yMCSSk6SBFEco+t7tG2Htuuk7To+tzBNcwR77I+Atm3LDGezGcIwJEAnAYOapoEQAlVVyYoURVnDBrsFzLJMWobyZYZuiuP8nDdC3xjQFjBNU/i+LzPs+1WJm0COMXSxWEggZzswdpYcU/+4j3yJofs0ZMr7u6dkC0kcYea7NGUPVZmjLEhlQXZDFCvo5W3bIAiCdZYjoG7asIMclp/ATyqkRwKmF1GvPLge9czzR/IoZjvujh5SH5TDJwj7V7j49YDXP/+u9PsB55//4P2HG3y8/Y7rm69kv0mx/+nuHpdX16PBPFpsBY4fohBnyPtTacvFS1TiBM/qBk0rUDcd6rYn21Ns5edFNc5wOHAPuBfHyyUW8znmPBD6ZxRZAsuyaOlt2WOHBseyKcbnzSWXGarD18a0ZJbuLJLSDRMTWl5+2X7xF2h1n/UPj2zT8Hr9WgoAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"SolidJS Performance\"\n        title=\"SolidJS Performance\"\n        src=\"/static/9fa1169a9f82c81354ea851118fac952/e5715/solidjs-performance.png\"\n        srcset=\"/static/9fa1169a9f82c81354ea851118fac952/a6d36/solidjs-performance.png 650w,\n/static/9fa1169a9f82c81354ea851118fac952/e5715/solidjs-performance.png 768w,\n/static/9fa1169a9f82c81354ea851118fac952/5440e/solidjs-performance.png 1419w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span> </p>\n<p>If you wish to dive deeper into these stats and take a closer look at performance benchmarks, <a href=\"https://krausest.github.io/js-framework-benchmark/current.html\">here's a comparison guide you can refer to</a>. </p>\n<h3 id=\"solid-is-truly-reactive\" style=\"position:relative;\"><a href=\"#solid-is-truly-reactive\" aria-label=\"solid is truly reactive permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Solid is Truly Reactive</h3>\n<p>Reactivity lies at the heart of SolidJS, which is why you'll never find any unnecessary renders of your Solid components. Only the part of a template that needs to update will re-render.</p>\n<p>With React, however, change in a state leads to re-rendering the entire component. There are ways to combat this, but it needs additional efforts to learn and incorporate these concepts into your applications.</p>\n<h3 id=\"community-support-documentation-and-resources\" style=\"position:relative;\"><a href=\"#community-support-documentation-and-resources\" aria-label=\"community support documentation and resources permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Community Support, Documentation, and Resources</h3>\n<p>Even though Solid has excellent and extensive documentation, the React community is much larger since it has been around for longer. That can be a deal-breaker if you want to build scalable web applications quickly. Even third-party libraries are short in number for Solid in comparison to React.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>Solid has an exciting future and is worth a side-project or an MVP for your startup. If you wish to explore Solid in-depth, you can check out an official tutorial by the Solid team <a href=\"https://www.solidjs.com/tutorial/introduction_basics\">here</a> that walks you through every concept in Solid. You can also <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/SolidJs/todo-app-solidjs\">explore the entire code for the demo in this tutorial here</a>. Until next time!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"date":"June 28, 2022","updated_date":null,"description":"In this tutorial, you’ll learn what SolidJS is, how it works, and its fundamentals such as reactivity, architecture, events, effects, etc. Then you’ll use this knowledge to build a simple todo app. Finally, you’ll understand how SolidJS compares with React and how it’s better and worse.","title":"Introduction to SolidJS","tags":["SolidJS","React","Frontend"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7699115044247788,"src":"/static/06f459d4c67e0e9c2b5f26d0b5c1a042/ee604/introduction-to-solidjs.png","srcSet":"/static/06f459d4c67e0e9c2b5f26d0b5c1a042/69585/introduction-to-solidjs.png 200w,\n/static/06f459d4c67e0e9c2b5f26d0b5c1a042/497c6/introduction-to-solidjs.png 400w,\n/static/06f459d4c67e0e9c2b5f26d0b5c1a042/ee604/introduction-to-solidjs.png 800w,\n/static/06f459d4c67e0e9c2b5f26d0b5c1a042/f3583/introduction-to-solidjs.png 1200w,\n/static/06f459d4c67e0e9c2b5f26d0b5c1a042/5707d/introduction-to-solidjs.png 1600w,\n/static/06f459d4c67e0e9c2b5f26d0b5c1a042/9ddc6/introduction-to-solidjs.png 2240w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Siddhant Varma","github":"FuzzySid","avatar":null}}}},{"node":{"excerpt":"Introduction Currently, the LoginRadius Identity Platform processes more than 100K requests per second. As our developer and enterprise…","fields":{"slug":"/engineering/why-we-rebuilt-loginradius-dot-net-core-apis-with-go/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>Currently, the LoginRadius Identity Platform processes more than 100K requests per second. As our developer and enterprise customers grow, we should be able to scale our APIs to handle staggering loads of requests per second. It won’t be surprising if our APIs have to serve a million requests per second in the future.</p>\n<p>Generally, we add more instances, CPU, or memory for supporting high request volumes. However, it has been burdening our infrastructure budget and maintenance. </p>\n<p>So, we’re focused on reducing the cost of compute capacity by improving efficiency. In this engineering update, we share our experience with a highly effective, low-risk, large-scale performance and cost optimization with Go.</p>\n<p>LoginRadius production environment consists of 30+ microservices backed by a cloud-native infrastructure. Most of these services are written in .NET and Node.js. In Q1 2021, we explored the possibilities of improving the performance of our services and optimizing costs.</p>\n<h2 id=\"how-loginradius-has-been-handling-high-rps-throughput\" style=\"position:relative;\"><a href=\"#how-loginradius-has-been-handling-high-rps-throughput\" aria-label=\"how loginradius has been handling high rps throughput permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How LoginRadius Has Been Handling High RPS Throughput?</h2>\n<p>LoginRadius tech stack consists of 30+ microservices. We have different microservices for each business service like Authentication, Web SSO, Federated SSO, etc. </p>\n<ul>\n<li>We have developed application microservices in various languages per the prevailing microservice use case.</li>\n<li>We have deployed our application in a multi-cloud environment across AWS, Azure, and Google Cloud by leveraging multiple availability zones and regions.</li>\n</ul>\n<h3 id=\"1-architecture\" style=\"position:relative;\"><a href=\"#1-architecture\" aria-label=\"1 architecture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Architecture</h3>\n<p><strong>Core Applications:</strong> Multiple microservices instances for Authentication, Account API, Analytics API, Risk-based Authentication, Backend Jobs, Integrations, and much more, </p>\n<p><strong>Data Storage:</strong> MongoDB, Elasticsearch, Redis, and PostgreSQL clusters are used to store a range of datasets for various applications and functionalities.</p>\n<p><strong>Queues:</strong> Amazon Kinesis Data Streams, Amazon Simple Notification Service (SNS), Amazon Simple Queue Service (SQS), and Azure Queue Storage. </p>\n<p><strong>Other Services:</strong> Services for rate-limiting, bcrypt clusters, feature flags, and more.</p>\n<p><strong>Routing:</strong> AWS load balancers (ALB, NLB, and ELB from AWS) and some nodes running NGINX as a proxy.</p>\n<h3 id=\"2-availability\" style=\"position:relative;\"><a href=\"#2-availability\" aria-label=\"2 availability permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Availability</h3>\n<p>We've been utilizing a multi-cloud and multi-region architecture for years based on our and our customers’ data and privacy compliance requirements. However, as our usage (and load) grew with maintenance costs, we relied more on AWS resources.</p>\n<ul>\n<li>We are using multiple regions and multiple availability zones as per region.</li>\n<li>We are using terraform scripts to provision new environments. This infrastructure automation allowed us to quickly scale from thousands of requests per second to hundreds of thousands of requests per second.  </li>\n</ul>\n<p>This is the basic architecture of the environment in the US:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 15.4296875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAlUlEQVQI1zWLQRKCMBAE+f8vQAX1ESggjwDxImiyF5KCQEII0d2y3MPUTHVvYJfFb865FXMcB2O09zS3bcWz1mIh6olqPX/IJtkuNuhHs8v4IYNzycKUxTmcShalkBSATyDm8MLDFI43luQ8unKk+wziAqQywaCmupN1Kx5vWbXi3slfaV5SayMHotWTZvPX0MGppvkLvYyhgHN+S1QAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Basic Architecture - US\"\n        title=\"Basic Architecture - US\"\n        src=\"/static/a923ca30b0d5aa1a50a3b7c684cb6358/01e7c/basic-architecture.png\"\n        srcset=\"/static/a923ca30b0d5aa1a50a3b7c684cb6358/01e7c/basic-architecture.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Each request is processed as follows:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 99.8046875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAACuUlEQVQ4y41UC0/bMBDu79+kPbSJirExYBpDtAP6QEKFlQIlpfQFfVFoSGnaPNu8mjRxbCeZA4PBYILTyb4o9/m+O58vghD2Honve/UrNXksMuIkCHz8hIuHEIqQLbgn/vXqQLy8x35cO9ssS0HwwOFOMMb/gu8OKV9qawXxnJuEH/6Lwb7vAwQdCIbyyA0NCDF+HnzLGa0dcbFDYXGr9SPHrOTF467yOP7TkUm5FNNWLUdQdFE1iG067ktpE5InPa3WM/L1QfFMrDCTK9m64/UMbQDRZkVIFPlY7nw9z6wVxSqjvpR2+MNDXuBZto0wwj72/P8UjDQAOZIoaQ0HuNB1DctZ2buYT9fmNkrzqern9GmZlgMPOQC4ruvfEngQGSGIIQg8DAD41RBThasURacLTKo4aLNq4EOMIHCmtj39C1ZNZ6BMBQ1cDpW+ZIi6y6mO7bq3Vx7GGSpWuiJlTscbVC+e62xVpVRJqjHjCHUmf9oeLuyw0WQrmmov7PKzGZYWwsYiiRAlRn9kxSguURRj+73VXDdxxMcpoXQhR2TdpgWTEcwup9OcwYgWzZumDR/fzXVqyHXBEznbNiHrXmPCCt62argqE6fYEWq0XOzwh/V+lRhnPCNoEarNzyQas4nazHrlQ6wwlzqNJuuXonHTat41+pzT364338err79Tr77tv1stvfnZ3DkZRDpDfftklCmxaaq7SdHZmrh9Iguafb8ryAuVJ3BsQkGd8oqlmHBkQn0KIgBCQOZBEBjWdAoA8siTCufD/VTJUyGuJkAj3RTGOjEM2zUIONuQlg+klT32y2ZjMdONU9JSbnjB/6F9E7zWUz/vDJd2B9Fkg+hilv2a5dJlPtLsK1RnTLXF/VM23+SL5+ODtsSNw+lDaosw9j0sahaZSi1Wa/RGjatxi1WbfY3mtd8Y8VbURh2MPQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Request Processing Flow\"\n        title=\"Request Processing Flow\"\n        src=\"/static/dc681ebd4fc2e915584560a49dea681e/01e7c/request-processing-flow.png\"\n        srcset=\"/static/dc681ebd4fc2e915584560a49dea681e/01e7c/request-processing-flow.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>The above diagram shows two cloud regions — US East and US West.</p>\n<p>When requests come:</p>\n<ul>\n<li>First, our infrastructure checks the primary region's health. If health is good, all requests are served by the primary US East region with three separate availability zones. </li>\n<li>If health checks fail for the primary region, the US West region serves all the requests with three separate availability zones.</li>\n</ul>\n<p><strong>So, how do we maintain high availability?</strong></p>\n<p>Every availability zone has operating instances of all services (including databases). If one availability zone is down, we still have two availability zones.</p>\n<h3 id=\"3-scaling\" style=\"position:relative;\"><a href=\"#3-scaling\" aria-label=\"3 scaling permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Scaling</h3>\n<p>We are using a two-pronged scaling approach as scaling based on resource utilization (CPU &#x26; Memory) alone is not practical.</p>\n<ol>\n<li>Traffic-based scaling</li>\n<li>Based on CPU &#x26; Memory utilization</li>\n</ol>\n<h4 id=\"why-scaling-was-challenging\" style=\"position:relative;\"><a href=\"#why-scaling-was-challenging\" aria-label=\"why scaling was challenging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Scaling Was Challenging?</h4>\n<p>Once, our multi-tenant application received a sudden spike in API requests — from thousands of requests to millions. Usually, adding new infrastructure to the existing pool takes around 60 seconds. And application deployment and start-up time were about 90 seconds. Plus, considering other possible delays in scaling, we can lose about 5 minutes for scaling up.</p>\n<p>Further, adding the time to gather metrics and make the scaling decision, the total delay can be ~6 minutes. This process can impact all multi-tenant customers' critical applications because user authentication and authorization are essential.</p>\n<p>We keep <em>Scaling Buffers</em> to support this kind of scenario.</p>\n<blockquote>\n<p><strong>Scaling Buffers:</strong>  During the <em>Scale-up Time</em>, the <em>Scaling Buffer</em> is the service's highest predicted traffic spike. Depending on the scaling strategy, we store several types of the buffer.</p>\n</blockquote>\n<p>Usually, we set a one million requests concurrency buffer. And based on the traffic pattern, our scaling automation triggers the scaling.</p>\n<h2 id=\"why-our-platform-performance-was-good-but-not-great\" style=\"position:relative;\"><a href=\"#why-our-platform-performance-was-good-but-not-great\" aria-label=\"why our platform performance was good but not great permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Our Platform Performance Was Good, But Not Great?</h2>\n<p>Our Platform performance is good. We can quickly handle millions of requests, and our application platform was scalable but not great. Minding the kind of growth we’re expecting, we wanted to improve and prepare our platform for the future.</p>\n<h3 id=\"challenges-in-the-existing-platform\" style=\"position:relative;\"><a href=\"#challenges-in-the-existing-platform\" aria-label=\"challenges in the existing platform permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Challenges in the Existing Platform</h3>\n<h4 id=\"1-startup-time\" style=\"position:relative;\"><a href=\"#1-startup-time\" aria-label=\"1 startup time permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Startup Time</h4>\n<p>No. of requests can fluctuate within a few seconds if not minutes or hours, especially with specific events such as holiday shopping, promotional events, Black Friday, etc. So, in the event of traffic spikes, application startup time plays a significant role in scaling.</p>\n<p>Our application startup time was around 90 seconds, so whenever scaling was happening due to high traffic, scaling took more time. That's why we needed to improve the application startup time.</p>\n<h4 id=\"2-cost\" style=\"position:relative;\"><a href=\"#2-cost\" aria-label=\"2 cost permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Cost</h4>\n<p>We used hundreds of <em>AWS c5.2xlarge</em> instances in a production environment to handle daily traffic. During certain events such as holiday shopping and Black Friday, we doubled our infrastructure according to expected traffic with a 20~30% buffer. We kept a high buffer because scaling took time with the existing .NET Core services. As a result, infrastructure cost was burdening as we were inefficiently deploying cloud infrastructure.</p>\n<h4 id=\"3-lack-of-flexibility-and-customization\" style=\"position:relative;\"><a href=\"#3-lack-of-flexibility-and-customization\" aria-label=\"3 lack of flexibility and customization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Lack of Flexibility and Customization</h4>\n<p>We designed our Identity Platform a few years ago. Since then, the technology landscape has dramatically improved and optimized in recent years. </p>\n<p>Also, current technology platforms available to build and support our product (Identity Platform) are limited. So, it is crucial to align functionality with proper technology capabilities.</p>\n<p>We were facing challenges in customization. It was inflexible and limiting to deliver the required outcomes in more complex situations and use cases.</p>\n<h2 id=\"the-road-to-lightning-performance-thanks-to-go\" style=\"position:relative;\"><a href=\"#the-road-to-lightning-performance-thanks-to-go\" aria-label=\"the road to lightning performance thanks to go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Road to Lightning Performance, Thanks to Go</h2>\n<h3 id=\"why-go\" style=\"position:relative;\"><a href=\"#why-go\" aria-label=\"why go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why <em>Go</em>?</h3>\n<p>We did a lot of research to choose the appropriate programming language for our application. We needed a language that would be simple to understand and learn, easy to maintain, and has high concurrency. Our research ended with Go due to its amazing qualities.</p>\n<p>Let's take a closer look. <em>Why choose Go? What makes Go such an excellent development language? What distinguishes it from the competition?</em> </p>\n<p>Let's get to the bottom of this by looking at what makes Go special.</p>\n<h3 id=\"go--background\" style=\"position:relative;\"><a href=\"#go--background\" aria-label=\"go  background permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Go — Background</h3>\n<p>Go is an open-source programming language developed by Google's Rob Pike, Robert Griesemer, and Ken Thompson. It was initially released in 2009. It has several enhancements and additions based on the C syntax to properly control memory use, manage objects, and enable static or strict typing along with concurrency.</p>\n<h4 id=\"1-concurrency\" style=\"position:relative;\"><a href=\"#1-concurrency\" aria-label=\"1 concurrency permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Concurrency</h4>\n<p>Concurrent code can be executed in parallel by separate computer cores or in sequence. Most programming languages lack concurrent execution when working with multiple threads. They often slow down programming, compiling, and execution.</p>\n<p>Go works with goroutines that are lightweight, low-cost threads. And Go channels allow goroutines to communicate with one another. </p>\n<p>Sequential Processes Communication: They are very similar to threads in Java but lightweight, and the cost of creating them is meager.</p>\n<h4 id=\"2-performance\" style=\"position:relative;\"><a href=\"#2-performance\" aria-label=\"2 performance permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) Performance</h4>\n<p>Go's core value is simplicity: it builds quickly, runs quickly, and is simple to learn. To help speed things up, there are no classes or type inheritance. This makes it easier to build a market-ready product quickly. Furthermore, its simplicity allows for quick and simple maintenance.</p>\n<h4 id=\"3-standard-library\" style=\"position:relative;\"><a href=\"#3-standard-library\" aria-label=\"3 standard library permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Standard Library</h4>\n<p>Go has an excellent standard library that includes a large number of built-in essential type functions and packages that are both practical and straightforward to use: I/O, encoding and decoding, manipulating raw bytes, network utility functions, parsing, debugging, and a lot more are all made simple by particular packages. Testing support is also included in the standard library, so no other dependencies are required.</p>\n<h4 id=\"4-easy-to-learn\" style=\"position:relative;\"><a href=\"#4-easy-to-learn\" aria-label=\"4 easy to learn permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4) Easy to Learn</h4>\n<p>Go has a simpler syntax than other languages and is simple to learn. The syntax of Go is somewhat similar to the C language. Developers can begin with Go in a couple of hours, but they need to spend time understanding best coding practices, especially understanding goroutines for concurrency.</p>\n<h2 id=\"benchmarking-api-performance-gains\" style=\"position:relative;\"><a href=\"#benchmarking-api-performance-gains\" aria-label=\"benchmarking api performance gains permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Benchmarking API Performance Gains</h2>\n<p>We run benchmarks on our API so that the performance insights help us make decisions about the tech stack. It will paint a clearer picture of where we stand compared to our existing tech stack and what areas need improvement or immediate attention. </p>\n<p>We did multiple stress tests on our high usage APIs built separately with .NET Core(Old) and Go (new). </p>\n<p>We are using Kubernetes to deploy and manage our microservices and application infrastructure and deploy our application microservices across multiple Pods.</p>\n<h3 id=\"stress-test-scenario\" style=\"position:relative;\"><a href=\"#stress-test-scenario\" aria-label=\"stress test scenario permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stress Test Scenario</h3>\n<table>\n<thead>\n<tr>\n<th>Test Item</th>\n<th>Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Instance Type</td>\n<td>c5.2xlarge on AWS</td>\n</tr>\n<tr>\n<td>No. of Instances</td>\n<td>20</td>\n</tr>\n<tr>\n<td>Reverse Proxy</td>\n<td>NGINX</td>\n</tr>\n<tr>\n<td>Concurrent Requests</td>\n<td>20K per second</td>\n</tr>\n<tr>\n<td>Duration</td>\n<td>5 minutes</td>\n</tr>\n<tr>\n<td>Stress Test Tool</td>\n<td><a href=\"https://gatling.io/\">Gatling</a></td>\n</tr>\n</tbody>\n</table>\n<p>We deployed both applications in the same infrastructure and did the same stress test.\nGolang application has performed much better.</p>\n<h4 id=\"existing-application-matrix--net-core\" style=\"position:relative;\"><a href=\"#existing-application-matrix--net-core\" aria-label=\"existing application matrix  net core permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Existing Application Matrix — .NET Core</h4>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 34.375%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABS0lEQVQY02VQXUvDMBTtn9+zCIK6Ca5sIFgQX4ZDfZqyl21siDp09mtZ27S1adeuH0ma1tupIHgIh3OTe88NRyp+QSlNkmS1Wum6rmkaCGDQqqr6vlcUeZalGVCeUVrAPcauxDkvy7LaQ4gSHigDHzAD0WjGSyHqv8jyapeyPM+lNE0ZZ1Vd7c9/gGO+Y2GQoq2+WETj5VxxZrOU1bBCiuO4Fj9TQtAM+gprnSyfyXjs3Qxt5QrJPfNYfjuYKq2jzeHgrvXy2GE1DDOJM66T17k/GtmDoaVco/6FcSYbnZ4J3G4EOu+j7qXefRid9Cz5dtK+n56a5KlkQoKFEQtRuHZi693eoAB7EXIDw4hMh9huiLGlYWLhCEPpxW6Q+JjYCY0hrCawCvIqm29jp8LOrojsgqCP0CCfwTbcZqpOXD8kEae8FjU0fzMk+gW3onx90KKwEAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Requests and Responses per Second (.NET Core)\" title=\"Requests and Responses per Second (.NET Core)\" src=\"/static/065af3c1452371eeef2cc2e9c6eecd81/01e7c/requests-and-responses-per-second-dot-net-core.png\" srcset=\"/static/065af3c1452371eeef2cc2e9c6eecd81/01e7c/requests-and-responses-per-second-dot-net-core.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 1(a): Requests and Responses per Second (.NET Core)</figcaption>\n</figure>\n \n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 33.7890625%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA6ElEQVQY042QzW7DIAzHef/n2GGXqn2FXSat0lRVmrRTliYpUZSlHoGEr2CoabepvdVY5sffNjKwrusAfuYb01qP41gUxeFQ1XVdliVx33+TPk25YNIzgTGG0WatXe7NOSeEkFIqJekiYuoMIVyz6ANioBpGOURMj1m8xNct9KNPCZlSCmN8uDmvp5e3ze6dgAFA8Dqhyx5sRBudyRBs+nXSXT6iQ7TJ+NXH+pmv0xLZ4v2iBwXHWbRqaCbgglfq1MzA5dBcFIq1puzpKPvKQvvJ91+ujQHZdR7M4yT8h3jn8Zb/nk7/dwaRrZNa00I0hQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"API Response Time (.NET Core)\" title=\"API Response Time (.NET Core)\" src=\"/static/10602d758e3df688d22b7e79cfa22e5f/01e7c/response-time-percentiles-dot-net-core.png\" srcset=\"/static/10602d758e3df688d22b7e79cfa22e5f/01e7c/response-time-percentiles-dot-net-core.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph -1(b): API Response Time (.NET Core)</figcaption>\n</figure>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 7.8125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAYElEQVQI1zWIyw6AIAzA/P9f83nzKAoXM1FQBgxC4jCx6aFpU0qxxsABIYT0QYmujxhjzplP/CEi7z0AaH0iYjPv1Il7Ujgq7LeHnSSHq73eo3SDdP1quauiRidsyy7mBd6/bjpuZavGAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Overall Matrix (.NET Core)\" title=\"Overall Matrix (.NET Core)\" src=\"/static/bd266c07f16fd3b1904ef569a8ca6425/01e7c/overall-matrix-dot-net-core.png\" srcset=\"/static/bd266c07f16fd3b1904ef569a8ca6425/01e7c/overall-matrix-dot-net-core.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 1(c): Overall Matrix (.NET Core)</figcaption>\n</figure>\n<p>You can see some errors in Graph - 1(a) after ramping up to 15K users. Also, response time is increasing, as seen in Graph - 1(b).</p>\n<p>The application can recover after a couple of seconds, and after that, the application cannot respond. Application scaling is taking time. And existing infra cannot handle this spike, so the application crashes after 18K RPS.</p>\n<h4 id=\"new-application-matrix--go\" style=\"position:relative;\"><a href=\"#new-application-matrix--go\" aria-label=\"new application matrix  go permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>New Application Matrix — Go</h4>\n<p>We did the same stress test with the new Go application. It is easily able to handle this kind of concurrency without any issue. </p>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 34.1796875%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABVElEQVQY012QS2vCQBSF8/8XRQtFkdQo1toKhS50UaQUWrAtXbrRqpOXMZPEPBwfmcyzk5RuerhcDnPPxx2uhv9UFMXxeFwsvk3TXAOwXK4AAJVfh1GY4/yUn/MyRljBLWCHYaQpjFIqlDjnjOECF0QFcGUIpepRSi5/JSjJCdqdNjFy1byCGRVSqJL/JDihhwz7LprP4ukrHI+9+wfHaIGLj3AimdQQOgheYYJhihIVPcxnyfQNjsbbu6FzbYB606w1Qa2hunmpW1cNs/4ePZUwJdSMZ1/h88R7HHmDoaN3rVbH1m9svWvrPafd93oDtztwO7eO0bfbqhtW8zN8KWG1EpHMy7zoGKy2vhsFUeJEsQVSy4+3MPEDd+XvNjCFQQZ3hyg5xcoUvLyUVl6LCcHKj0MofB/hPcSpt86cNElRhs7A2sdJlu5pQQWXZZhLzjgh5AfSS3h3N+xolgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Requests and Responses per Second (Go)\" title=\"Requests and Responses per Second (Go)\" src=\"/static/da6febfd92d89610654f4c6c921720cd/01e7c/requests-and-responses-per-second-go-lang.png\" srcset=\"/static/da6febfd92d89610654f4c6c921720cd/01e7c/requests-and-responses-per-second-go-lang.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 2(a): Requests and Responses per Second (Go)</figcaption>\n</figure>\n \n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 33.984375%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA70lEQVQY02VQy26DMBD0/39Jz/2A9lT1klNPLRIhisLDjgFjGxu8XqcLtCppRmNp1zsj7Q67lCXn3O8wTZPWOsuyPM+LosiP+VeWcSHmeXbO7ZWMXgghPQAAIgHASbPVjwJmjEHE24K08g4Ykb+XaP06T3vNYrbWYvrv+TNDOr7U/jz4Uv/6b3fmYLvoe7AtMbr+h16BlTDKw9Pb6fmjev0EI4MSoASJcR7pFEbb42Ss4qMSpm3ccKXCDdJrSe3YNz0/t6eLrhotKnOtXcd1VyfwFAMLECAixAS4cqsX0r3LDwVCkUTaE1PcSFOIFP43k/CT9PPUbq4AAAAASUVORK5CYII='); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"API Response Time (Go)\" title=\"API Response Time (Go)\" src=\"/static/ac8ce361632cba137c0e2d02aef53c6a/01e7c/response-time-percentiles-go-lang.png\" srcset=\"/static/ac8ce361632cba137c0e2d02aef53c6a/01e7c/response-time-percentiles-go-lang.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph -2(b): API Response Time (Go)</figcaption>\n</figure>\n<figure align=\"center\">\n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 512px; \">\n      <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 7.03125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAABCAIAAABR8BlyAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAQklEQVQI1x3IQQ6AIAwAMP//RKPRgYJsDhyDKDeIt6aTfz4gZW1XIINiY7VczV1WnwD1TO/wjnkYKC8uzgdvQf6UDpLGNvVCnefiAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"></span>\n  <img class=\"gatsby-resp-image-image\" alt=\"Overall Matrix (Go)\" title=\"Overall Matrix (Go)\" src=\"/static/397ef4b4903cbbacdb16a5ab45b0f16f/01e7c/overall-matrix-go-lang.png\" srcset=\"/static/397ef4b4903cbbacdb16a5ab45b0f16f/01e7c/overall-matrix-go-lang.png 512w\" sizes=\"(max-width: 512px) 100vw, 512px\" style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\" loading=\"lazy\">\n    </span>\n  <figcaption> Graph - 2(c): Overall Matrix (Go)</figcaption>\n</figure>\n<p>The Go application can easily handle 20K ramp-up requests per second without any issue, as shown in Graph -2(a).</p>\n<p>You can see in Graph - 2(b) what the response time was after 2 min 47 sec for a couple of seconds. The Go application was scaling during that time. It is scaling quickly, so it is not impacting API request performance, and, also, the application can recover response API time as expected. </p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this article, you have learned how we have achieved better API performance by rebuilding them in Go, which were previously built in .NET Core. And you have understood our approach to this transition and how it increased the API performance of the LoginRadius Identity Platform.</p>\n<p>Leverage LoginRadius Identity Platform to build authentication functionality for your web and mobile apps. <a href=\"https://accounts.loginradius.com/auth.aspx?action=register\">Sign up for a free LoginRadius account here</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"June 06, 2022","updated_date":null,"description":"At Loginradius, we strive to leverage technology and ingenuity to push the boundaries of what our Identity Platform can deliver. In this engineering article, learn how we improved the performance of our APIs with Go.","title":"Why We Re-engineered LoginRadius APIs with Go?","tags":["Go","API",".NET","LoginRadius"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/b63787a6ecfda78c022020fe03233557/ee604/high-performance-identity-apis.png","srcSet":"/static/b63787a6ecfda78c022020fe03233557/69585/high-performance-identity-apis.png 200w,\n/static/b63787a6ecfda78c022020fe03233557/497c6/high-performance-identity-apis.png 400w,\n/static/b63787a6ecfda78c022020fe03233557/ee604/high-performance-identity-apis.png 800w,\n/static/b63787a6ecfda78c022020fe03233557/f3583/high-performance-identity-apis.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vijay Singh Shekhawat","github":"code-vj","avatar":null}}}},{"node":{"excerpt":"B2B applications require connecting customers and partners with their existing identity system or directory. Customers often want their…","fields":{"slug":"/engineering/identity-management-for-b2b-companies/"},"html":"<p>B2B applications require connecting customers and partners with their existing identity system or directory. Customers often want their employees or end-users to access your product and service with hierarchical access rights and their existing identity.</p>\n<p>Managing these requirements in-house can be tricky and time-consuming. However, the LoginRadius B2B Identity solution can bridge this gap for your business and help you eliminate friction. Above all, it serves a faster go-to-market with an industry-leading deployment time of 3-4 weeks while ensuring the following:</p>\n<h2 id=\"easy-onboarding-and-administration-delegation\" style=\"position:relative;\"><a href=\"#easy-onboarding-and-administration-delegation\" aria-label=\"easy onboarding and administration delegation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Easy Onboarding and Administration Delegation</h2>\n<p>LoginRadius B2B Identity allows your customers and partners to effectively create their accounts without needing them to create another identity. </p>\n<p>This feature lets you give customers and partners authority to manage accounts and access via their internal identity sources or your dashboard.</p>\n<p>Let’s say: your customer wants to allow only marketing and sales employees of the organization to access your B2B application. And within those 20 employees, the access rights will be different. LoginRadius B2B Identity can allow your customer to use their internal identity for authentication and manage the provision and access of their employee accounts within their identity source. </p>\n<p>Similarly, suppose some customers do not want to use internal identity for authentication and authorization. In that case, they can easily do this via managing configurations like login method, roles, and permission from your application dashboard. LoginRadius B2B Identity works in the background to smoothly process these requirements.</p>\n<h2 id=\"maintenance-free-sso-protocols-integration\" style=\"position:relative;\"><a href=\"#maintenance-free-sso-protocols-integration\" aria-label=\"maintenance free sso protocols integration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Maintenance-free SSO Protocols Integration</h2>\n<p>To allow your customers and partners to use their internal identity for authentication, you must configure Federated SSO protocols depending on their identity application. With LoginRadius B2B Identity, you get effortless integration of the most popular and complex SSO protocols, such as SAML, JWT, and OAuth. </p>\n<p>Let’s say one of your customers wants to authenticate using Salesforce while the other prefers to utilize their AWS identities. You can utilize OAuth integration for authentication using Salesforce and SAML integration for authentication using AWS — without understanding both protocols’ complexity and in-depth implementation.</p>\n<p>Not just this, integration of these protocols is entirely maintenance-free; any required change or updates in protocols are taken care of by LoginRadius.</p>\n<h2 id=\"secure-and-unified-access\" style=\"position:relative;\"><a href=\"#secure-and-unified-access\" aria-label=\"secure and unified access permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Secure and Unified Access</h2>\n<p>Get a centralized view of all your customers and partners. You can easily manage their identities and access controls (roles and permissions) from the LoginRadius Dashboard or the LoginRadius Management APIs. </p>\n<p>Revoke access automatically upon user offboarding to ensure effortless access security to applications of your customers and partners. Similarly, it revokes customers’ and partners’ access rights to your application in case of churn or contract termination.</p>\n<h2 id=\"reduced-it-support-overhead\" style=\"position:relative;\"><a href=\"#reduced-it-support-overhead\" aria-label=\"reduced it support overhead permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Reduced IT Support Overhead</h2>\n<p>LoginRadius B2B Identity lets you delegate admin access to your customers and partners for seamlessly managing their employees and users. Consequently, it saves the efforts and time of your IT support team. </p>\n<p>Also, you can set up self-serve registration for your customers and partners, thus saving time in manually setting up their accounts. Similarly, these customers and partners can facilitate self-serve registration for their employees and users.</p>\n<h2 id=\"data-and-privacy-protection\" style=\"position:relative;\"><a href=\"#data-and-privacy-protection\" aria-label=\"data and privacy protection permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Data and Privacy Protection</h2>\n<p>The following built-in capabilities of LoginRadius CIAM lets you meet data regulations and protect customers’ and partners’ data privacy:</p>\n<ul>\n<li>Consent management</li>\n<li>Preference management</li>\n<li>Compliance features for GDPR, CCPA, etc.</li>\n<li>Privacy versioning</li>\n</ul>\n<h2 id=\"audit-logs-and-intelligence\" style=\"position:relative;\"><a href=\"#audit-logs-and-intelligence\" aria-label=\"audit logs and intelligence permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Audit Logs and Intelligence</h2>\n<p>LoginRadius Dashboard lets you access your application's audit logs of activities performed by customers and partners.</p>\n<p>Also, you can access 30 different analytical charts to understand your customer and partner base and engagement.</p>\n<h2 id=\"implement-b2b-identity-management-with-loginradius\" style=\"position:relative;\"><a href=\"#implement-b2b-identity-management-with-loginradius\" aria-label=\"implement b2b identity management with loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Implement B2B Identity Management with LoginRadius</h2>\n<p>The following explains the step-by-step implementation of LoginRadius B2B Identity:</p>\n<ul>\n<li>Set up organizations for your customers and partners</li>\n<li>Set up roles and permissions for the organization’s users</li>\n<li>Set up organization users and assign them roles</li>\n<li>Set up authentication methods for organizations and their users. </li>\n</ul>\n<blockquote>\n<p><strong>Note:</strong> To implement B2B Identity, you must have a <strong>Developer Pro account with LoginRadius</strong>. Create a <a href=\"https://accounts.loginradius.com/auth.aspx?return_url=https://dashboard.loginradius.com/login&#x26;action=register&#x26;plan=pro\">Developer Pro account here for 21 days of the free trial</a>.</p>\n</blockquote>\n<h3 id=\"step-1-organization-management\" style=\"position:relative;\"><a href=\"#step-1-organization-management\" aria-label=\"step 1 organization management permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1: Organization Management</h3>\n<p>These are your customers or partner organizations who need to access your application. You can create and manage these Organizations using the following APIs:</p>\n<ul>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Create Organizations</a>docs/references/api/b2b-identity/#create-organization)</p>\n<p>API Endpoint: <code>https://api.loginradius.com/identity/v2/manage/organizations</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Update Organizations</a>docs/references/api/b2b-identity/#update-organization)</p>\n<p>API Endpoint: PUT <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Remove Organizations</a>docs/references/api/b2b-identity/#remove-organization)</p>\n<p>API Endpoint: DELETE <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Update Organization Status</a>docs/references/api/b2b-identity/#update-status-of-organization)</p>\n<p>API Endpoint: PUT <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}/status</code></p>\n</li>\n</ul>\n<h3 id=\"step-2-roles-management-for-organization\" style=\"position:relative;\"><a href=\"#step-2-roles-management-for-organization\" aria-label=\"step 2 roles management for organization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2: Roles Management for Organization</h3>\n<p>These are the roles that organization users will have to access permission-based resources and processes. You can create, assign, and manage roles using the following APIs:</p>\n<ul>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Create Role</a>docs/references/api/roles-management/#roles-create)</p>\n<p>API Endpoint: <code>https://api.loginradius.com/identity/v2/manage/role</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Add Permission to Role</a>docs/references/api/roles-management/#add-permissions-to-role)</p>\n<p>API Endpoint: PUT <code>https://api.loginradius.com/identity/v2/manage/role/{role}/permission</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Remove Permission from Role</a>docs/references/api/roles-management/#remove-permissions)</p>\n<p>API Endpoint: DELETE <code>https://api.loginradius.com/identity/v2/manage/role/{role}/permission</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Set Roles for Organization</a>docs/references/api/b2b-identity/#addupdate-roles)</p>\n<p>API Endpoint: <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}/defaultroles</code></p>\n</li>\n</ul>\n<h3 id=\"step-3-user-management-for-organization\" style=\"position:relative;\"><a href=\"#step-3-user-management-for-organization\" aria-label=\"step 3 user management for organization permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3: User Management for Organization</h3>\n<ul>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Add User to Organization</a>docs/references/api/b2b-identity/#add-user-to-organization)</p>\n<p>API Endpoint: <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}/members</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Remove Users from Organization</a>docs/references/api/b2b-identity/#remove-users-from-organization)</p>\n<p>API Endpoint: DELETE <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}/members</code></p>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Get Organization Users</a>docs/references/api/b2b-identity/#organization-users)</p>\n<p>API Endpoint: GET <code>https://api.loginradius.com/identity/v2/manage/organizations/{id}/members</code></p>\n</li>\n</ul>\n<h3 id=\"step-4-login-methods-for-organization-users\" style=\"position:relative;\"><a href=\"#step-4-login-methods-for-organization-users\" aria-label=\"step 4 login methods for organization users permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Login Methods for Organization Users</h3>\n<p>You can allow organizations to use the organizational identity or ask them to create an identity for authenticating themselves.</p>\n<ul>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Set Global IDP for User</a>docs/references/api/b2b-identity/#set-global-idp-on-profile): Set a global Identity Provider authentication method from the already enabled authentication methods for your LoginRadius App. The global IDP will apply to organizations of all your customers and partners. </p>\n<p>For example: Login with Gmail, Login with Facebook, Login with Email-Password, etc.  </p>\n<p>API Endpoint: <code>https://api.loginradius.com/identity/v2/manage/organizations/{org_id}/members/{uid}/idp/global</code></p>\n<blockquote>\n<p><strong>Note:</strong> To show the global IDP to all organizations, turn the setting on via <a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">this API</a>docs/references/api/b2b-identity/#set-global-authentication-method-for-organization).</p>\n</blockquote>\n</li>\n<li>\n<p><a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">Create SAML Login for Organization</a>docs/references/api/b2b-identity/#create-organizational-saml-idp): Set a SAML authentication method specific to the customer or partner.</p>\n<p>For example: Login with Salesforce for one customer and Login with Azure AD for another customer. So, customers and partners can easily authenticate using their identity provider rather than creating a new identity.</p>\n<p>API Endpoint: <code>https://api.loginradius.com/identity/v2/manage/organizations/{org id}/idp/saml</code></p>\n</li>\n</ul>\n<h2 id=\"manage-email-communication\" style=\"position:relative;\"><a href=\"#manage-email-communication\" aria-label=\"manage email communication permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Manage Email Communication</h2>\n<p>You can manage the welcome email and related email communication for the organization users using LoginRadius Dashboard, <a href=\"https://www.loginradius.com/resource/loginradius-ciam-developers-whitepaper\">as explained here</a>docs/guide/manage-organizations/#manage-email-template-and-setting). </p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>Save on R&#x26;D, engineering resources, and maintenance by utilizing LoginRadius B2B Identity  — consequently, go to market faster.</p>\n<p>Create a <a href=\"https://accounts.loginradius.com/auth.aspx?return_url=https://dashboard.loginradius.com/login&#x26;action=register&#x26;plan=pro\">Developer Pro account here</a> to start your journey of eliminating authentication and access friction from your B2B business.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"May 31, 2022","updated_date":null,"description":"B2B companies need to manage identity differently to meet customer needs and deliver value efficiently while ensuring secure and seamless access. Read more to learn how your company can implement B2B identity management.","title":"Why B2B Companies Should Implement Identity Management","tags":["Identity","Access Management","B2B"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/40cc7e952a0e3c8722171d03a00830f1/ee604/b2b-identity-management.png","srcSet":"/static/40cc7e952a0e3c8722171d03a00830f1/69585/b2b-identity-management.png 200w,\n/static/40cc7e952a0e3c8722171d03a00830f1/497c6/b2b-identity-management.png 400w,\n/static/40cc7e952a0e3c8722171d03a00830f1/ee604/b2b-identity-management.png 800w,\n/static/40cc7e952a0e3c8722171d03a00830f1/f3583/b2b-identity-management.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Ravi Teja Ganta","github":"ravitejag","avatar":null}}}},{"node":{"excerpt":"What is a Cyber Attack? A cyber attack is a sequence of actions performed by a threat actor to obtain unauthorized access to a computer…","fields":{"slug":"/engineering/top-cyber-threats-in-2022/"},"html":"<h2 id=\"what-is-a-cyber-attack\" style=\"position:relative;\"><a href=\"#what-is-a-cyber-attack\" aria-label=\"what is a cyber attack permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is a Cyber Attack?</h2>\n<p>A cyber attack is a sequence of actions performed by a threat actor to obtain unauthorized access to a computer, computer network, or other computing systems to intentionally steal data, harm innocent people, or launch attacks from a compromised computer. To launch a cyberattack, cybercriminals utilize many methods, including phishing, ransomware, malware, man-in-the-middle attack, and denial of service, among others.</p>\n<h3 id=\"1-phising\" style=\"position:relative;\"><a href=\"#1-phising\" aria-label=\"1 phising permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1) Phising</h3>\n<p>Phishing is used to steal user credentials and sensitive data such as credit card numbers and social security numbers or install malware on a victim's machine. An attacker usually sends fraudulent communications that appear to be from a reputable source. Specifically, scammers send emails or text messages containing malicious links in a manner that seems to originate from legitimate senders. </p>\n<h3 id=\"2-dos-and-ddos\" style=\"position:relative;\"><a href=\"#2-dos-and-ddos\" aria-label=\"2 dos and ddos permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2) DoS and DDoS</h3>\n<p>Denial-of-Service (DoS) and Distributed Denial-of-Service (DDoS) attacks send malicious and spam requests to a system or network, severely restricting the ability to perform and serve legitimate users and requests. This attack is frequently used to set up another attack.</p>\n<h3 id=\"3-voice-phishing-or-vishing\" style=\"position:relative;\"><a href=\"#3-voice-phishing-or-vishing\" aria-label=\"3 voice phishing or vishing permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3) Voice Phishing Or Vishing</h3>\n<p>Vishing combines voice and phishing in which an attacker tricks a victim to steal personal and confidential information. It is a social engineering attack as it relies on psychology to convince victims to give sensitive information or perform an action for the attacker's benefit.</p>\n<h3 id=\"4-malware\" style=\"position:relative;\"><a href=\"#4-malware\" aria-label=\"4 malware permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4) Malware</h3>\n<p>Malware attacks are common types of cyberattacks in which malware (usually malicious software) performs unauthorized actions like stealing personal, financial, or business information on the victim's system. Malicious software is created in several forms, including ransomware, spyware, and command and control.</p>\n<h3 id=\"5-ransomware\" style=\"position:relative;\"><a href=\"#5-ransomware\" aria-label=\"5 ransomware permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>5) Ransomware</h3>\n<p>Ransomware is malware that threatens to expose or limit access to data or a computer system by encrypting valuable data or limiting system functionality. Cybercriminals demand monetary incentives (ransom) for releasing the system after encrypting or locking the data. A deadline is typically attached to the ransom demand. If the victim does not pay the ransom on time, the data will be lost permanently, or the ransom will be increased.</p>\n<h3 id=\"6-man-in-the-middle-attack\" style=\"position:relative;\"><a href=\"#6-man-in-the-middle-attack\" aria-label=\"6 man in the middle attack permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>6) Man-in-the-Middle Attack</h3>\n<p>A man-in-the-middle (MiTM) attack occurs when an attacker intercepts and distributes messages between two participants who think they are interacting directly and securely. Participants who send emails, instant messages, or video conferencing are unaware that an attacker has inserted themselves into the conversation and is collecting and manipulating their information.</p>\n<h3 id=\"7-brute-fore-attack\" style=\"position:relative;\"><a href=\"#7-brute-fore-attack\" aria-label=\"7 brute fore attack permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>7) Brute-fore Attack</h3>\n<p>A Brute-force Attack is an attempt to find a credential, such as a password, using computer-based automated trial and error. The attack involves automated spraying of all possible character combinations and lengths into a password field until a match. Brute-force attacks are successful when the authentication protocol of an online service complements this type of attack. Shared secrets between the service and the user provide the highest probability of success for a brute-force attacker.</p>\n<h3 id=\"8-iot-devices\" style=\"position:relative;\"><a href=\"#8-iot-devices\" aria-label=\"8 iot devices permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>8) IoT Devices</h3>\n<p>Any cyberattack that targets an Internet of Things (IoT) device or network is known as an IoT attack. Once the device has been hacked, the hacker can take control of it, steal data, or join a network of infected devices to execute DoS or DDoS attacks.</p>\n<h3 id=\"9-spyware--keyloggers\" style=\"position:relative;\"><a href=\"#9-spyware--keyloggers\" aria-label=\"9 spyware  keyloggers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>9) Spyware &#x26; Keyloggers</h3>\n<p>A keylogger is spyware that logs a user's activity by logging keystrokes. Every key pushed on the keyboard is captured and forwarded to a malicious actor when the spyware installs a keylogger on a device. As a result, the attacker will have access to data streams that help find user passwords and other sensitive information. Keylogger spyware is generally installed on the user's device by unintentionally clicking on a malicious link or attachment.</p>\n<h3 id=\"10-cross-site-scripting-xss\" style=\"position:relative;\"><a href=\"#10-cross-site-scripting-xss\" aria-label=\"10 cross site scripting xss permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>10) Cross-site Scripting (XSS)</h3>\n<p>Cross-site Scripting (XSS) attacks use third-party online resources in which malicious scripts are inserted into a legitimate website or application to obtain a user's information. Attackers commonly employ JavaScript, Microsoft VBScript, ActiveX, and Adobe Flash for XSS attacks. A web app is usually vulnerable to XSS attacks when it receives user input without validating or encoding it in its output.</p>\n<h2 id=\"to-conclude\" style=\"position:relative;\"><a href=\"#to-conclude\" aria-label=\"to conclude permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>To Conclude</h2>\n<p>Cyberattacks are becoming ever more common and sophisticated, mostly with financial motives.\nWhile preventative cybersecurity tactics vary by attack type, you should follow <a href=\"https://www.loginradius.com/blog/identity/cybersecurity-best-practices-for-enterprises/\">best security practices</a> and practice IT hygiene for mitigating these attacks.</p>\n<p>These cyber-threats are creating more emphasis to stack up security measures. You can follow these <a href=\"https://www.loginradius.com/blog/identity/tips-from-loginradius-security-expert-2022/\">Security Tips</a>, which are well-known among LoginRadius’s cybersecurity Experts.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"May 31, 2022","updated_date":null,"description":"Cybercriminals are using an increasing number of attacks to exploit web apps and steal valuable data. This article teaches about the ten most common types of cyber threats.","title":"Top 10 Cyber Threats in 2022","tags":["Cyber Threats","Security"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/92629222753ebb5a3139b4769d414041/ee604/top-10-cyber-threats-in-2022.png","srcSet":"/static/92629222753ebb5a3139b4769d414041/69585/top-10-cyber-threats-in-2022.png 200w,\n/static/92629222753ebb5a3139b4769d414041/497c6/top-10-cyber-threats-in-2022.png 400w,\n/static/92629222753ebb5a3139b4769d414041/ee604/top-10-cyber-threats-in-2022.png 800w,\n/static/92629222753ebb5a3139b4769d414041/f3583/top-10-cyber-threats-in-2022.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vijay Singh Shekhawat","github":"code-vj","avatar":null}}}},{"node":{"excerpt":"Web design and CSS have come a long way. And today, modern websites have everything you could wish for alongside stunning designs. Then why…","fields":{"slug":"/engineering/guest-post/modern-login-signup-form-tailwindcss-react/"},"html":"<p>Web design and CSS have come a long way. And today, modern websites have everything you could wish for alongside stunning designs. Then why should your website's login and signup forms look boring?</p>\n<p>The web ecosystem has tons of reliable third-party libraries and frameworks to help you build intuitive designs even if you're not a design wizard. Amidst the plethora of libraries comes a utility first CSS framework called <a href=\"https://tailwindcss.com/\">Tailwind CSS</a>.</p>\n<p>So in this post, you'll learn:</p>\n<ul>\n<li>what Tailwind CSS is;</li>\n<li>why it's awesome; and,</li>\n<li>how you can use it in a React app.</li>\n</ul>\n<p>I'll then walk you through step by step how to use it to create a modern login and signup form with routing in React.</p>\n<p>Finally, you'll see how to make these forms functional using <a href=\"https://www.loginradius.com/resource/whitepaper/loginradius-ciam-developers/\">LoginRadius Authentication APIs</a> docs/references/api/authentication).</p>\n<h2 id=\"what-is-tailwind-css\" style=\"position:relative;\"><a href=\"#what-is-tailwind-css\" aria-label=\"what is tailwind css permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Tailwind CSS?</h2>\n<p>If you've heard of Materialize and Bootstrap, Tailwind CSS is much similar in what it offers. It's a CSS framework that helps developers build layouts, components, themes, and whatnot, without writing all the CSS themselves.</p>\n<p>However, unlike Bootstrap and Materialize, it doesn't give you built-in components out of the box. Instead, it gives you a wide range of fully customizable utility classes that you can use to style your pages.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACn0lEQVQoz22SW08TURSF+wNUFEpbC7RQRLFcCgaIMSi3couAQklsmemEUlpKKZCoie++++SrD8aQYOIf8DeYIMYgd1IKbaEzreCjT59npqgx8WHN3jlnztp77bVNsbo80do8jys/8tC5wpB9hRHHe8Zcq0yY14g4z1ls0lAseSTLEcMVqwza34m4gtf6lvGyT8iWLIq1IKBh0j9SWY42xwzDQyMM9I4z7PXR2+Olp+wNTz0/eR0tEK44x2dep7fzEf09o3i7Rum+P0h/6Qek8ixTlpQomMEUtKoo5XkCpUdMlGzju7yH79IuvpIdZFuWYLnGtF10aNNErjJZss/EFf1+l8mruwTMSdFhmkB5SiApOhQPZMcJ/o5DZgZSLPRliLcKkjsnBCtFMYsgsqhF4gqVBXeBxcYCCfcZMXcK2bnOlPWbID0yZJuCNhV/exJf6wGBvh2U8S3kkS0CTYdIpaIzXYFA0FLMZ12nxOpzhGuP8VeuEW9OkWhOo1RtIFu3BeH1HIo9x9ItYc7tU2Zb00QbT0g05IjeKHb2mzDsVJmrK54rrk1iLZu8eHDKQlOaRU8GybauE6pM1QuSrhSRxiyxWpVoS4b5BkFe/ZdQKtMIVanEbqpE6tJMudZ41pliqU3v8IRQzbaQvoHpyd0D/P3CgLFt5OFdgv17KO0pZp0aM46iXH2OEZeQW6MaRcICiiOJ5PzKvGefZfF/wPrFMMckVWeZrs6R6D5mzpskdu+YuDvHcusp87dzxm7pcufF3JZahDwxirjAYrNKwpMl4t4h7P5M0L5PyJ4vuqzLkq8JlOoxj2zWDIl6DBrzU43cwMW5bFaNXH8bcmRZ8uTF3AsXe6jDpv5x9B8Y7mr/uSuuU6hS43nHd15JP3g5csYvp6AG8t8jLJkAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"TailwindCSS vs. Bootstrap Comparison\"\n        title=\"TailwindCSS vs. Bootstrap Comparison\"\n        src=\"/static/53e88d5c504fe9fe3dc546ca8b0da336/e5715/tailwind-css-vs-bootstrap-comparison.png\"\n        srcset=\"/static/53e88d5c504fe9fe3dc546ca8b0da336/a6d36/tailwind-css-vs-bootstrap-comparison.png 650w,\n/static/53e88d5c504fe9fe3dc546ca8b0da336/e5715/tailwind-css-vs-bootstrap-comparison.png 768w,\n/static/53e88d5c504fe9fe3dc546ca8b0da336/7b67d/tailwind-css-vs-bootstrap-comparison.png 2240w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"why-tailwind-css-better-or-worse-than-the-others\" style=\"position:relative;\"><a href=\"#why-tailwind-css-better-or-worse-than-the-others\" aria-label=\"why tailwind css better or worse than the others permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Tailwind CSS Better or Worse Than the Others?</h2>\n<p>The community loves Tailwind. For most developers, the key takeaway is that it gives you more freedom on how you want your components or elements to look. So in many cases, when developers use component-based CSS frameworks like Bootstrap, they have a hard time changing the way they want their website to look.</p>\n<p>Being utility first, it's the most customization-friendly CSS framework! </p>\n<p>Also, it's pretty easy to integrate with modern frontend frameworks like React, NextJS, VueJS, Angular, Svelte, etc. I'll also explore that shortly when we add Tailwind to our React app. </p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACLklEQVQoz2VTXWvTYBjtrbBN6ZI0W+0+pAVBhjLZwIvB0JuJm7DVfWRNmnSdWMQyZYyNguA2EUFEFHYr+C9kKqh3gleKovgxOl3bfEfw/vgkb5NavTh5wvs+73nPOU8SK2UsXElbUHtMKIKJfMKgamDpqIHtSRd3sx5uX3SD9zvTHu5JHpZS1MvryIsWFvkqFoV9qAmbzpqI+Q9GElYLcrdN1cb6GCPaPM9QGXdw85wDLUlEHFXOgCw0MM9/QU74STgICZtkvAlNrKGY+UG1CuVIHbMdBuY6dIKBhS5676ReroZS/1fMZhyoJEQW6pD4vQCRQh9S3MXOyiu8XtvC7sPneDD1FnOHXRSSOqkyoPXqmOd+YWfkGTYvPMbEqTqpDAVZAdoIZbK7evYdtsee4tbMZ5RP70HmKAI6JHVSDFRzhMrQJ5SH91FM0TlSqDRz9xGLFnxSWtBEF2rfb1LlYHmASHgriOD6xEdcPn4AOW5B6XVRSjso9psBSSs2GgojMttvogmyRgOXDpl4VNDxpLGL7I0XyHe5NF2dlJIjvp2MTZkGoVBGikibXGifbaoiWY3r2BjxUKq8waTyEmq3HUXk94RWI8tKDwV95huyUx8gD9YQXBA1M+Jin4mrgy7Kaa/5vbbIwou1JENMGqpiZvo9Fka/B0r/tp6PKhGLRnO9ZS/cWx4wsXLSxrUTFrOcO1aDnGqQZQtRpon/A/+XyK8FUrU6auN+zsMW/QR/AKmtFC5/kCD5AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"TailwindCSS Pros\"\n        title=\"TailwindCSS Pros\"\n        src=\"/static/4409d71c09a348492578a1acd7833fba/e5715/tailwind-css-pros.png\"\n        srcset=\"/static/4409d71c09a348492578a1acd7833fba/a6d36/tailwind-css-pros.png 650w,\n/static/4409d71c09a348492578a1acd7833fba/e5715/tailwind-css-pros.png 768w,\n/static/4409d71c09a348492578a1acd7833fba/7b67d/tailwind-css-pros.png 2240w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>On the downside, Tailwind might make your HTML bloated with loads of CSS classes for small and specific rules. However, you can control it with a framework like React by building smaller reusable components and using JSX bindings for long class names for more maintainability and readability. </p>\n<p>In fact, we'll take this optimal approach in building our Login form, so you'll understand some best practices you can use to avoid bloated HTML templates in your React app. </p>\n<h2 id=\"what-youll-build-today\" style=\"position:relative;\"><a href=\"#what-youll-build-today\" aria-label=\"what youll build today permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What You'll Build Today?</h2>\n<p>We'll create a simple yet modern looking login and signup form that looks like this:</p>\n<p><video controls width=\"700\" align=\"center\" src=\"/46886cf38c3148a337f29fc7cbf22acb/demo.mov\"> </video></p>\n<p>It will be interactive using React state, can route to different pages, and we'll also, in the end, talk about how we can make it functional from a backend standpoint. </p>\n<p>Sounds good? Let's start by understanding how we can add TailwindCSS to our React app. </p>\n<h2 id=\"project-setup\" style=\"position:relative;\"><a href=\"#project-setup\" aria-label=\"project setup permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Project Setup</h2>\n<p>Inside a directory of your choice, create a new React project by running:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npx create-react-app react-tailwind-app</span></code></pre>\n<p>Next, move inside the project and install react-router-dom by running:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">cd create-react-app react-tailwind-app && npm i react-router-dom</span></code></pre>\n<h3 id=\"install-tailwind-css\" style=\"position:relative;\"><a href=\"#install-tailwind-css\" aria-label=\"install tailwind css permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Install Tailwind CSS</h3>\n<p>Now, <a href=\"https://tailwindcss.com/docs/guides/create-react-app\">add Tailwind to your React project by following the steps given here</a>. </p>\n<p>First, install Tailwind CSS and its related dependencies by running the following command in the root directory:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npm install -D tailwindcss postcss autoprefixer</span></code></pre>\n<p>Next, generate some configurational files by running the following command in the root directory:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npx tailwindcss init -p</span></code></pre>\n<p>That should generate a <code>tailwind.config.js</code> file and <code>postcss.config.js</code> file for you as shown:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 496px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 362.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAABJCAYAAAA9mQYkAAAACXBIWXMAABYlAAAWJQFJUiTwAAAHGElEQVRYw+1YSY8k1REuDpYsJGQJW6CBXqoq932tLWvrmuruqa7pZXqWbmbMaHxqIWEOIMtsEuCbhQBLRgjZV+4IBIN/hH+AjTTD8ks+IiIrs6tqesQMXPsQeplZWd/7IuKLePle5dq1a2i1Wtjc3EQYhlBVDaZpwfN8OI4L3w/EdN2Q3zRNX7DimWGYMlaOjo5w+/ZtnJycIE1T1OsKms18gsFgiOn0Mi5dmsC2nYcC8mQ8uQDevHkTd+7cATMNgkBeUBQVtVpdRr7nSdiKex7ZCsDiGY+Vvb09cslHFEVizGQ83sStW3/E9es3iOkW9vcPcOPGDRwdHePFF29jZ2eK4+NjXL68SxMrC4wrDNJoNNDpdASQHzJ9vg4opjZd5/cxeRDK6LqemGXZD4RBAIfDocQsjmOhziw910fWzjDoDRBHCbKsi35/gI2NDbTbndJNcVsjt5Xc9UqSJOj1epJpBueHnDHTsWFFLuxmCCf0H0jGfFLkP44FTdcZMCa5UPziRNzhHx3LIaAY9mSA4GADVpsmqlPQ5wDmXZVMhwEBGjOGnTZaoYMozLNsEaDn6GhH69BVRdzh2ed1l5smpqo6Aofe1VVUYgK5uH+E/snf4DV70BSFhE3gnopxZwWWWkO9RuyqM+ASVFsA9O0ZYCNwER+eIPjgv7CGB9Cra1AdH2pnDKPbgD/tw+kl8C9lMHxHXM9BFxmbFCLNmLkckTy8KJVRXqCk6ARqRiSNXpPiQ9fNCLptlSxPQXOGumvnSeHMcoYzimNI14qik2xUDIbruNhaweHoWUz7FxCRS/Va4eZi/NKwil66Qi7PZLO7uyvVUcqGfohdDV5gIIk1UgElyjWgWaa4dZqYHNAwSBn8OwubG8L29rY0BnZZoRccemHirlJMW/D2RrDHGbxJj+LYhdNvnMaRQdUclEMiMeTq4FrmUUpPpZdNKqm4DTN04W40YSU+rDQQW2Q4lxRK7kzYCbrdLkajkYCqXE6WCyUZwG6F8CfEatiEM2jAHbXkT2cC0qTCkBvDlStXMJlMZjGkH00V3dYqTGIkDKn8rFa0ALA8siJKhswuyzIBVKRSKBlpFQbN6hI7O4vFNNM8s8lyHM3Qy0uP3eTGGkWhANapUnw7xuX2LVhZBG87g021zO5ajTCv6blaLkaJbwE4Ho+lLRWy4ZbeiTKZVVymlzm7DMh/YqbLbnMVicsMyF17Z2cnd1mErVHve47cTBDsD+GRXDg54eEIwd4A4ZUNMWbPcWbW7EUpG+7W7Xa7TIpuUPcIVBieIwlhpmbsy8hMdOqVzFKf9UDxip9p+nwMo5KhZSnY6K+Jm8xMbIeEPe0h2B2IjBRaS+ZjyROXDKfTqciG12XJGLV/VbdEKnYnptgFEj9pDktZLtflQtgMyCva4eFhDkj1qdsBuetKjJiZO27DvdiGQR1FWa1Bpf6orNfLElwQNgNytzldU3R0WuuIMwv2qCNZZjCnl8LuJvC2OnLtbXYkEQVoUZaVooYL4x99X4GbUEKylNwOBZTBpD9SGNi4FPm+6I+lbLhSuNtsbW3lDDVmWEPSc+BsdeGRu5wMcXtmrEVlrbbgcpkUBmQNcmIKl31fpaXTgtmIJDZ5YkKRjtQ0C3tp0WKJlUlpNpvy9cDlx7IZ9lYRd3OGvJawy04/lViyhFjsPM7X9gJDBi37IbvgxcSM4jRsCDuuY64aDjxXBkukEHLJ0J+TDYPKYsWA9FBpjGC2msQiEzAutyK7fK/QkiqymRd2keWCYQHILrcaVVoFDVidJO+FXH5J3rGZKWdcXNTPEPYDgJSUZqMGv+nIOpKLuiXlJpokhhw/6d5zy8FDGXKl1Orkdl0Tt8Q9tppyej27n29fRZ88A1A/XXt1/aFfXcu1XH4fngV4Zps/4/lZ7z0W4KPYOeA54DngOeA54DngOeCvA1z4+vrVgMU39uzcRls6k3lswHyvdxGbfdpJBV65u/zFgGkSY/fwOry/fAa7P4Ver+Vb/6VTpEe1Ssrf2Fkfq3/6kL5QJyXg8ouP5TIfXqSugTjwYZj09U8f46aMp8YHbI9icirC+7ztyY4khc8K+4Mhjo9foOc7uE7btk3aw/CJp+yVf44hbyn4zOHgYF+kw2eHadqg/XKftr2ZnBvyeaHJR4DmqcmR4NIztkpCe5N8n0J7EdejvbKFJG3ikCa5ShvKq1ev4WB/H2vrNTkeLUxV8nPZKl2vV+syslV++8pXWHvzG6yTKW//BzUaq298jSdf/hxPvfIF/vDql/jNS5+j9tY3WPnr17hA9hzZk3/+Er9/7Susv3EX6tv0nzfvYuX1u6hU3vkfLnx0H89+cA/Opz/A+9ePUD7+HpV3v8Xv/n4Pz3x4H5X3vkX1n9/jeXrv+X98J+8/8d7/8fT79+Td6N8/ok6j/skP+Anhob5P4VXOpgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"tailwind config files\"\n        title=\"tailwind config files\"\n        src=\"/static/9ced8f7783ffd5b9ebd9abab98363db4/bb630/tailwind-config-files.png\"\n        srcset=\"/static/9ced8f7783ffd5b9ebd9abab98363db4/bb630/tailwind-config-files.png 496w\"\n        sizes=\"(max-width: 496px) 100vw, 496px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Awesome!</p>\n<h3 id=\"configuring-tailwind-css\" style=\"position:relative;\"><a href=\"#configuring-tailwind-css\" aria-label=\"configuring tailwind css permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Configuring Tailwind CSS</h3>\n<p>Now, go ahead and update the <code>tailwind.config.js</code> file to support templates for your React component files as shown:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">module</span><span class=\"mtk1\">.</span><span class=\"mtk10\">exports</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">content:</span><span class=\"mtk1\"> [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;./src/**/*.{js,jsx,ts,tsx}&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">theme:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">extend:</span><span class=\"mtk1\"> {},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">plugins:</span><span class=\"mtk1\"> [],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Almost there! We'll now add some necessary Tailwind directives to your <code>index.css</code> file present in the root directory:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">@tailwind</span><span class=\"mtk1\"> base;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">@tailwind</span><span class=\"mtk1\"> components;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">@tailwind</span><span class=\"mtk1\"> utilities;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">...</span></span></code></pre>\n<p>Each of the above directives represents a layer of Tailwind's utility classes that you can use in your project. Their declaration allows using these utility classes anywhere in your project. </p>\n<p>Finally, we'll kickstart your React project by spinning a local development server:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">npm start</span></code></pre>\n<p>You're now ready to start using Tailwind CSS to create some awesome-looking UI for your React app!</p>\n<h2 id=\"frontend-architecture-and-boilerplate\" style=\"position:relative;\"><a href=\"#frontend-architecture-and-boilerplate\" aria-label=\"frontend architecture and boilerplate permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Frontend Architecture and Boilerplate</h2>\n<p>We'll break down the entire page into small, reusable components to ensure that your code is readable and maintainable and doesn't have bloated HTML templates. </p>\n<h3 id=\"component-architecture\" style=\"position:relative;\"><a href=\"#component-architecture\" aria-label=\"component architecture permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Component Architecture</h3>\n<p>For instance, you can have a <code>&#x3C;Header/></code> component that takes care of the page's heading and displays a link to navigate to another page. </p>\n<p>Similarly, you can have a reusable custom <code>&#x3C;Input/></code> component that can be used inside the form. All in all, here's what your frontend architecture would look like:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAACPklEQVQoz4VTTWsTURTNT9BO3rxMMqlpqSCk4qLUhaYRbSk1laJtqGmaZCZJY0REFDeCUhB3ChVKoaBbV+JG8GPnQhFBqKKL4kLRYDWdzMR82KYu1OOdN0laRXFxuHPfO++8e89948rvtJDvsaApJpJyCZrHRGybgdnBNSxmgAXtO27kf2I++QMLM3VcOVIRPBspbiHOCojLH6HxMuUmXClub67+Bk2uYUx6grDnGobVRQyp8zjEbiIuFZFgm3xbwI4x9hbT8grhky1oIcMbhA2BlGwh51/HiHwHfTsSCPWcwsCuk+jnZ6Grn5FR1pvchqjQFk2Q6BR7T/gAl11uxP0AEXafcA/H+Ruc6P4C3VNFmn2D7m4QNui7gWxnGVHfU4xIdzHKHlKrhbaoEy24xjteIqhGsK83it7AIIY6biMtN+jWIpJ8tYmiyBNSGX3uc+gPHsZu/yjGtj8j76qiwqRsCF9djg9m02hTtGz76qw70T6UVirIdVuCk+k0aN1ALlBGVq1Bl+vQec0ZSutQC0leal/QyiekV5jyLiOtEsddQz7QEF5qSgmT3hc4Kj3HBFsiruEI/onN6ixMsxWE/bM46J2jli0My7cQUi/igHIVMfc7hJTLCHddwH7lEg2l4LT8N2wVHBCC18WTifIljKuPcEx5LLzTeZ3sqCPro9a95v8ETWF2lL3GJFsW7ev0RnW2RvFr0xIDM10lnNlj4nTQ+rfgVlGdhqLxCg3MEWiD9tM+E+f3ljGXqIq/6Bco8Pyp5un9kAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Login Page Architecture Hierarchy\"\n        title=\"Login Page Architecture Hierarchy\"\n        src=\"/static/04ff8abefb4aa8da5c5d0ab928cddd6b/e5715/login-page-architecture-hierarchy.png\"\n        srcset=\"/static/04ff8abefb4aa8da5c5d0ab928cddd6b/a6d36/login-page-architecture-hierarchy.png 650w,\n/static/04ff8abefb4aa8da5c5d0ab928cddd6b/e5715/login-page-architecture-hierarchy.png 768w,\n/static/04ff8abefb4aa8da5c5d0ab928cddd6b/7b67d/login-page-architecture-hierarchy.png 2240w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"directory-structure\" style=\"position:relative;\"><a href=\"#directory-structure\" aria-label=\"directory structure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Directory Structure</h3>\n<p>So first, let's go ahead and create these files and folders. You'll develop corresponding files for the Signup page as well. Create the following files and folders inside your root directory:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"shell\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">.</span>\n<span class=\"grvsc-line\">├── components/</span>\n<span class=\"grvsc-line\">│   ├── FormAction.js</span>\n<span class=\"grvsc-line\">│   ├── FormExtra.js</span>\n<span class=\"grvsc-line\">│   ├── Header.js</span>\n<span class=\"grvsc-line\">│   ├── Input.js</span>\n<span class=\"grvsc-line\">│   ├── Login.js</span>\n<span class=\"grvsc-line\">│   └── Signup.js</span>\n<span class=\"grvsc-line\">├── constants/</span>\n<span class=\"grvsc-line\">│   └── formFields.js</span>\n<span class=\"grvsc-line\">└── pages/</span>\n<span class=\"grvsc-line\">    ├── Login.js</span>\n<span class=\"grvsc-line\">    └── Signup.js</span></code></pre>\n<p>For perspective, here's how we'll use those components to build your entire Login Page:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.30769230769231%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACh0lEQVQoz2WSS0hUURzGZ5c9JLKZO2oWIrZq4SJRCNpZgUaRmo/xNWP5iB7Sw9QgIhHbZLRwZYtKLF+gBJJSi1BBC11oiTUp5uhM3nnpjJPzdPx15zrJkBf+fOecy/873/c/n6L6uI2qZBvaOCslgoUSlYWuxj+M93kZfuthuNPNSKeH0R6vvP63nx6C5swg+QdsFMcaKVPbKVXbUJSqrURWsdLC/KSf/7+AwxWxCzI7N0Ft7iAZ0e/IE2YpFn5TJBhRyKrUIqWxZhmLVWZmhn1ym9+3hclkxri0wqJ+GaNRxGZz4HH7qK9r4EyajhRlOXmq72iERQpUCyhCUnUqD2VKN1qlhConMyOebR1BEEULS8tGTKKIYcHEqt0BW9s626qgMMpPRVyAcsEn2V5Dkav8SmrsTU4n1pJ+rJqMQ138+rLd4Fp34/OG7YdJQrglXTQw2I/mVBsXD06RldBFVnwvhYKksEA1T+bRN1xK7uVCUgdnY/r42LPAhneVTfxSf8j+ZmiK4dqUeTt72sk++Zxz0R9IT6wkNb6aHOV0pOUNtIe9ZMX103D7CeOfxzBMupkbceHUw/oc2L+BYTSIccqDx7fOE42B/P2rXI31oRO88kvvepQSpZ2f49vu9EN+Bp7padZ10XKtj6ayTtofjGMYC8j/W69skLtXpCxO6hNEOXZybEKLndhIOZyb8O0M7YdhgvrH12lqqaNOwvefuneG2VrplAjN6I5Y0YZrVw5D5E81Dl7dd9F2y8nrWi+9j6D7ITJ21Ad4UePk5T0Xd1LtaGIsVCRZqUmxc+NERLBl62Gl+dEW+ebL+yyypew9KzuVEyWGz80ymS7Byt00Oy1FDhrPr/EX7AF5kqCl0RYAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Login Page Architecture\"\n        title=\"Login Page Architecture\"\n        src=\"/static/4abf614464356d75a4c1bad1e319e7a5/e5715/login-page-architecture.png\"\n        srcset=\"/static/4abf614464356d75a4c1bad1e319e7a5/a6d36/login-page-architecture.png 650w,\n/static/4abf614464356d75a4c1bad1e319e7a5/e5715/login-page-architecture.png 768w,\n/static/4abf614464356d75a4c1bad1e319e7a5/7b67d/login-page-architecture.png 2240w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Makes sense? Great! </p>\n<h3 id=\"components-boilerplate-code\" style=\"position:relative;\"><a href=\"#components-boilerplate-code\" aria-label=\"components boilerplate code permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Components Boilerplate Code</h3>\n<p>While we're at it, let's also create some component boilerplate for all these files except the <code>/src/constants/formFields.js</code>.</p>\n<p>For the Login.js files (<code>/src/pages/Login.js</code>), you can put down the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">LoginPage</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Similarly, you can create such boilerplates for the rest of the files. </p>\n<h3 id=\"form-fields-constants\" style=\"position:relative;\"><a href=\"#form-fields-constants\" aria-label=\"form fields constants permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Form Fields Constants</h3>\n<p>You've created a <code>formFields.js</code> file earlier. This file will hold all the input fields related constants like placeholder, value, name, field type, etc. Inside this file, add the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\">=[</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelText:</span><span class=\"mtk8\">&quot;Email address&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelFor:</span><span class=\"mtk8\">&quot;email-address&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk8\">&quot;email-address&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">type:</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">autoComplete:</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isRequired:</span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">placeholder:</span><span class=\"mtk8\">&quot;Email address&quot;</span><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelText:</span><span class=\"mtk8\">&quot;Password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelFor:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">type:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">autoComplete:</span><span class=\"mtk8\">&quot;current-password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isRequired:</span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">placeholder:</span><span class=\"mtk8\">&quot;Password&quot;</span><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">signupFields</span><span class=\"mtk1\">=[</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelText:</span><span class=\"mtk8\">&quot;Username&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelFor:</span><span class=\"mtk8\">&quot;username&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk8\">&quot;username&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk8\">&quot;username&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">type:</span><span class=\"mtk8\">&quot;text&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">autoComplete:</span><span class=\"mtk8\">&quot;username&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isRequired:</span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">placeholder:</span><span class=\"mtk8\">&quot;Username&quot;</span><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelText:</span><span class=\"mtk8\">&quot;Email address&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelFor:</span><span class=\"mtk8\">&quot;email-address&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk8\">&quot;email-address&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">type:</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">autoComplete:</span><span class=\"mtk8\">&quot;email&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isRequired:</span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">placeholder:</span><span class=\"mtk8\">&quot;Email address&quot;</span><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelText:</span><span class=\"mtk8\">&quot;Password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelFor:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">type:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">autoComplete:</span><span class=\"mtk8\">&quot;current-password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isRequired:</span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">placeholder:</span><span class=\"mtk8\">&quot;Password&quot;</span><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelText:</span><span class=\"mtk8\">&quot;Confirm Password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">labelFor:</span><span class=\"mtk8\">&quot;confirm-password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">id:</span><span class=\"mtk8\">&quot;confirm-password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk8\">&quot;confirm-password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">type:</span><span class=\"mtk8\">&quot;password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">autoComplete:</span><span class=\"mtk8\">&quot;confirm-password&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">isRequired:</span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">placeholder:</span><span class=\"mtk8\">&quot;Confirm Password&quot;</span><span class=\"mtk1\">   </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\">,</span><span class=\"mtk12\">signupFields</span><span class=\"mtk1\">}</span></span></code></pre>\n<p>The above file has two arrays: one each for your login form fields and signup form fields. Each array contains an object that contains attributes for the input fields.</p>\n<p>The field names should be self-explanatory as to what they represent. Here's a quick summary of that:</p>\n<ul>\n<li><code>labelText</code>: The label for an input field</li>\n<li><code>labelFor</code>: The value that associates a label to the input field via an id attribute on the input field</li>\n<li><code>id</code>, <code>name</code> , <code>type</code>, and <code>placeholder</code>: Respective attributes on the input field  </li>\n<li><code>isRequired</code>: If you want to make an input field mandatory, in this case, all our input fields for form submission will be mandatory</li>\n</ul>\n<p>Later, we'll use this array to cycle through each input field and render a custom <code>&#x3C;Input/></code> component that you'll create shortly.</p>\n<h2 id=\"set-up-routing\" style=\"position:relative;\"><a href=\"#set-up-routing\" aria-label=\"set up routing permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Set Up Routing</h2>\n<p>As you already have your components boilerplates in place, let's first set up routing for your app.</p>\n<p>By default, when a user opens the app, we'll direct them to a Login page. Then, if the route changes to <strong>/signup</strong>, we'll direct them to a Signup page. </p>\n<p>Head over to your <code>/src/App.js</code> file and add the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./App.css&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">BrowserRouter</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">Routes</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">Route</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;react-router-dom&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">SignupPage</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./pages/Signup&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">LoginPage</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;./pages/Login&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">App</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;min-h-full h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;max-w-md w-full space-y-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">     </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">BrowserRouter</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Routes</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Route</span><span class=\"mtk1\"> </span><span class=\"mtk12\">path</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">element</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">LoginPage</span><span class=\"mtk17\">/&gt;</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Route</span><span class=\"mtk1\"> </span><span class=\"mtk12\">path</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/signup&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">element</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">SignupPage</span><span class=\"mtk17\">/&gt;</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">Routes</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">BrowserRouter</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk12\">App</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>Notice that you have two containers wrapped around your <code>&#x3C;BrowserRouter/></code> with some long classnames. </p>\n<p>The first container gives a minimum height of 100% and sets a fixed height of the container to 100vh via the <code>min-h-full</code> and <code>h-screen</code> classes. Then, it centers everything via <code>flex</code>, <code>items-center</code> to vertically center all the flex child elements, and <code>justifty-center</code> to center them horizontally. </p>\n<p>Finally, we have some padding classes prefixed with <code>p</code>. For top and bottom padding, we use the prefix <code>py-</code> followed by some value. We also have some responsive padding on small and large screen devices prefixed with <code>sm:</code> and <code>lg:</code> respectively. You can learn more about these <a href=\"https://tailwindcss.com/docs/padding\">padding</a> and <a href=\"https://tailwindcss.com/docs/margin\">margin</a> properties to see other similar classes you can use. </p>\n<p>Similarly, the second container sets some width for its child elements and provides some spacing via the respective Tailwind classes.</p>\n<h2 id=\"the-header-component\" style=\"position:relative;\"><a href=\"#the-header-component\" aria-label=\"the header component permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Header Component</h2>\n<p>Now, let's create the <code>&#x3C;Header/></code> component that you can render on both the login and signup pages for quick information and navigation.</p>\n<p>Head over to <code>/src/components/Header.js</code>, and add the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> {</span><span class=\"mtk12\">Link</span><span class=\"mtk1\">} </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;react-router-dom&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Header</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">heading</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">paragraph</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">linkName</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">linkUrl</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;#&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mb-10&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;flex justify-center&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">img</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">alt</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;h-14 w-14&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://ik.imagekit.io/pibjyepn7p9/Lilac_Navy_Simple_Line_Business_Logo_CGktk8RHK.png?ik-sdk-version=javascript-1.4.3</span><span class=\"mtk14\">&</span><span class=\"mtk8\">updatedAt=1649962071315&quot;</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">h2</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mt-6 text-center text-3xl font-extrabold text-gray-900&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk4\">{</span><span class=\"mtk12\">heading</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h2</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">p</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mt-2 text-center text-sm text-gray-600 mt-5&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">{</span><span class=\"mtk12\">paragraph</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk4\">{</span><span class=\"mtk8\">&#39; &#39;</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">to</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">linkUrl</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;font-medium text-purple-600 hover:text-purple-500&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk4\">{</span><span class=\"mtk12\">linkName</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">Link</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">p</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Your <code>&#x3C;Header/></code> component takes four props:</p>\n<ul>\n<li>a dynamic <code>heading</code> that it displays on the top;</li>\n<li>then some additional text as <code>paragraph</code>;</li>\n<li>a <code>linkName</code> to display which page it will redirect the user to; and,</li>\n<li>its corresponding path as <code>linkUrl</code>.</li>\n</ul>\n<p>Using the ' justify-center ' class, we place all these elements inside a flexbox container and horizontally center them. There is also an outer container that simply gives the header some bottom margin using the <code>mb-10</code> class.</p>\n<p>Then, we give our header image some fixed height and width using the <code>h-14</code> and <code>w-14</code> classes, respectively. </p>\n<p>Finally, our text and links have some typography classes for font-size, font-colour, hover effect, and font-weight.</p>\n<p>Let's now go ahead and render the <code>&#x3C;Header/></code> component with all the props inside the Login page (<code>/src/pages/Login.js</code>):</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Header</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../components/Header&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">LoginPage</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Header</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">heading</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Login to your account&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">paragraph</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Don&#39;t have an account yet? &quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">linkName</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Signup&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">linkUrl</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/signup&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Here's what the login page should now look like:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 18.923076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAEABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAd+AsD//xAAWEAADAAAAAAAAAAAAAAAAAAAAARD/2gAIAQEAAQUCFP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAABD/2gAIAQEABj8Cf//EABYQAAMAAAAAAAAAAAAAAAAAAAAQcf/aAAgBAQABPyEpf//aAAwDAQACAAMAAAAQ8A//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/ED//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/ED//xAAaEAEAAQUAAAAAAAAAAAAAAAABEQAQITFx/9oACAEBAAE/EHTmKCDKe2//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"login page header\"\n        title=\"login page header\"\n        src=\"/static/496d8822658d348bc2c55fffe8cac357/212bf/login-page-header.jpg\"\n        srcset=\"/static/496d8822658d348bc2c55fffe8cac357/6aca1/login-page-header.jpg 650w,\n/static/496d8822658d348bc2c55fffe8cac357/212bf/login-page-header.jpg 768w,\n/static/496d8822658d348bc2c55fffe8cac357/27b8c/login-page-header.jpg 2666w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Let's now start building the rest of the Login page form.</p>\n<h2 id=\"the-input-component\" style=\"position:relative;\"><a href=\"#the-input-component\" aria-label=\"the input component permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Input Component</h2>\n<p>We'll now create our reusable and great looking <code>&#x3C;Input/></code> component that you'll use to build your Login form.</p>\n<p>Head over to the <code>/src/components/Input.js</code> file, and add the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fixedInputClass</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;rounded-md appearance-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-purple-500 focus:border-purple-500 focus:z-10 sm:text-sm&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Input</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">handleChange</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">value</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">labelText</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">labelFor</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">id</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">name</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">type</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">isRequired</span><span class=\"mtk1\">=</span><span class=\"mtk4\">false</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">customClass</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;my-5&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">label</span><span class=\"mtk1\"> </span><span class=\"mtk12\">htmlFor</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">labelFor</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;sr-only&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk4\">{</span><span class=\"mtk12\">labelText</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">onChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleChange</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">value</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">name</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">type</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">required</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">isRequired</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">fixedInputClass</span><span class=\"mtk1\">+</span><span class=\"mtk12\">customClass</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">placeholder</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Remember all those fields' key-value pairs you set earlier in your <code>formFields.js</code> constants file?</p>\n<p>Those are all the props your <code>&#x3C;Input/></code> component will take. It will also take a <code>value</code> and a <code>handleChange</code> prop since we want this to be a controlled component linked to some state.</p>\n<p>Notice how the HTML markup of this component looks very clean. How is that possible? Are you not using any Tailwind classes here?</p>\n<p>As there are a lot of Tailwind classes for styling this input field, we have created a constant for it — called <code>fixedInputClass</code>. It contains all the essential styling classes for the input field.</p>\n<p>We also take a <code>customClass</code> prop that will append any custom Tailwind class you want to pass to the input field for customizations. How cool is that?!</p>\n<h2 id=\"the-login-component\" style=\"position:relative;\"><a href=\"#the-login-component\" aria-label=\"the login component permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Login Component</h2>\n<p>Next, create the <code>&#x3C;Login/></code> component inside <code>/src/components/Login.js</code>, where the entire Login form will be rendered. This component will also be responsible for owning any state or event handlers passed down as props to other child components.</p>\n<p>Based on your <code>loginFields</code> from your <code>formFields</code> constants, we programmatically generate an initial value for your <code>loginState</code>.</p>\n<p>Then we have a <code>handleChange</code> event handler to update the state whenever an <code>onChange</code> event is fired from the nested <code>&#x3C;Input/></code> component. </p>\n<p>Then we simply loop through the <code>fields</code> array and render an <code>&#x3C;Input/></code> component that you've created in the previous section.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;react&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../constants/formFields&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Input</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./Input&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fields</span><span class=\"mtk1\">=</span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">fields</span><span class=\"mtk1\">.</span><span class=\"mtk11\">forEach</span><span class=\"mtk1\">(</span><span class=\"mtk12\">field</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">[</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">]=</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Login</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">loginState</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setLoginState</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleChange</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setLoginState</span><span class=\"mtk1\">({...</span><span class=\"mtk12\">loginState</span><span class=\"mtk1\">,</span><span class=\"mtk12\">[e.target.id]:e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">form</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mt-8 space-y-6&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;-space-y-px&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">fields</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk12\">field</span><span class=\"mtk4\">=&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">key</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">handleChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleChange</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">loginState</span><span class=\"mtk1\">[</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">]</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">labelText</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">labelText</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">labelFor</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">labelFor</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">name</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">type</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">isRequired</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">isRequired</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">placeholder</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Before seeing how the login form looks, you need to render it inside your Login page.</p>\n<p>So render the above <code>&#x3C;Login/></code> component inside <code>/src/pages/Login.js</code> file as shown:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Header</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../components/Header&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Login</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../components/Login&quot;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">LoginPage</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Header</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">heading</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Login to your account&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">paragraph</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Don&#39;t have an account yet? &quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">linkName</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Signup&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">linkUrl</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/signup&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Login</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Now, if you go back to your React app, you should see your Login page input fields appear as follows:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 25.538461538461537%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAd+AsD//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAEFAn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAY/An//xAAXEAEAAwAAAAAAAAAAAAAAAAABABBh/9oACAEBAAE/IYG1/9oADAMBAAIAAwAAABDwD//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABoQAAICAwAAAAAAAAAAAAAAAAERABAhMVH/2gAIAQEAAT8QOoh5F9r/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"login page with input fiels\"\n        title=\"login page with input fiels\"\n        src=\"/static/cbb10ea9a4b8162c9e9e9501ff9b8fad/212bf/login-page-with-input-fields.jpg\"\n        srcset=\"/static/cbb10ea9a4b8162c9e9e9501ff9b8fad/6aca1/login-page-with-input-fields.jpg 650w,\n/static/cbb10ea9a4b8162c9e9e9501ff9b8fad/212bf/login-page-with-input-fields.jpg 768w,\n/static/cbb10ea9a4b8162c9e9e9501ff9b8fad/eec88/login-page-with-input-fields.jpg 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Excellent, it looks like you're almost there!</p>\n<p>Now add the final pieces to the Login page by writing the <code>&#x3C;FormExtra></code> and <code>&#x3C;FormAction/></code> components.</p>\n<h2 id=\"wrapping-up-the-login-page\" style=\"position:relative;\"><a href=\"#wrapping-up-the-login-page\" aria-label=\"wrapping up the login page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrapping Up the Login Page</h2>\n<p>The <code>&#x3C;FormExtra/></code> component holds the template and styles for a simple \"Remember me\" functionality. </p>\n<p>Inside <code>/src/components/FormExtra.js</code> file, add the following code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">FormExtra</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;flex items-center justify-between &quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;flex items-center&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;remember-me&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;remember-me&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;h-4 w-4 text-purple-600 focus:ring-purple-500 border-gray-300 rounded&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">label</span><span class=\"mtk1\"> </span><span class=\"mtk12\">htmlFor</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;remember-me&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;ml-2 block text-sm text-gray-900&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            Remember me</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;text-sm&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">a</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;#&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;font-medium text-purple-600 hover:text-purple-500&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            Forgot your password?</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">a</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Again here we're using some Tailwind typography and flexbox classes to style and structure the layout of the UI. </p>\n<p>Let's go to the <code>/src/components/FormAction.js</code> file and create a submit button for the Login form. </p>\n<p>Add the following code inside this file:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"17\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">FormAction</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;Button&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">action</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;submit&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">text</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">type</span><span class=\"mtk1\">===</span><span class=\"mtk8\">&#39;Button&#39;</span><span class=\"mtk1\"> ?</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">button</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">action</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-purple-600 hover:bg-purple-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 mt-10&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">onSubmit</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk4\">{</span><span class=\"mtk12\">text</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            :</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;&gt;&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Notice that you also have loads of CSS classes inside our <code>&#x3C;button/></code> element to style it. It makes our HTML appear bloated and difficult to read. We can follow the same approach of using a constant and a prop against the <code>className</code> for the <code>&#x3C;button/></code> as we previously did to combat this. </p>\n<p>At last, we'll put everything together inside <code>/src/components/Login.js</code> file as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"18\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;react&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../constants/formFields&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">FormAction</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./FormAction&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">FormExtra</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./FormExtra&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Input</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./Input&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fields</span><span class=\"mtk1\">=</span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">fields</span><span class=\"mtk1\">.</span><span class=\"mtk11\">forEach</span><span class=\"mtk1\">(</span><span class=\"mtk12\">field</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">[</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">]=</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Login</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">loginState</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setLoginState</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleChange</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setLoginState</span><span class=\"mtk1\">({...</span><span class=\"mtk12\">loginState</span><span class=\"mtk1\">,</span><span class=\"mtk12\">[e.target.id]:e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleSubmit</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk11\">preventDefault</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">authenticateUser</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//Handle Login API Integration here</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">authenticateUser</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">form</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mt-8 space-y-6&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onSubmit</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;-space-y-px&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">fields</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk12\">field</span><span class=\"mtk4\">=&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">key</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">handleChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleChange</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">loginState</span><span class=\"mtk1\">[</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">]</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">labelText</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">labelText</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">labelFor</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">labelFor</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">name</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">type</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">isRequired</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">isRequired</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">placeholder</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">FormExtra</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">FormAction</span><span class=\"mtk1\"> </span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">text</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Login&quot;</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>And once we do that, we should have a stunning, modern looking login page appear right in front of us:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 62.46153846153847%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAAA90lEQVQoz62RTU7DMBCFff81ErCCQxQjxUncCiliAQeA8rOHRZUmrt3YMw87gRXUVSOe9EnjmfHT2COUUiiKIqIgpcRicfMLKW+R+sq6QqkKLOs71KsVylJBa4065rVeoqoqCPyzRAgBObz3CBQmwnEEMyNHUv/Rw3yaMT7WL3JGO2uxfn3H89Mb1pGXGNuYyxlnJyQiOLeHdQ7O7uEdgTFjwiQiRtcZDIMH02TOTCCmeYbpsrEGnnw6jQRPCMO3IU403G0CmssNmvMWj9cGD1c9mrMO9xd9rNHBfzxgyOOT3TbSMmxLI247kWrAyVv+4S/xvC3P4QsLC6JyPkfDCgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"login page\"\n        title=\"login page\"\n        src=\"/static/2bb44b070fe325150bbfc386d7bc3561/e5715/login-page.png\"\n        srcset=\"/static/2bb44b070fe325150bbfc386d7bc3561/a6d36/login-page.png 650w,\n/static/2bb44b070fe325150bbfc386d7bc3561/e5715/login-page.png 768w,\n/static/2bb44b070fe325150bbfc386d7bc3561/d9ed5/login-page.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"the-signup-page\" style=\"position:relative;\"><a href=\"#the-signup-page\" aria-label=\"the signup page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The Signup Page</h2>\n<p>You've created so many reusable components. Now, it's straightforward to use them to build the Signup page further.</p>\n<p>Feel free to take this as a challenge and build it yourself based on what you've learned. </p>\n<p>Here's a quick walkthrough of the steps and how you can use the same approach to build the Signup page in minutes. </p>\n<p>First, create a main <code>&#x3C;Singup/></code> component inside <code>/src/components/Signup.js</code> file similar to the <code>&#x3C;Login/></code> component you've completed in the previous section. It will render the signup form fields and attach state and event handlers to it.</p>\n<p>Here's how the entire code looks like:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"19\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">useState</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;react&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">signupFields</span><span class=\"mtk1\"> } </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../constants/formFields&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">FormAction</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./FormAction&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Input</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;./Input&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fields</span><span class=\"mtk1\">=</span><span class=\"mtk12\">signupFields</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">={};</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">fields</span><span class=\"mtk1\">.</span><span class=\"mtk11\">forEach</span><span class=\"mtk1\">(</span><span class=\"mtk12\">field</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">[</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">]=</span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">Signup</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">signupState</span><span class=\"mtk1\">,</span><span class=\"mtk12\">setSignupState</span><span class=\"mtk1\">]=</span><span class=\"mtk11\">useState</span><span class=\"mtk1\">(</span><span class=\"mtk12\">fieldsState</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleChange</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk11\">setSignupState</span><span class=\"mtk1\">({...</span><span class=\"mtk12\">signupState</span><span class=\"mtk1\">,</span><span class=\"mtk12\">[e.target.id]:e</span><span class=\"mtk1\">.</span><span class=\"mtk12\">target</span><span class=\"mtk1\">.</span><span class=\"mtk12\">value</span><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">handleSubmit</span><span class=\"mtk1\">=(</span><span class=\"mtk12\">e</span><span class=\"mtk1\">)</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">e</span><span class=\"mtk1\">.</span><span class=\"mtk11\">preventDefault</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">signupState</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">createAccount</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk3\">//handle Signup API Integration here</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">createAccount</span><span class=\"mtk1\">=()</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">form</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mt-8 space-y-6&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onSubmit</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">className</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk12\">fields</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk12\">field</span><span class=\"mtk4\">=&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                        </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Input</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">key</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">handleChange</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleChange</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">signupState</span><span class=\"mtk1\">[</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk1\">]</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">labelText</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">labelText</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">labelFor</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">labelFor</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">id</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">name</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">type</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">isRequired</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">isRequired</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                            </span><span class=\"mtk12\">placeholder</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">field</span><span class=\"mtk1\">.</span><span class=\"mtk12\">placeholder</span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                    </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">FormAction</span><span class=\"mtk1\"> </span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">handleSubmit</span><span class=\"mtk4\">}</span><span class=\"mtk1\"> </span><span class=\"mtk12\">text</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Signup&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">div</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">form</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Then, render this component inside <code>/src/pages/Signup.js</code> alongside the <code>&#x3C;Header/></code> components with some modified props for the signup page. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"jsx\" data-index=\"20\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Header</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../components/Header&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Signup</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;../components/Signup&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">export</span><span class=\"mtk1\"> </span><span class=\"mtk15\">default</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">SignupPage</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Header</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">heading</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Signup to create an account&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">paragraph</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Already have an account? &quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">linkName</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;Login&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">              </span><span class=\"mtk12\">linkUrl</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;/&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Signup</span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk17\">&lt;/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>And that's it! That's all there is to build a great looking signup page that looks as follows:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 62.46153846153847%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAAA8UlEQVQoz62R2QrCMBBF+///oSi+1q1p2oof4PKqoA+2bo0LaExt2muMKIq2uCUchmEmh2FiEEJgWZaCoNFowqxWYZp3qLxWq4Oouu1S2MSC57ThtFqwKYHrunAcCs/zQCmFgT8fQ0qJLK5HbASirbjleW+eJkzT9BbniyUWyxD+eIrJKEDIGBhbP/Q8TZgn1DJfyaYKf4ZZEGK1/kEYx/Llnr4W7nYcQkRqN4mWX/layKM9YhzP2QP66rYPhPKodjg8YD44YDWONWx0iefaxxOKbYJ+maNb5OhXLnQKe/RKXNfeFmY1vtuTu8M0ySDnU045+aKZ56aFlAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Signup page\"\n        title=\"Signup page\"\n        src=\"/static/fa1a6161f8a44b5d86827ad42aa7232a/e5715/signup-page.png\"\n        srcset=\"/static/fa1a6161f8a44b5d86827ad42aa7232a/a6d36/signup-page.png 650w,\n/static/fa1a6161f8a44b5d86827ad42aa7232a/e5715/signup-page.png 768w,\n/static/fa1a6161f8a44b5d86827ad42aa7232a/d9ed5/signup-page.png 2880w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Don't worry; if you got stuck somewhere, feel free to <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/React/react-tailwind-app\">refer to the entire codebase for this tutorial here</a>. </p>\n<h2 id=\"use-loginradius-authentication-apis\" style=\"position:relative;\"><a href=\"#use-loginradius-authentication-apis\" aria-label=\"use loginradius authentication apis permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use LoginRadius Authentication APIs</h2>\n<p>You can use <a href=\"https://www.loginradius.com/resource/whitepaper/loginradius-ciam-developers/\">LoginRadius</a> to quickly set up an authentication backend for your frontend application.</p>\n<p>First, <a href=\"https://accounts.loginradius.com/auth.aspx\">set up an account</a>, and get your API key from your Account Dashboard.</p>\n<p>Then, you can use their <a href=\"https://www.loginradius.com/docs/api/v2/single-sign-on/Machine-to-Machine/overview/\">login endpoint</a> to authenticate users. </p>\n<p>The endpoint takes an email and password as parameters and validates them against the correct credentials. If we were to integrate this endpoint in our previously built <code>&#x3C;Login/></code> component (<code>/scr/components/Login.js</code>), here's what the <code>authenticateUser</code> method would look like:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"21\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">//Handle Login API Integration here</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk11\">authenticateUser</span><span class=\"mtk1\"> = () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">       </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">endpoint</span><span class=\"mtk1\">=</span><span class=\"mtk8\">`https://api.loginradius.com/identity/v2/auth/login?apikey=</span><span class=\"mtk4\">${</span><span class=\"mtk12\">apiKey</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">endpoint</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk12\">method:</span><span class=\"mtk8\">&#39;POST&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk12\">headers:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk8\">&#39;Content-Type&#39;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;application/json&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             </span><span class=\"mtk12\">body:</span><span class=\"mtk10\">JSON</span><span class=\"mtk1\">.</span><span class=\"mtk11\">stringify</span><span class=\"mtk1\">(</span><span class=\"mtk12\">loginFields</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             }).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk3\">//API Success from LoginRadius Login API</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">             .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk4\">=&gt;</span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">         </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>Similarly, you can use <a href=\"https://www.loginradius.com/resource/whitepaper/loginradius-ciam-developers/\">the Signup endpoint</a> to create users without managing a complete backend database yourself.</p>\n<p>Curious to learn more?</p>\n<p>I did a full-fledged <a href=\"https://www.loginradius.com/blog/engineering/guest-post/authenticating-svelte-apps/\">guide on authenticating Svelte apps with LoginRadius here</a>.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this tutorial, you have learned to create beautiful registration and authentication forms for your web app with Tailwind CSS. You also learned the advantages and disadvantages of Tailwind CSS and understood how Tailwind CSS works better with React.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk14 { color: #F44747; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n</style>","frontmatter":{"date":"May 17, 2022","updated_date":null,"description":"In this article, you'll learn how to instantly build great-looking authentication forms for Login and Signup using Tailwind CSS in React. You'll also understand how to make these forms functional using the third-party Authentication service LoginRadius.","title":"Build a Modern Login/Signup Form with Tailwind CSS and React","tags":["Tailwind CSS","React","Authentication"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/a1c3066797f2394882941ee5e3297547/ee604/modern-login-and-signup-form-banner.png","srcSet":"/static/a1c3066797f2394882941ee5e3297547/69585/modern-login-and-signup-form-banner.png 200w,\n/static/a1c3066797f2394882941ee5e3297547/497c6/modern-login-and-signup-form-banner.png 400w,\n/static/a1c3066797f2394882941ee5e3297547/ee604/modern-login-and-signup-form-banner.png 800w,\n/static/a1c3066797f2394882941ee5e3297547/f3583/modern-login-and-signup-form-banner.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Siddhant Varma","github":"FuzzySid","avatar":null}}}}]},"markdownRemark":{"excerpt":"Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie…","fields":{"slug":"/engineering/identity-impact-of-google-chrome-thirdparty-cookie-restrictions/"},"html":"<p>Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie restrictions for 1% of stable clients and 20% of Canary, Dev, and Beta clients.</p>\n<p><strong>What does it mean for user authentication?</strong></p>\n<p>On one hand, Google believes third-party cookies are widely used for cross-site tracking, greatly affecting user privacy. Hence, Google wants to phase out (or restrict) supporting third-party cookies in Chrome by early Q2 2025 (subject to regulatory processes).</p>\n<p>On the other hand, Google introduced Privacy Sandbox to support the use cases (other than cross-site tracking and advertising) previously implemented using third-party cookies.</p>\n<p>In this article, we’ll discuss:</p>\n<ul>\n<li>How is user authentication (identity) affected?</li>\n<li>What is Google offering as part of Privacy Sandbox to support various identity use cases when third-party cookies are phased out?</li>\n</ul>\n<h2 id=\"how-is-user-authentication-affected\" style=\"position:relative;\"><a href=\"#how-is-user-authentication-affected\" aria-label=\"how is user authentication affected permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is User Authentication Affected?</h2>\n<p>Third-party cookie restrictions affect user authentication in three ways, as follows.</p>\n<h3 id=\"external-identity-providers\" style=\"position:relative;\"><a href=\"#external-identity-providers\" aria-label=\"external identity providers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>External Identity Providers</h3>\n<p>If your website or app uses an external Identity Provider (IdP) — like LoginRadius, the IdP sets a third-party cookie when the user authenticates on your app.</p>\n<h3 id=\"web-sso\" style=\"position:relative;\"><a href=\"#web-sso\" aria-label=\"web sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Web SSO</h3>\n<p>If you have multiple apps across domains within your organization and authentication is handled using an IdP (internal or external) with web SSO, you already use third-party cookies to facilitate seamless access for each user using a single set of credentials.</p>\n<p>If you have implemented web SSO with one primary domain and multiple sub-domains of the primary domain, third-party cookie restrictions may not apply. For now, Google doesn’t consider the cookies set by sub-domains as third-party cookies, although this stance may change in the future.</p>\n<p>For example, you have apps at <code>example.com</code>, <code>travel.example.com</code>, <code>stay.example.com</code>, and web SSO is handled by <code>auth.example.com</code>. In this case, third-party cookie restrictions don’t apply.</p>\n<h3 id=\"federated-sso\" style=\"position:relative;\"><a href=\"#federated-sso\" aria-label=\"federated sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated SSO</h3>\n<p>Federated SSO is similar to, albeit different from, web SSO. It can handle multiple IdPs and applications—aka., Service Providers (SPs)—spanning multiple organizations. It can also implement authentication scenarios that are usually implemented through web SSO.</p>\n<p>Usually, authentication is handled on a separate pop-up or page when the user wants to authenticate rather than on the application or website a user visits. </p>\n<p>For example, you already use federated SSO if you facilitate authentication for a set of apps through multiple social identity providers as well as traditional usernames and passwords.</p>\n<blockquote>\n<p><strong>Note</strong>: It is also possible to store tokens locally, not within cookies. In this case, third-party cookie restrictions won’t affect token-based authentication. However, the restrictions still affect authentication where tokens are stored within third-party cookies (a common and secure method).</p>\n</blockquote>\n<h2 id=\"chromes-alternatives-for-third-party-cookies\" style=\"position:relative;\"><a href=\"#chromes-alternatives-for-third-party-cookies\" aria-label=\"chromes alternatives for third party cookies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Chrome’s Alternatives for Third-Party Cookies</h2>\n<p>Google has been developing alternative features and capabilities for Chrome to replace third-party cookies as part of its Privacy Sandbox for Web initiative.</p>\n<p>Specific to authentication, Google recommends the following:</p>\n<ol>\n<li>Cookies Having Independent Partitioned State (CHIPS)</li>\n<li>Storage Access API</li>\n<li>Related Website Sets</li>\n<li>Federated Credential Management (FedCM) API</li>\n</ol>\n<h3 id=\"cookies-having-independent-partitioned-state-chips\" style=\"position:relative;\"><a href=\"#cookies-having-independent-partitioned-state-chips\" aria-label=\"cookies having independent partitioned state chips permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cookies Having Independent Partitioned State (CHIPS)</h3>\n<p><a href=\"https://developers.google.com/privacy-sandbox/3pcd/chips\">CHIPS</a> are a restricted way of setting third-party cookies on a top-level site without making them accessible on other top-level sites. Thus, they limit cross-site tracking and enable specific cross-site functionalities, such as maps, chat, and payment embeds.</p>\n<p>For example, a user visits <code>a.com</code> with a map embed from <code>map-example.com</code>, which can set a partitioned cookie that is only accessible on a.com. </p>\n<p>If the user visits <code>b.com</code> with a map embed from <code>map-example.com</code>, it cannot access the partitioned cookie set on <code>a.com</code>. It has to create a separate partitioned cookie specific to <code>b.com</code>, thus blocking cross-site tracking yet allowing limited cross-site functionality.</p>\n<p>You should specifically opt for partitioned cookies (CHIPS), which are set with partitioned and secure cookie attributes.</p>\n<p>If you’re using an external identity provider for your application, CHIPS is a good option to supplant third-party cookie restrictions. </p>\n<p>However, CHIPS may not be ideal if you have a web SSO or federated SSO implementation. It creates separate partitioned cookies for each application with a separate domain, which can increase complexity and create compatibility issues.</p>\n<h3 id=\"storage-access-api\" style=\"position:relative;\"><a href=\"#storage-access-api\" aria-label=\"storage access api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Storage Access API</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/storage-access-api\">Storage Access API</a>, you can access the local storage in a third-party context through iframes, similar to when users visit it as a top-level site in a first-party context. That is, it gives access to unpartitioned cookies and storage.</p>\n<p>Storage Access API requires explicit user approval to grant access, similar to locations, camera, and microphone permissions. If the user denies access, unpartitioned cookies and storage won’t be accessible in a third-party context.</p>\n<p>It is most suitable when loading cross-site resources and interactions, such as:</p>\n<p>Verifying user sessions when allowing interactions on an embedded social post or providing personalization for an embedded video.\nEmbedded documents requiring user verification status to be accessible.</p>\n<p>As it requires explicit user approval, it is advisable to use Storage Access API when you can’t implement an identity use case with the other options.</p>\n<h3 id=\"related-website-sets\" style=\"position:relative;\"><a href=\"#related-website-sets\" aria-label=\"related website sets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Related Website Sets</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/related-website-sets\">Related Website Sets</a>, you can declare a <code>primary</code> website and <code>associatedSites</code> for limited purposes to grant third-party cookie access and local storage for a limited number of sites.</p>\n<p>Chrome automatically recognizes related website sets declared, accepted, and maintained in this open-source GitHub repository: <a href=\"https://github.com/GoogleChrome/related-website-sets\">Related Website Sets</a></p>\n<p>It provides access through Storage Access API directly without prompting for user approval, but only after the user interacts with the relevant iframe.</p>\n<p>It is important to declare a limited number of domains in related website sets that are meaningful and used for specific purposes. Google may block or suspend any exploitative use of this feature.</p>\n<p>The top-level site can also request approval for specific cross-site resources and scripts to Storage Access API using <code>resuestStorageAccessFor()</code> API.</p>\n<p>If you’re using an external identity provider for your web application, you can declare the domain of the identity provider in the related set to ensure limited third-party cookies and storage access to the identity provider, thus ensuring seamless user authentication.</p>\n<p>Related Website Sets can also work to supplement third-party cookie restrictions in web SSO and federated SSO if the number of web applications (or domains) is limited.</p>\n<h3 id=\"federated-credential-management-fedcm-api\" style=\"position:relative;\"><a href=\"#federated-credential-management-fedcm-api\" aria-label=\"federated credential management fedcm api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated Credential Management (FedCM) API</h3>\n<p>FedCM API enables federated SSO without third-party cookies.</p>\n<p>With FedCM API, a user follows these steps for authentication:</p>\n<ol>\n<li>The User navigates to a Service Provider (SP) — aka., Relying Party (RP)</li>\n<li>As the user requests to authenticate, the SP requests the browser through FedCM API to initiate authentication.</li>\n<li>The browser displays a list of available identity providers (supported by the RP), such as social IdPs like Google, Apple, LinkedIn, and Facebook, or other OAuth IdPs like LoginRadius.</li>\n<li>Once the user selects an IdP, the browser communicates with the IdP. Upon valid authentication, the IdP generates a secure token.\nThe browser delivers this secure token to the RP to facilitate user authorization.</li>\n</ol>\n<p>You can access a user demo of FedCM here: <a href=\"https://fedcm-rp-demo.glitch.me/\">FedCM</a>. </p>\n<p>For more information about implementing federated SSO with FedCM API, go through the <a href=\"https://developers.google.com/privacy-sandbox/3pcd/fedcm-developer-guide\">FedCM developer guide</a>.</p>\n<h2 id=\"how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" style=\"position:relative;\"><a href=\"#how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" aria-label=\"how is loginradius preparing for the third party cookie phase out permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is LoginRadius Preparing for the Third-party Cookie Phase-out?</h2>\n<p>Firstly, we’re committed to solving our customers' user identity pain points — and preparing for the third-party cookies phase-out is no different.</p>\n<p>We’ll implement the most relevant and widely useful solutions to facilitate a smooth transition for our customers.</p>\n<p>Please subscribe to our blog for more information. We’ll update you on how we help with the third-party cookie phase-out.</p>\n<h2 id=\"in-conclusion\" style=\"position:relative;\"><a href=\"#in-conclusion\" aria-label=\"in conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>In Conclusion</h2>\n<p>The proposed changes to phase out third-party cookies and suggested alternatives are evolving as Google has been actively collaborating and discussing changes with the border community.</p>\n<p>Moreover, browsers like Firefox, Safari, and Edge may approach restricting third-party cookies differently than Google does.</p>\n<p>From LoginRadius, we’ll keep you updated on what we’re doing as a leading Customer Identity and Access Management (CIAM) vendor to prepare for the third-party cookie phase-out.</p>\n<h2 id=\"glossary\" style=\"position:relative;\"><a href=\"#glossary\" aria-label=\"glossary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Glossary</h2>\n<p><strong>Top-level site</strong>: It is the primary site a user has visited.</p>\n<p><strong>First-party cookie</strong>: A cookie set by the top-level site.</p>\n<p><strong>Third-party cookie</strong>: A cookie set by a domain other than the top-level site. For example, let’s assume that a user has visited <code>a.com</code>, which might use an embed from <code>loginradius.com</code> to facilitate authentication. If <code>loginradius.com</code> sets a cookie when the user visits <code>a.com</code>, it is called a third-party cookie as the user hasn’t directly visited <code>loginradius.com</code>.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>References</h2>\n<ul>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/prepare/prepare-for-phaseout\">Changes to Chrome's treatment of third-party cookies</a></li>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/guides/identity\">Check the impact of the third-party cookie changes on your sign-in workflows</a></li>\n</ul>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"July 08, 2024","updated_date":null,"description":"Google Chrome has planned to phase out third-party cookies, which will affect different website functionalities depending on third-party cookies. This blog focuses on how this phase-out affects identity and user authentication and discusses alternatives for overcoming challenges.","title":"How Chrome’s Third-Party Cookie Restrictions Affect User Authentication?","tags":["Identity","Cookies","Chrome"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png","srcSet":"/static/eb7396060c0adc430dbed2d04b63d431/69585/third-party-cookies-phaseout-chrome.png 200w,\n/static/eb7396060c0adc430dbed2d04b63d431/497c6/third-party-cookies-phaseout-chrome.png 400w,\n/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png 800w,\n/static/eb7396060c0adc430dbed2d04b63d431/f3583/third-party-cookies-phaseout-chrome.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Raghunath Reddy","github":"raghunath-r-a","avatar":null}}}},"pageContext":{"limit":6,"skip":6,"currentPage":2,"type":"//engineering//","numPages":52,"pinned":"17fa0d7b-34c8-51c4-b047-df5e2bbaeedb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}