{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/7","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"What is a Smart Contract? Smart Contracts 📝 are simple programs stored on a blockchain network. You can say it's like an agreement between…","fields":{"slug":"/engineering/guest-post/ethereum-smart-contract-tutorial/"},"html":"<h2 id=\"what-is-a-smart-contract\" style=\"position:relative;\"><a href=\"#what-is-a-smart-contract\" aria-label=\"what is a smart contract 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 Smart Contract?</h2>\n<p><a href=\"https://en.wikipedia.org/wiki/Smart_contract\"><strong>Smart Contracts</strong></a> 📝 are simple programs stored on a blockchain network.</p>\n<p>You can say it's like an agreement between two people in the form of computer code. The transactions in a smart contract are processed by the blockchain and stored as a <strong>42 character hex address</strong> with the prefix <code>\"0x\"</code>). All of which means that they can be sent automatically without needing a third party.</p>\n<p><strong>🤔 Remember:</strong> They're stored in a public database. And once a smart contract is deployed, it cannot be changed.</p>\n<h2 id=\"what-is-solidity\" style=\"position:relative;\"><a href=\"#what-is-solidity\" aria-label=\"what is solidity 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 Solidity?</h2>\n<p>Solidity is one of the most popular languages used for building smart contracts on Ethereum Blockchain. It's also an object-oriented programming language.</p>\n<h2 id=\"build-your-first-smart-contract\" style=\"position:relative;\"><a href=\"#build-your-first-smart-contract\" aria-label=\"build your first smart contract 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 Your First Smart Contract</h2>\n<ol>\n<li>Open <strong><code>Remix</code> IDE</strong> from <a href=\"https://remix.ethereum.org/\">here</a>.</li>\n<li>Click on <code>Sure</code> and then <code>Done</code>.</li>\n<li>Under <code>default_workshop</code>, click on <code>create new file</code>.</li>\n<li>Rename it as <code>Hostel.sol</code>.</li>\n</ol>\n<p>Now you're ready to write your first <strong>Smart Contract</strong>. 🤩</p>\n<h3 id=\"contract-code\" style=\"position:relative;\"><a href=\"#contract-code\" aria-label=\"contract 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>Contract Code</h3>\n<ol>\n<li>You have to provide the <code>solidity version</code> in the smart contract:</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">pragma solidity ^</span><span class=\"mtk7\">0.5</span><span class=\"mtk1\">.</span><span class=\"mtk7\">16</span><span class=\"mtk1\">;</span></span></code></pre>\n<ol start=\"2\">\n<li>Now create the main contract named <code>Hostel</code>:</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">contract </span><span class=\"mtk12\">Hostel</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<ol start=\"3\">\n<li>Now, inside the <code>contract Hostel{...}</code> follow the steps below.</li>\n<li>Create some variables where the smart contract will store the <a href=\"https://ethereum.stackexchange.com/questions/20874/payable-function-in-solidity\"><strong>payable</strong></a> <code>address</code> (42 char hex string with prefix : <code>\"0x\"</code>) of the <code>Landlord</code> &#x26; the <code>Tenant</code>.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    address payable tenant;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    address payable landlord;</span></span></code></pre>\n<ol start=\"5\">\n<li>Create some <a href=\"https://ethereum.stackexchange.com/questions/19380/external-vs-public-best-practices\"><strong>public</strong></a> variables where the smart contract will store some integer values. For this, there's a data type called <code>uint</code> (256-bit unsigned integer)</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    uint </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> no_of_rooms = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    uint </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> no_of_agreement = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    uint </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> no_of_rent = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span></code></pre>\n<ol start=\"6\">\n<li>Now, create a <code>structure</code> to store details of each Hostel room like <code>Hostel no.</code>, <code>Hostel name</code>, <code>Hostel address</code>, <code>No of total agreements</code>, <code>Monthly rent</code>, <code>One-time security deposit</code>, <code>Last agreement sign time</code>, <code>Vacancy</code>, <code>Landlord address</code>, and <code>Current Tenant Address</code>.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    struct </span><span class=\"mtk12\">Room</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint roomid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint agreementid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        string roomname;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        string roomaddress;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint rent_per_month;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint securityDeposit;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint timestamp;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        bool vacant;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable landlord;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable currentTenant;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<ol start=\"7\">\n<li><code>map</code> previous <code>structure</code> with a <code>uint</code>(named : <code>roomid</code>).</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">mapping(uint =&gt; </span><span class=\"mtk12\">Room</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Room_by_No</span><span class=\"mtk1\">;</span></span></code></pre>\n<ol start=\"8\">\n<li>Similar to the above, create a <code>structure</code> for each <code>Rental Agreement</code> and map that with a <code>uint</code>(named: <code>agreementid</code>). This will store details like: <code>Hostel no.</code>, <code>Agreement No</code>, <code>Hostel name</code>, <code>Hostel address</code>, <code>Monthly rent</code>, <code>One-time security deposit</code>,<code>Lockin Period</code>, <code>Agreement sign time</code>, <code>Landlord address</code>, and <code>Tenant Address</code>.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    struct </span><span class=\"mtk12\">RoomAgreement</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint roomid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint agreementid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        string </span><span class=\"mtk12\">Roomname</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        string </span><span class=\"mtk12\">RoomAddresss</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint rent_per_month;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint securityDeposit;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint lockInPeriod;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint timestamp;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable tenantAddress;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable landlordAddress;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">mapping(uint =&gt; </span><span class=\"mtk12\">RoomAgreement</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk12\">RoomAgreement_by_No</span><span class=\"mtk1\">;</span></span></code></pre>\n<ol start=\"9\">\n<li>Now, create a <code>structure</code> for each <code>Rent</code> payment and map that with a <code>uint</code>. This will store details like: <code>Rent No.</code>, <code>Hostel no.</code>, <code>Agreement No</code>, <code>Hostel name</code>, <code>Hostel address</code>, <code>Monthly rent</code>, <code>Rent payment time</code>, <code>Landlord address</code>, and <code>Tenant Address</code>.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    struct </span><span class=\"mtk12\">Rent</span><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint rentno;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint roomid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint agreementid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        string </span><span class=\"mtk12\">Roomname</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        string </span><span class=\"mtk12\">RoomAddresss</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint rent_per_month;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint timestamp;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable tenantAddress;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable landlordAddress;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">   mapping(uint =&gt; </span><span class=\"mtk12\">Rent</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Rent_by_No</span><span class=\"mtk1\">;</span></span></code></pre>\n<ol start=\"10\">\n<li>\n<p>Create some <a href=\"https://ethereum.stackexchange.com/questions/48971/what-are-function-modifiers\"><strong>modifiers</strong></a> that will help you verify a few things before running a function.</p>\n<p>Here <code>require(...);</code> means that if the given condition is not satisfied, the function won't execute, and the given string will appear as an error code.</p>\n</li>\n</ol>\n<p>The following will check if the message sender is the landlord.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier onlyLandlord(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender == </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].landlord, </span><span class=\"mtk8\">&quot;Only landlord can access this&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check if the message sender is anyone except the landlord.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier notLandLord(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender != </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].landlord, </span><span class=\"mtk8\">&quot;Only Tenant can access this&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether the room is vacant or not.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier </span><span class=\"mtk12\">OnlyWhileVacant</span><span class=\"mtk1\">(uint </span><span class=\"mtk12\">_index</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=\"mtk4\">require</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].vacant == </span><span class=\"mtk4\">true</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Room is currently Occupied.&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether the tenant has enough <code>Ether</code> in his wallet to pay the rent.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier enoughRent(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.value &gt;= uint(</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].rent_per_month), </span><span class=\"mtk8\">&quot;Not enough Ether in your wallet&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether the tenant has enough <code>Ether</code> in his wallet to pay a one-time security deposit and one month's rent in advance.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier enoughAgreementfee(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.value &gt;= uint(uint(</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].rent_per_month) + uint(</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].securityDeposit)), </span><span class=\"mtk8\">&quot;Not enough Ether in your wallet&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether the tenant's address is the same as who has signed the previous rental agreement.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier sameTenant(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender == </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].currentTenant, </span><span class=\"mtk8\">&quot;No previous agreement found with you & landlord&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether any time is left for the agreement to end.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier </span><span class=\"mtk12\">AgreementTimesLeft</span><span class=\"mtk1\">(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint </span><span class=\"mtk12\">_AgreementNo</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].agreementid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint time = </span><span class=\"mtk10\">RoomAgreement_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_AgreementNo</span><span class=\"mtk1\">].timestamp + </span><span class=\"mtk10\">RoomAgreement_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_AgreementNo</span><span class=\"mtk1\">].lockInPeriod;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(now &lt; time, </span><span class=\"mtk8\">&quot;Agreement already Ended&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether 365 days have passed after the last agreement has been created.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"17\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier </span><span class=\"mtk12\">AgreementTimesUp</span><span class=\"mtk1\">(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint </span><span class=\"mtk12\">_AgreementNo</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].agreementid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint time = </span><span class=\"mtk10\">RoomAgreement_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_AgreementNo</span><span class=\"mtk1\">].timestamp + </span><span class=\"mtk10\">RoomAgreement_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_AgreementNo</span><span class=\"mtk1\">].lockInPeriod;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(now &gt; time, </span><span class=\"mtk8\">&quot;Time is left for contract to end&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>The following will check whether 30 days have passed after the last rent payment.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"18\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    modifier </span><span class=\"mtk12\">RentTimesUp</span><span class=\"mtk1\">(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint time = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].timestamp + </span><span class=\"mtk7\">30</span><span class=\"mtk1\"> days;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(now &gt;= time, </span><span class=\"mtk8\">&quot;Time left to pay Rent&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<ol start=\"11\">\n<li>Now, create some <a href=\"https://docs.soliditylang.org/en/v0.4.24/introduction-to-smart-contracts.html\"><strong>functions</strong></a></li>\n</ol>\n<p>The following function will be used to add Rooms.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"19\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    function addRoom(string memory </span><span class=\"mtk12\">_roomname</span><span class=\"mtk1\">, string memory </span><span class=\"mtk12\">_roomaddress</span><span class=\"mtk1\">, uint </span><span class=\"mtk12\">_rentcost</span><span class=\"mtk1\">, uint  </span><span class=\"mtk12\">_securitydeposit</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender != address(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        no_of_rooms ++;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        bool </span><span class=\"mtk12\">_vacancy</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[no_of_rooms] = </span><span class=\"mtk12\">Room</span><span class=\"mtk1\">(no_of_rooms,</span><span class=\"mtk7\">0</span><span class=\"mtk1\">,</span><span class=\"mtk12\">_roomname</span><span class=\"mtk1\">,</span><span class=\"mtk12\">_roomaddress</span><span class=\"mtk1\">, </span><span class=\"mtk12\">_rentcost</span><span class=\"mtk1\">,</span><span class=\"mtk12\">_securitydeposit</span><span class=\"mtk1\">,</span><span class=\"mtk7\">0</span><span class=\"mtk1\">,</span><span class=\"mtk12\">_vacancy</span><span class=\"mtk1\">, msg.sender, address(</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 class=\"mtk1\">    }</span></span></code></pre>\n<p>Now, create a function to sign the rental agreement for a hostel room between the landlord and a tenant.</p>\n<p>Before creating the <code>signAgreement</code> function, remember the following:</p>\n<ul>\n<li>The function will only execute if the user is <code>Tenant</code>, meaning that the user's address and the landlord's address don't match.</li>\n<li>The function will only execute if the user has enough ether (payable 'ether') in their Ethereum wallet.(Enough ether means = one-time security deposit + 1st month's rent)</li>\n</ul>\n<p>Let's use those modifiers here, so that:</p>\n<ul>\n<li>The function <code>signAgreement</code> will only execute only if the said room is vacant and the tenant has enough ether in their wallet.</li>\n</ul>\n<p>Remember those modifiers in point no.10? Use those modifiers here to execute the following function.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"20\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    function signAgreement(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> payable notLandLord(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) enoughAgreementfee(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk12\">OnlyWhileVacant</span><span class=\"mtk1\">(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender != address(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable </span><span class=\"mtk12\">_landlord</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].landlord;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint totalfee = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].rent_per_month + </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].securityDeposit;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_landlord</span><span class=\"mtk1\">.transfer(totalfee);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        no_of_agreement++;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].currentTenant = msg.sender;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].vacant = </span><span class=\"mtk4\">false</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].timestamp = block.timestamp;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].agreementid = no_of_agreement;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">RoomAgreement_by_No</span><span class=\"mtk1\">[no_of_agreement]=</span><span class=\"mtk12\">RoomAgreement</span><span class=\"mtk1\">(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">,no_of_agreement,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].roomname,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].roomaddress,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].rent_per_month,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].securityDeposit,</span><span class=\"mtk7\">365</span><span class=\"mtk1\"> days,block.timestamp,msg.sender,</span><span class=\"mtk12\">_landlord</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        no_of_rent++;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Rent_by_No</span><span class=\"mtk1\">[no_of_rent] = </span><span class=\"mtk12\">Rent</span><span class=\"mtk1\">(no_of_rent,</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">,no_of_agreement,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].roomname,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].roomaddress,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].rent_per_month,now,msg.sender,</span><span class=\"mtk12\">_landlord</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>Now, create a function that the tenant will use to pay the monthly rent to the landlord.</p>\n<p>Before creating the <code>payRent</code> function, remember the following:</p>\n<ul>\n<li>The function will only execute if the user's address and previous tenant's address both are the same, meaning that the user can only pay rent if he/she has signed an agreement with the landlord within the last 365 days.</li>\n<li>The function will only execute if the tenant had paid his/her previous rent more than a month ago.</li>\n<li>The function will only execute if the user has enough ether (payable 'ether') in his/her Ethereum wallet. (enough ether = enough room rent).</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"21\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    function payRent(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> payable sameTenant(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk12\">RentTimesUp</span><span class=\"mtk1\">(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) enoughRent(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender != address(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        address payable </span><span class=\"mtk12\">_landlord</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].landlord;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        uint </span><span class=\"mtk12\">_rent</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].rent_per_month;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">_landlord</span><span class=\"mtk1\">.transfer(</span><span class=\"mtk12\">_rent</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].currentTenant = msg.sender;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].vacant = </span><span class=\"mtk4\">false</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        no_of_rent++;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Rent_by_No</span><span class=\"mtk1\">[no_of_rent] = </span><span class=\"mtk12\">Rent</span><span class=\"mtk1\">(no_of_rent,</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].agreementid,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].roomname,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].roomaddress,</span><span class=\"mtk12\">_rent</span><span class=\"mtk1\">,now,msg.sender,</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].landlord);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<p>Let's create a function that the landlord will use to mark an agreement complete.</p>\n<p>Before creating <code>agreementCompleted</code> function, remember the following:</p>\n<ul>\n<li>The function will only execute if the user's address and the landlord's address are the same.</li>\n<li>\n<p>The function will only execute if the tenant had signed that agreement more than a year ago.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"22\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">function agreementCompleted(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> payable onlyLandlord(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk12\">AgreementTimesUp</span><span class=\"mtk1\">(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender != address(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(</span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].vacant == </span><span class=\"mtk4\">false</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Room is currently Occupied.&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].vacant = </span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    address payable </span><span class=\"mtk12\">_Tenant</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].currentTenant;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    uint </span><span class=\"mtk12\">_securitydeposit</span><span class=\"mtk1\"> = </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].securityDeposit;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">_Tenant</span><span class=\"mtk1\">.transfer(</span><span class=\"mtk12\">_securitydeposit</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n</li>\n</ul>\n<p>Let's create a function that the landlord will use to terminate an agreement.</p>\n<p>Before creating <code>agreementTerminated</code> function, remember the following:</p>\n<ul>\n<li>The function will only execute if the user's address and the landlord's address are the same.</li>\n<li>The function will only execute if the tenant had signed that agreement less than a year ago.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"ruby\" data-index=\"23\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">    function agreementTerminated(uint </span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk4\">public</span><span class=\"mtk1\"> onlyLandlord(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">) </span><span class=\"mtk12\">AgreementTimesLeft</span><span class=\"mtk1\">(</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">require</span><span class=\"mtk1\">(msg.sender != address(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">Room_by_No</span><span class=\"mtk1\">[</span><span class=\"mtk12\">_index</span><span class=\"mtk1\">].vacant = </span><span class=\"mtk4\">true</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span></code></pre>\n<h3 id=\"compile\" style=\"position:relative;\"><a href=\"#compile\" aria-label=\"compile 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>Compile</h3>\n<p>Now, click on the <code>Solidity Compile</code> option in the left sidebar.</p>\n<ol>\n<li>Select compiler version <code>0.5.16+</code></li>\n<li>Then click on <code>Compile Hostel.sol</code></li>\n</ol>\n<p>Similar to as follows:</p>\n<img alt=\"Compiler\" height=\"400px\" src=\"/5ce5c32de28546a86432392cbf54dd65/img1.webp\"/>\n<h3 id=\"deploy\" style=\"position:relative;\"><a href=\"#deploy\" aria-label=\"deploy 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>Deploy</h3>\n<p>Click on the <code>Deploy &#x26; Run Transactions</code> option in the left sidebar.</p>\n<ol>\n<li>Choose <code>Environment</code> > <code>JavaScript VM (London)</code></li>\n<li>Now click on <code>Deploy</code></li>\n</ol>\n<img alt=\"Deploy\" height=\"400px\" src=\"/513485d83b050cdc5ad7c27659bc5401/img2.webp\">\n<p><strong>🎉 Congratulations, your smart contract has been deployed. 🎉</strong></p>\n<h3 id=\"sample-transactions\" style=\"position:relative;\"><a href=\"#sample-transactions\" aria-label=\"sample transactions 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>Sample Transactions</h3>\n<p>Remember that whenever a transaction is getting executed, it stores all the details in a unique <code>hash</code> key.</p>\n<p>Now, under <code>Deployed Contract</code> click on <code>> HOSTEL AT ..... (MEMORY)</code></p>\n<ol>\n<li>Click on the <code>V</code> icon (dropdown menu) of <code>addRoom</code> function.</li>\n<li>Fill up the details.</li>\n</ol>\n<p>Similar to as follows:</p>\n<img height=\"250px\" alt=\"AddRoom\" src=\"/61f7bcd783df9bf205cf8665b3747648/img3.webp\">\n<blockquote>\n<p><strong>Note:</strong> You're entering your details in <code>wei</code> not in <code>ether</code> (1 ether = 1000000000000000000 wei)</p>\n</blockquote>\n<ol start=\"3\">\n<li>\n<p>Then click on <code>transact</code></p>\n<p><strong>🎉 Congratulations, you've successfully added your 1st room in the contract. 🎉</strong></p>\n<p>(You can find the same in the terminal also.)</p>\n<p>Now the landlord of the room is your 1st Ether Address. (The one with 99.99 test ether in wallet.)</p>\n</li>\n<li>Change the <code>Account Address</code> from the dropdown menu. (Choose anyone except the one with 99.99 ether)</li>\n</ol>\n<img height=\"300px\" alt=\"Change Address\" src=\"/5df1597fa3a2d5e7554be241d599716c/img4.webp\">\n<ol start=\"5\">\n<li>Add the total amount you have previously chosen as (rent cost + security deposit)</li>\n<li>And then from the dropdown <code>wei</code>, choose <code>ether</code></li>\n</ol>\n<img height=\"300px\" alt=\"Change Value\" src=\"/9ce22e6fbeb12b420b5e4cb098ee525a/img5.webp\">\n<ol start=\"7\">\n<li>\n<p>Scroll down and click on <code>signAgreement</code>, enter <code>1</code>, and press <code>signAgreement</code></p>\n<p>You can check the same by entering <code>RoomAgreementNo</code> : <code>1</code></p>\n</li>\n</ol>\n<img height=\"300px\" alt=\"Agreement Details\" src=\"/19fa5bc82fa0c7ab9f8f869751d48c78/img6.webp\">\n<p><strong>🎉 Congratulations, you've successfully signed your 1st agreement. 🎉</strong></p>\n<p>All your transactions are shown in the <code>terminal</code>.</p>\n<img height=\"300px\" alt=\"Terminal\" src=\"/03a9636e1732d7907a857aade4a8d017/img7.webp\">\n<p>Now, you can cross verify this by checking your <code>ether</code> account address.</p>\n<h2 id=\"advantages-of-smart-contracts\" style=\"position:relative;\"><a href=\"#advantages-of-smart-contracts\" aria-label=\"advantages of smart contracts 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>Advantages of Smart Contracts</h2>\n<p>Now you may ask, \"what's the use of smart contracts when there are several centralized methods?\"</p>\n<p>Let me explain some advantages of smart contracts over centralized systems:</p>\n<ol>\n<li>Here data cannot be changed or tampered with. So, it is almost impossible for malicious actors to manipulate data.</li>\n<li>It's completely decentralized.</li>\n<li>Unlike any centralized payment wallet, you don't have to pay any commission percentages to a middle man to transact.</li>\n</ol>\n<h3 id=\"storage--others\" style=\"position:relative;\"><a href=\"#storage--others\" aria-label=\"storage  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>Storage &#x26; Others</h3>\n<p>You may also ask \"how are all the transactions recorded?\"</p>\n<p>You have to remember that smart contracts store data in a block of the blockchain, and all transactions are stored with a unique <code>hash</code> key.</p>\n<p>In Remix IDE, you can download the complete transactions history as a JSON file. For that, follow these steps:</p>\n<ol>\n<li>Click <code>Deploy &#x26; Run Transaction</code></li>\n<li>Then, expand the <code>Transactions Recorded (..) V</code> dropdown menu.</li>\n<li>Then Click on the <code>Save</code> icon.</li>\n<li>Press <code>ok</code>.</li>\n</ol>\n<h3 id=\"gas-fee\" style=\"position:relative;\"><a href=\"#gas-fee\" aria-label=\"gas fee 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>Gas Fee</h3>\n<p>You may have noticed that whenever a transaction is executed, a few <code>wei</code> is getting deducted from your ether wallet.</p>\n<p>It's called <em>gas fee</em>, which is the payment made by users to compensate for the computing energy required to process and validate transactions.</p>\n<p>As more Ethereum miners come up in near future, the <code>gas fee</code> will decrease in an inverse relation.</p>\n<h3 id=\"future-possibilities\" style=\"position:relative;\"><a href=\"#future-possibilities\" aria-label=\"future possibilities 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>Future Possibilities</h3>\n<p>After this, if you want to build a fullstack website using React, you can use this smart contract as a backend.</p>\n<p>For that you need to install/download: </p>\n<p><strong>Frontend:</strong></p>\n<ol>\n<li><a href=\"https://nodejs.org/en/\">Node.js</a></li>\n</ol>\n<p><strong>Backend:</strong></p>\n<ol>\n<li><a href=\"https://www.npmjs.com/package/web3\">web3.js</a></li>\n<li><a href=\"https://www.trufflesuite.com/docs/truffle/getting-started/installation\">Truffle</a></li>\n</ol>\n<p><strong>Testing:</strong></p>\n<ol>\n<li><a href=\"https://www.trufflesuite.com/ganache\">Ganache</a></li>\n<li><a href=\"https://metamask.io/\">Metamask</a></li>\n</ol>\n<p>Just follow the <a href=\"https://web3js.readthedocs.io/en/v1.5.2/\">official documentation</a> of Web3.js to connect your smart contract with your React app.</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>You've successfully understood what Solidity is and how smart contracts work. And you've successfully built and deployed a perfectly working smart contract (where a tenant can pay rent in ether (ETH) directly to the landlord's wallet without paying a single wei to a middle man).</p>\n<p>To download the complete code used in this tutorial, click <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Solidity/decentralised-pg-booking-system-using-ethereum-smart-contract\">here</a>.</p>\n<p>Want to quickly add user login and signup functionality to your React apps? <a href=\"https://www.loginradius.com/authentication/\">Use LoginRadius for free.</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 .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n</style>","frontmatter":{"date":"November 24, 2021","updated_date":null,"description":"Smart contracts are an exciting way to build decentralized applications (dapps) on a blockchain. This tutorial helps you learn and build your first smart contract using Solidity on Ethereum blockchain.","title":"Build Your First Smart Contract with Ethereum & Solidity","tags":["Blockchain","Ethereum","Solidity"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/228990fbfc76ea8c2e7af2b164f89999/58556/coverimage.webp","srcSet":"/static/228990fbfc76ea8c2e7af2b164f89999/61e93/coverimage.webp 200w,\n/static/228990fbfc76ea8c2e7af2b164f89999/1f5c5/coverimage.webp 400w,\n/static/228990fbfc76ea8c2e7af2b164f89999/58556/coverimage.webp 800w,\n/static/228990fbfc76ea8c2e7af2b164f89999/99238/coverimage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Aritra Belel","github":"belelaritra","avatar":null}}}},{"node":{"excerpt":"JSON (JavaScript Object Notation) is a text-based, language-independent format that is easily understandable by humans and machines. JOSE…","fields":{"slug":"/engineering/guest-post/what-are-jwt-jws-jwe-jwk-jwa/"},"html":"<p>JSON (JavaScript Object Notation) is a text-based, language-independent format that is easily understandable by humans and machines.</p>\n<p>JOSE (Javascript Object Signing and Encryption) is a framework used to facilitate the secure transfer of claims between any two parties. Its specifications provide a general approach to encryption of any content, not necessarily in JSON. However, it is built on JSON for easy use in web applications. Let's explore some of these specifications.</p>\n<h2 id=\"jwt--json-web-token\" style=\"position:relative;\"><a href=\"#jwt--json-web-token\" aria-label=\"jwt  json web token 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>JWT — JSON Web Token</h2>\n<p><a href=\"https://www.loginradius.com/blog/engineering/guest-post/jwt-authentication-best-practices-and-when-to-use/\">JWT</a> is a standard mechanism used for authentication. It is compact and URL-safe to represent the claims to be transferred between two parties. Claims are a set of key/value pairs that provide a target system with information about a client to apply an appropriate level of access control to its resources. Claim names could be Registered (IANA), Public, or Private. Some registered claim names are:</p>\n<ul>\n<li>\"iss\": Issuer claim — identifies the issuer of the claim</li>\n<li>\"sub\": Subject claim — identifying the subject of a claim</li>\n<li>\"jti\": JWT ID — Uniquely identify a claim</li>\n</ul>\n<h3 id=\"structure\" style=\"position:relative;\"><a href=\"#structure\" aria-label=\"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>Structure</h3>\n<p>JWT is mainly composed of three parts: header, payload, and signature that are Base64 URL-encoded.</p>\n<ul>\n<li>The header is used to identify the algorithm used to generate a signature.</li>\n<li>The payload consists of the claims and signature (secret key) used to validate the token.</li>\n<li>The structure of sending the information could be Serialized or Deserialized. In the Serialized form, JWT is represented as a string containing the header, payload, and signature separated by dots.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">[header].[payload].[signature]</span></code></pre>\n<p>Here's a simple JWT example.</p>\n<p>JSON Web Token:</p>\n<p><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTIzNDU2Nzg5LCJuYW1lIjoiSm9zZXBoIn0.OpOSSw7e485LOP5PrzScxHb7SR6sAOMRckfFwi4rp7o</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">header:</span>\n<span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">  &quot;alg&quot; : &quot;HS256&quot;,                      Header</span>\n<span class=\"grvsc-line\">                            ---------------------------------&gt;  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9</span>\n<span class=\"grvsc-line\">  &quot;typ&quot; : &quot;JWT&quot;</span>\n<span class=\"grvsc-line\">}</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">Payload:</span>\n<span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">  &quot;id&quot; : 123456789,                     Payload</span>\n<span class=\"grvsc-line\">                            ---------------------------------&gt;  eyJpZCI6MTIzNDU2Nzg5LCJuYW1lIjoiSm9zZXBoIn0</span>\n<span class=\"grvsc-line\">  &quot;name&quot; : &quot;Joseph&quot;</span>\n<span class=\"grvsc-line\">}</span>\n<span class=\"grvsc-line\">                                                Signature</span>\n<span class=\"grvsc-line\">OpOSSw7e485LOP5PrzScxHb7SR6sAOMRckfFwi4rp7o  ----------------&gt;  OpOSSw7e485LOP5PrzScxHb7SR6sAOMRckfFwi4rp7o</span></code></pre>\n<p>This shows the decoded JSON Web Token. In the deserialized form, JWT contains only the header and the payload as plain JSON objects.</p>\n<h2 id=\"jws--json-web-signature\" style=\"position:relative;\"><a href=\"#jws--json-web-signature\" aria-label=\"jws  json web signature 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>JWS — JSON Web Signature</h2>\n<p>JWS is used to represent content secured with digital signatures or Hash-based Message Authentication Codes (HMACs) with the help of JSON data structures. It cryptographically secures a JWS Header and JWS Payload with a JWS Signature. The encoded strings of these three are concatenated using dots similar to JWT. The identifiers and algorithms used are specified in the JSON Web Algorithms specification.</p>\n<p>The JWS Header MUST contain an alg parameter, as it uses the algorithm to encode the JWS Header and the JWS Payload to produce the JWS Signature. Some of the commonly used algorithms to sign the JWS Header and Payload are:</p>\n<ul>\n<li>HMAC using SHA-256 or SHA-512 hash algorithms (HS256, HS512)</li>\n<li>RSA using SHA-256 or SHA-512 hash algorithms (RS256, RS512)</li>\n</ul>\n<p>JWS example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9 ----------------&gt; JWS Header</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ --------------&gt; JWS Payload</span></code></pre>\n<p>It has an Encoded JWS Header followed by an Encoded JWS Payload separated by a '.'. This is the JWS Signing input which, on signing with the HMAC SHA-256 algorithm and base64url encoding, gives the Encoded JWS Signature value:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk</span></code></pre>\n<p>On concatenation:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk</span></code></pre>\n<p>Learn more about JWS <a href=\"https://openid.net/specs/draft-jones-json-web-signature-04.html\">here</a></p>\n<h2 id=\"jwe--json-web-encryption\" style=\"position:relative;\"><a href=\"#jwe--json-web-encryption\" aria-label=\"jwe  json web encryption 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>JWE — JSON Web Encryption</h2>\n<p>JSON Web Encryption enables encrypting a token so that only the intended recipient can read it. It standardizes the way to represent the encoded data in a JSON data structure. Representation of the encrypted payload may be by JWE compact serialization or JWE JSON serialization.</p>\n<h3 id=\"structure-1\" style=\"position:relative;\"><a href=\"#structure-1\" aria-label=\"structure 1 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>Structure</h3>\n<p>The JWE compact serialization form has five main components:</p>\n<ol>\n<li>JOSE header</li>\n<li>JWE Encrypted Key</li>\n<li>JWE initialization vector</li>\n<li>JWE Ciphertext</li>\n<li>JWE Authentication Tag</li>\n</ol>\n<p>All these components are base64url-encoded and are concatenated using dots (<code>.</code>).</p>\n<ul>\n<li>\n<p>The JOSE Header, the first element of the token, is the same as the headers of the previously mentioned JWT and JWS.</p>\n<p>JWE has additional elements to the Header — <code>enc</code> and <code>zip</code>.</p>\n<p><code>enc</code> defines the <em>content encryption algorithm</em> while the <code>alg</code> element defines the encryption algorithm for the <em>Content Encryption Key (CEK)</em>.</p>\n<p><code>zip</code> provides a compression algorithm if token compression is needed.</p>\n</li>\n<li>During the encryption process, the issuer generates a random key, which is 256-bits in size, that is used to encrypt the message. This is placed in the JWE Encrypted key section.</li>\n<li>Some encryption algorithms require an initialization vector, which is a randomly generated number that is used along with a secret key to encrypt data. This prevents repeated encryption of the same data using the same secret key. The recipient requires this initialization vector to decrypt the message, and hence, is placed in the JWE token.</li>\n<li>The fourth section of the token is the JWE ciphertext that is computed by encrypting the plaintext JSON payload. It uses the algorithm mentioned in the header's <code>enc</code> element.</li>\n<li>The JWE Authentication Tag is the last part of the JWE Token generated along with the ciphertext. It ensures the integrity of the ciphertext.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"> &quot;header&quot;:</span>\n<span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">    &quot;alg&quot; : &quot;RSA-OAEP&quot;,                --------------------&gt; For content encryption key</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    &quot;enc&quot; : &quot;A256GCM&quot;                  --------------------&gt; For content encryption algorithm</span>\n<span class=\"grvsc-line\">},</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"> &quot;encrypted_key&quot; : &quot;qtF60gW8O8cXKiYyDsBPX8OL0GQfhOxwGWUmYtHOds7FJWTNoSFnv5E6A_Bgn_2W&quot;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">&quot;iv&quot; : &quot;HRhA5nn8HLsvYf8F-BzQew&quot;,       --------------------&gt; initialization vector</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">&quot;ciphertext&quot; : &quot;ai5j5Kk43skqPLwR0Cu1ZIyWOTUpLFKCN5cuZzxHdp0eXQjYLGpj8jYvU8yTu9rwZQeN9EY0_81hQHXEzMQgfCsRm0HXjcEwXInywYcVLUls8Yik&quot;,</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">&quot;tag&quot; : &quot;thh69dp0Pz73kycQ&quot;             --------------------&gt; Authentication tag</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>Learn more about JWE <a href=\"https://datatracker.ietf.org/doc/html/draft-jones-json-web-encryption\">here</a></p>\n<h2 id=\"jwk--json-web-key\" style=\"position:relative;\"><a href=\"#jwk--json-web-key\" aria-label=\"jwk  json web key 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>JWK — JSON Web Key</h2>\n<p>JWK is a JSON structure representing a set of public keys as a JSON object using the Elliptic Curve or RSA algorithms. Public key representations can help verify the signature with the corresponding private key.</p>\n<h3 id=\"structure-2\" style=\"position:relative;\"><a href=\"#structure-2\" aria-label=\"structure 2 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>Structure</h3>\n<p>JWK consists of a JWK Container Object and an array of JWK Key Objects.</p>\n<ul>\n<li>The JWK Container Object is a JSON object that contains a specific member that is an array. This member is a required element in the Container Object.</li>\n<li>The JWK Key Objects are stored within the array of the JWK Container object. They have a set of members that is common to all key types. As mentioned before, JWK Key objects can use Elliptic Curve or RSA algorithms. To do so, the <code>alg</code> field must hold <code>EC</code> or <code>RSA</code>, respectively. Here is an example of a JWK using RSA:</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">{</span>\n<span class=\"grvsc-line\">&quot;alg&quot;:&quot;RSA&quot;,</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">&quot;mod&quot;: &quot;0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs</span>\n<span class=\"grvsc-line\">tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI</span>\n<span class=\"grvsc-line\">SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw&quot;,</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">&quot;exp&quot;:&quot;AQAB&quot;,</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">&quot;kid&quot;:&quot;2011-04-29&quot;</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<p>It provides a Key ID for matching.</p>\n<h2 id=\"jwa--json-web-algorithms\" style=\"position:relative;\"><a href=\"#jwa--json-web-algorithms\" aria-label=\"jwa  json web algorithms 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>JWA — JSON Web Algorithms</h2>\n<p>The JWA specification focuses mainly on enumerating the algorithms necessary for JWS, JWK AND JWE. It also describes the operations that are specific to these algorithms and key types.</p>\n<p><strong>Algorithms for JWS:</strong> These algorithms are used to sign the contents of the JWS Header and the JWS Payload</p>\n<figure>\n  <img src=\"/fc6a7de2f489ae211efdce5772825f45/JWS_algo.webp\" alt=\"JWS algorithms\" align=\"center\">\n  <figcaption align=\"center\">Source: <a href=\"https://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-10.html\">ietf-jose-json-web-algorithms</a></figcaption>\n</figure>\n<p><strong>Algorithms for JWE</strong> These algorithms encrypt the Content Encryption Key (CEK) and produce the JWE Encrypted Key</p>\n<figure>\n  <img src=\"/fe11d3345c9923bed40f6eb944d6b0f1/JWE_algo.webp\" alt=\"JWE algorithms\" align=\"center\">\n  <figcaption align=\"center\">Source: <a href=\"https://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-10.html\">ietf-jose-json-web-algorithms</a> </figcaption>\n</figure>\n<p><strong>Algorithms for JWK:</strong> JWA specifies a set of algorithm families to be used for the public keys represented by JWK</p>\n<figure>\n  <img src=\"/c6bc6931be2e66587f6f3dfcd7806e10/JWK_algo.webp\" align=\"center\">\n  <figcaption align=\"center\">Source: <a href=\"https://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-10.html\">ietf-jose-json-web-algorithms</a> </figcaption>\n</figure>\n<p>Learn more about JWA <a href=\"https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-algorithms-40\">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>The IETF JSON Object Signing and Encryption (JOSE) working group was chartered to develop a secure object format based on JSON and simplify adding object-based security features to internet applications.</p>\n<p>The basic requirements for these object formats are confidentiality and integrity mechanisms encoded in JSON. JWT, JWS, JWE, JWK, and JWA are the JOSE working group items intended to describe these object formats.</p>\n<p>The JOSE specifications have many use cases and are sought out for integrity protection, encryption, security tokens, OAuth, web cryptography, etc. Check out <a href=\"https://datatracker.ietf.org/doc/rfc7165/\">this site</a> to know more about JOSE use cases.</p>\n<p>Want to learn how to use JWT for authentication in your apps? Check out this informational <a href=\"https://www.loginradius.com/blog/engineering/guest-post/jwt-authentication-best-practices-and-when-to-use/\">JWT authentication guide</a>.</p>\n<p><strong>References:</strong></p>\n<ul>\n<li><a href=\"https://tools.ietf.org/\">IETF</a></li>\n<li><a href=\"https://openid.net/\">OpenID</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  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"November 24, 2021","updated_date":null,"description":"Learn about the JOSE framework and its specifications, including JSON Web Token (JWT), JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), and JSON Web Algorithms (JWA). For easier reference, bookmark this article.","title":"What are JWT, JWS, JWE, JWK, and JWA?","tags":["JSON","Encryption"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/7898fa94ca50b14a5edee22b6dd76018/58556/coverImage.webp","srcSet":"/static/7898fa94ca50b14a5edee22b6dd76018/61e93/coverImage.webp 200w,\n/static/7898fa94ca50b14a5edee22b6dd76018/1f5c5/coverImage.webp 400w,\n/static/7898fa94ca50b14a5edee22b6dd76018/58556/coverImage.webp 800w,\n/static/7898fa94ca50b14a5edee22b6dd76018/99238/coverImage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Yashesvinee V","github":"Yashesvinee","avatar":null}}}},{"node":{"excerpt":"In this tutorial, you'll learn how to easily convert an OpenCV project into a web app that you can showcase. You'll use a library called…","fields":{"slug":"/engineering/guest-post/opencv-web-app-with-streamlit/"},"html":"<p>In this tutorial, you'll learn how to easily convert an OpenCV project into a web app that you can showcase. You'll use a library called Streamlit, which helps you easily build a web user interface in Python. Yes, you heard it right — no HTML, CSS, or JavaScript required. Just Python!</p>\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<ul>\n<li>You should be comfortable using basic <a href=\"https://opencv.org/\">OpenCV</a> functions.</li>\n<li>You should be comfortable coding in Python.</li>\n</ul>\n<p>Let's get started.</p>\n<h2 id=\"install-dependencies\" style=\"position:relative;\"><a href=\"#install-dependencies\" aria-label=\"install dependencies 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 Dependencies</h2>\n<p>Install OpenCV and Streamlit using pip. You would also need Pillow — another image library.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"py\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">pip install opencv-python streamlit Pillow</span></span></code></pre>\n<blockquote>\n<p>If you use Python 2.7, note that OpenCV doesn't directly support Python 2.7 in their latest versions. Accordingly, you have to specify an older version like this <code>pip install opencv-python==4.2.0.32</code></p>\n</blockquote>\n<h2 id=\"create-a-small-opencv-project\" style=\"position:relative;\"><a href=\"#create-a-small-opencv-project\" aria-label=\"create a small opencv project 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>Create a Small OpenCV Project</h2>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"py\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> cv2</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">brighten_image</span><span class=\"mtk1\">(</span><span class=\"mtk12\">image</span><span class=\"mtk1\">, </span><span class=\"mtk12\">amount</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    img_bright = cv2.convertScaleAbs(image, </span><span class=\"mtk12\">beta</span><span class=\"mtk1\">=amount)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> img_bright</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">blur_image</span><span class=\"mtk1\">(</span><span class=\"mtk12\">image</span><span class=\"mtk1\">, </span><span class=\"mtk12\">amount</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    img = cv2.cvtColor(image, </span><span class=\"mtk7\">1</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    blur_img = cv2.GaussianBlur(img, (</span><span class=\"mtk7\">11</span><span class=\"mtk1\">, </span><span class=\"mtk7\">11</span><span class=\"mtk1\">), amount)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> blur_img</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">enhance_details</span><span class=\"mtk1\">(</span><span class=\"mtk12\">img</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    hdr = cv2.detailEnhance(img, </span><span class=\"mtk12\">sigma_s</span><span class=\"mtk1\">=</span><span class=\"mtk7\">12</span><span class=\"mtk1\">, </span><span class=\"mtk12\">sigma_r</span><span class=\"mtk1\">=</span><span class=\"mtk7\">0.15</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> hdr</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">img = cv2.imread(</span><span class=\"mtk12\">filename</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&#39;tony_stark.webp&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\"># do some cool image processing stuff</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">img = enhance_details(img)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">img = brighten_image(img, </span><span class=\"mtk12\">amount</span><span class=\"mtk1\">=</span><span class=\"mtk7\">25</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">img = blur_image(img, </span><span class=\"mtk12\">amount</span><span class=\"mtk1\">=</span><span class=\"mtk7\">0.2</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">cv2.imshow(</span><span class=\"mtk8\">&#39;Tony Stark&#39;</span><span class=\"mtk1\">, img)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">cv2.waitKey(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">cv2.destroyAllWindows()</span></span></code></pre>\n<p>Here are three image processing functions that accept an image, do some processing, and return the processed image.</p>\n<ol>\n<li><code>brighten_image</code> — increases the brightness of the image.</li>\n<li><code>blur_image</code> — applies a blur effect on the image.</li>\n<li><code>enhance_details</code> — applies an effect to enhance the details of the image.</li>\n</ol>\n<p>These functions make use of the OpenCV functions to do the actual processing — for e.g.: cv2.GaussianBlur, etc. I'm not explaining in-depth about them and the various parameters they accept since this tutorial is more focused on integrating OpenCV with Streamlit. However, feel free to jump to the OpenCV documentation to know more details about them. </p>\n<p>This program reads the image from the <code>filepath</code> using <code>cv2.imread()</code>; then, it passes the image to these functions that do the processing. Finally, the image is displayed using <code>cv2.imshow()</code>. <code>cv2.waitKey(0)</code> is to wait till the user presses any key, after which the program is exited.</p>\n<h2 id=\"streamlit-basics\" style=\"position:relative;\"><a href=\"#streamlit-basics\" aria-label=\"streamlit basics 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>Streamlit Basics</h2>\n<p>Streamlit offers some common UI components out of the box that you can place on your webpage. This makes it super easy to code up something real quick. The way Streamlit works is that it reruns the Python script every time a user interacts with the components. They have some caching and optimizations, but this simple design makes it easy to build interactive webpages using Streamlit.</p>\n<blockquote>\n<p>Someone said, “Talk is cheap. Show me the code.” So, let's see some code.</p>\n</blockquote>\n<p>Open an editor and copy-paste this to <code>demo-app.py</code></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"py\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> streamlit </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> st</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">st.title(</span><span class=\"mtk8\">&quot;OpenCV Demo App&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">st.subheader(</span><span class=\"mtk8\">&quot;This app allows you to play with Image filters!&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">st.text(</span><span class=\"mtk8\">&quot;We use OpenCV and Streamlit for this demo&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> st.checkbox(</span><span class=\"mtk8\">&quot;Main Checkbox&quot;</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    st.text(</span><span class=\"mtk8\">&quot;Check Box Active&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">slider_value = st.slider(</span><span class=\"mtk8\">&quot;Slider&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">min_value</span><span class=\"mtk1\">=</span><span class=\"mtk7\">0.5</span><span class=\"mtk1\">, </span><span class=\"mtk12\">max_value</span><span class=\"mtk1\">=</span><span class=\"mtk7\">3.5</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">st.text(</span><span class=\"mtk4\">f</span><span class=\"mtk8\">&quot;Slider value is </span><span class=\"mtk4\">{</span><span class=\"mtk1\">slider_value</span><span class=\"mtk4\">}</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">st.sidebar.text(</span><span class=\"mtk8\">&quot;text on side panel&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">st.sidebar.checkbox(</span><span class=\"mtk8\">&quot;Side Panel Checkbox&quot;</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>To start a streamlit app, simply run the command <code>streamlit run</code> with the filename — for example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"py\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">streamlit run demo-app.py</span></span></code></pre>\n<p>You should get a similar output as follows. </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">  You can now view your Streamlit app in your browser.</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">  Local URL: http://localhost:8501</span>\n<span class=\"grvsc-line\">  Network URL: http://192.168.1.8:8501</span></code></pre>\n<p>Click on the links in the output to open the Streamlit app in your browser. You'll see something as follows. </p>\n<p><img src=\"/9202979fe96eb015f5209a8591dbc320/streamlit-1.webp\" alt=\"Streamlit basic web app\" title=\"Streamlit Basic Demo\"></p>\n<p>If you see the code, it's very straightforward. It imports streamlit as st. The default is a simple linear layout where you can place components on the webpage in a sequential manner.</p>\n<p>For example, <code>st.title() , st.checkbox(), st.slider()</code> places the components on the main page in the order they're called.. </p>\n<p>Streamlit also offers a side panel. In order to place components in the sidepanel, you can do as follows:</p>\n<p><code>st.sidebar.title() , st.sidebar.checkbox(), st.sidebar.slider()</code></p>\n<p>There are other components also apart from these. You can <a href=\"https://docs.streamlit.io/library/get-started\">explore more in the docs</a>.</p>\n<h2 id=\"integrate-streamlit-into-your-opencv-project\" style=\"position:relative;\"><a href=\"#integrate-streamlit-into-your-opencv-project\" aria-label=\"integrate streamlit into your opencv project 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>Integrate Streamlit into Your OpenCV Project</h2>\n<p>Let's integrate your OpenCV program into Streamlit. Here is the complete code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"py\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> cv2</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> streamlit </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> st</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> numpy </span><span class=\"mtk15\">as</span><span class=\"mtk1\"> np</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> PIL </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Image</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">brighten_image</span><span class=\"mtk1\">(</span><span class=\"mtk12\">image</span><span class=\"mtk1\">, </span><span class=\"mtk12\">amount</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    img_bright = cv2.convertScaleAbs(image, </span><span class=\"mtk12\">beta</span><span class=\"mtk1\">=amount)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> img_bright</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">blur_image</span><span class=\"mtk1\">(</span><span class=\"mtk12\">image</span><span class=\"mtk1\">, </span><span class=\"mtk12\">amount</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    blur_img = cv2.GaussianBlur(image, (</span><span class=\"mtk7\">11</span><span class=\"mtk1\">, </span><span class=\"mtk7\">11</span><span class=\"mtk1\">), amount)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> blur_img</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">enhance_details</span><span class=\"mtk1\">(</span><span class=\"mtk12\">img</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    hdr = cv2.detailEnhance(img, </span><span class=\"mtk12\">sigma_s</span><span class=\"mtk1\">=</span><span class=\"mtk7\">12</span><span class=\"mtk1\">, </span><span class=\"mtk12\">sigma_r</span><span class=\"mtk1\">=</span><span class=\"mtk7\">0.15</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> hdr</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main_loop</span><span class=\"mtk1\">():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    st.title(</span><span class=\"mtk8\">&quot;OpenCV Demo App&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    st.subheader(</span><span class=\"mtk8\">&quot;This app allows you to play with Image filters!&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    st.text(</span><span class=\"mtk8\">&quot;We use OpenCV and Streamlit for this demo&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    blur_rate = st.sidebar.slider(</span><span class=\"mtk8\">&quot;Blurring&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">min_value</span><span class=\"mtk1\">=</span><span class=\"mtk7\">0.5</span><span class=\"mtk1\">, </span><span class=\"mtk12\">max_value</span><span class=\"mtk1\">=</span><span class=\"mtk7\">3.5</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    brightness_amount = st.sidebar.slider(</span><span class=\"mtk8\">&quot;Brightness&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">min_value</span><span class=\"mtk1\">=-</span><span class=\"mtk7\">50</span><span class=\"mtk1\">, </span><span class=\"mtk12\">max_value</span><span class=\"mtk1\">=</span><span class=\"mtk7\">50</span><span class=\"mtk1\">, </span><span class=\"mtk12\">value</span><span class=\"mtk1\">=</span><span class=\"mtk7\">0</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    apply_enhancement_filter = st.sidebar.checkbox(</span><span class=\"mtk8\">&#39;Enhance Details&#39;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    image_file = st.file_uploader(</span><span class=\"mtk8\">&quot;Upload Your Image&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=[</span><span class=\"mtk8\">&#39;jpg&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&#39;png&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&#39;jpeg&#39;</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=\"mtk4\">not</span><span class=\"mtk1\"> image_file:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">None</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    original_image = Image.open(image_file)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    original_image = np.array(original_image)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    processed_image = blur_image(original_image, blur_rate)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    processed_image = brighten_image(processed_image, brightness_amount)</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\"> apply_enhancement_filter:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        processed_image = enhance_details(processed_image)</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    st.text(</span><span class=\"mtk8\">&quot;Original Image vs Processed Image&quot;</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    st.image([original_image, processed_image])</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">__name__</span><span class=\"mtk1\"> == </span><span class=\"mtk8\">&#39;__main__&#39;</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    main_loop()</span></span></code></pre>\n<p><strong>Let's understand what's happening here.</strong></p>\n<p>Apart from the image processing functions, you have a 'main_loop' function to add the logic for the webpage.</p>\n<p>Nothing fancy about <code>st.title(), st.subheader(), st.text()</code> — they just print some text in different sizes.</p>\n<p>Next, there are two sliders to get the amount by which you need to apply the blur and brightness filters.</p>\n<p>Note that <code>st.sidebar</code> places these components in the sidebar.</p>\n<p><code>slider()</code> takes in some arguments: name of the slider, min value, max value, and the default value of the slider. This function returns the current value of the slider.</p>\n<p>Next, there's a checkbox component.</p>\n<p><code>checkbox()</code> returns <em>True</em> if the checkbox is checked; else, it would return <em>False</em>.</p>\n<p>Next, there's a <code>file_uploader</code> component, through which users can upload files of different types specified by the <code>type</code> parameter. Here, it's restricted to the image file types needed for the demo usecase.</p>\n<p>When the program starts, there are no files selected by the user. At this time, this component returns <em>None</em>. When a file is uploaded from the UI, this component returns the path of the file. </p>\n<p>This is why there's an if-check on the return value of this component. If no files are selected, you can skip the rest of the program by returning from the <code>main_loop()</code> function.</p>\n<p>Remember that the entire program is rerun whenever there's user interaction on any components of the page. When a user uploads a file, the whole program is executed again — and the if-check fails so that the program executes the image processing logic.</p>\n<p><code>Pillow.Image()</code> is used to open this file, then it's converted to a numpy array using <code>np.array()</code> so that OpenCV can process it.</p>\n<p>Now, it's passed to the different processing functions along with the <code>amount</code> parameter.</p>\n<p>Finally, the program displays the original and processed images using the <code>st.image()</code> component.</p>\n<p>The web app is ready! </p>\n<p>To start the app, simply run:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">streamlit run demo-app.py</span></code></pre>\n<p>Now you can play with the filters. Of course, these are some basic filters, but you can extend it to more interesting filters — like cartoonify filters, etc. — using the rich features of OpenCV.</p>\n<p><img src=\"/8a3adfc96648a8ef90ba512e93ba1648/streamlit-final.webp\" alt=\"Streamlit final Screenshot\" title=\"Streamlit OpenCV Webapp\"></p>\n<h2 id=\"how-to-publish-your-app\" style=\"position:relative;\"><a href=\"#how-to-publish-your-app\" aria-label=\"how to publish your 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>How to Publish Your App?</h2>\n<p>To publish your app, you need to host this program somewhere. There are different hosting providers for complex projects. But for this hobby project, is there a simple and quick solution?</p>\n<p>Yes, there's one!</p>\n<p>You can host the Streamlit application in <a href=\"https://streamlit.io/cloud\">Streamlit Cloud</a> for free. You can host up to 3 apps in an account for free with up to 1GB of memory.</p>\n<p>Check out this tutorial from the community to host your app in Streamlit Cloud.</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>You can find the source code for this tutorial <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Python/OpenCV-Streamlit-Integration\">here</a>. The web app discussed above is <a href=\"https://share.streamlit.io/dingusagar/opencv-streamlit-demo/main/demo-app.py\">hosted here</a> if you want to try it out.</p>\n<p>Want to add user authentication and registration in your app quickly? Check out the <a href=\"https://www.loginradius.com/integrations/python/\">LoginRadius Python integration</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 .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n</style>","frontmatter":{"date":"November 10, 2021","updated_date":null,"description":"You can now easily publish your OpenCV apps to the web using Streamlit, a Python library. Follow this tutorial to learn the process step by step.","title":"How to Build an OpenCV Web App with Streamlit","tags":["OpenCV","Streamlit","Python"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/818e31111fb212b94c72ff9edb09bd3f/58556/coverimage.webp","srcSet":"/static/818e31111fb212b94c72ff9edb09bd3f/61e93/coverimage.webp 200w,\n/static/818e31111fb212b94c72ff9edb09bd3f/1f5c5/coverimage.webp 400w,\n/static/818e31111fb212b94c72ff9edb09bd3f/58556/coverimage.webp 800w,\n/static/818e31111fb212b94c72ff9edb09bd3f/99238/coverimage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Dingu Sagar","github":"dingusagar","avatar":null}}}},{"node":{"excerpt":"Why Follow React Coding Best Practices? Writing code to create apps isn't just enough; the code should be as clean and maintainable as your…","fields":{"slug":"/engineering/guest-post/react-best-coding-practices/"},"html":"<h2 id=\"why-follow-react-coding-best-practices\" style=\"position:relative;\"><a href=\"#why-follow-react-coding-best-practices\" aria-label=\"why follow react coding best practices 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 Follow React Coding Best Practices?</h2>\n<p>Writing code to create apps isn't just enough; the code should be as clean and maintainable as your app. Before jumping into the good practices to follow, it's essential to realize the reasons behind the same. It becomes crucial for you to understand coding conventions because of the following reasons:</p>\n<ol>\n<li>As a developer, you shall understand that writing code to build apps is not enough, but the code should also be <em>Reliable</em>, <em>Scalable</em>, and <em>Maintainable</em>. Generally, 40% - 80% of the total cost of software is spent on its maintenance.</li>\n<li><em>Readability is the priority</em>. Any software is seldom fully supported by one single developer; There is a whole team or group of people working on it. Furthermore, new developers always join the project team. Thus,  maintaining coding standards improves the product's readability that lets developers easily understand the codebase even faster.</li>\n<li>Like any product, the software must be well-packaged and clean. Following best coding practices helps you write clean code throughout the codebase by ensuring consistency.</li>\n</ol>\n<h2 id=\"starting-with-react-best-practices\" style=\"position:relative;\"><a href=\"#starting-with-react-best-practices\" aria-label=\"starting with react best practices 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>Starting with React Best Practices</h2>\n<h3 id=\"code-structure\" style=\"position:relative;\"><a href=\"#code-structure\" aria-label=\"code 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>Code Structure</h3>\n<p>There's basically no defined structure, but you should have a style to follow throughout the codebase. Thus, this section explains how you can structure your codebase for medium to large-sized apps.</p>\n<ol>\n<li>\n<p>Put all your imports in order at the very top of the code file. You shall ideally prioritize as follows:</p>\n<p><code>React imports</code> &#x3C;> <code>Library imports</code> &#x3C;> <code>import * as</code> &#x3C;> <code>import ./&#x3C;some file></code></p>\n<p>Make sure all your imports statements are on new lines, as this will make your imports clean and easy to understand for all the components, third-party libraries, etc.</p>\n</li>\n<li>Use <code>index.js</code> for each folder to export so that all the imports are referenced on the <code>index.js</code> file, and you don't have to write import statements again and again for every file.</li>\n<li>\n<p>It's easy to get confused about <em>whether to use double quotes (\" \") or single quotes (' ')</em> while working with React. The simple answer is: <code>maintain consistency</code> whatever you're using. </p>\n<p>Also, consider that you use double quotes (\" \") for <code>JSX</code> attributes and single quotes (' ') for the <code>JS</code> code (Follow the standard way or maintain consistency).</p>\n</li>\n<li>Most of the time, beginners merge two-three components inside a single file and play around with that. However, that's not a good practice to follow. Dividing the whole app into components and then working on it on a separate file is a good practice to maintain clean code.</li>\n<li>Do you sometimes use CSS styles with JSX? But it's a bad practice. Always make <code>classNames</code> for each element and put all the styling under respective CSS files only.</li>\n</ol>\n<h3 id=\"naming-conventions\" style=\"position:relative;\"><a href=\"#naming-conventions\" aria-label=\"naming conventions 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>Naming Conventions</h3>\n<ol>\n<li>Your filenames should always have consistent casing and extension. Either use <code>.js</code> or <code>.jsx</code> as explained in code structure for extensions. And <code>PascalCase</code> or <code>camelCase</code> for filenames.</li>\n<li>In React, name your file the same as the React component inside that file i.e. without a hyphen in the filename. For example: <code>Registration-Form</code> → ❌. <code>RegistrationForm</code> → ✔️.</li>\n<li>Not only filename but also make sure that your <code>variables/functions/modules</code> filenames are consistent with cases.</li>\n<li>Use well-descriptive names for <code>variables/functions/modules/Actions</code>, keeping in mind that it is application-specific so that even a third party or new developer can easily understand you code.</li>\n<li>It's bad to use the underscore prefix ( _ ) for a React component's internal methods because underscore prefixes seem to be used as a convention in other languages to denote private objects or variables. But everything in JavaScript is public. And there is no native support for privacy. So, even if you add underscore prefixes to your properties, It'll not make them private. <code>_onClickSubmit() → ❌</code></li>\n<li>When making reducer functions, write <code>Action</code> types as <code>domain/eventNames</code>. For example: <code>ADD_TODO</code> and <code>INCREMENT</code> (in CAPITALS) as this matches the typical conventions in most programming languges for declaring the constant values.</li>\n<li>Talking about <code>cases</code> in a React component, use <code>PascalCase</code> for the same — and for their instances, use <code>camelCase</code>. For example:-</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">const loginForm = &lt;LoginForm /&gt;;</span>\n<span class=\"grvsc-line\">import LoginForm from &#39;./loginForm&#39;;</span></code></pre>\n<h3 id=\"files-and-folders\" style=\"position:relative;\"><a href=\"#files-and-folders\" aria-label=\"files and folders 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>Files and Folders</h3>\n<ol>\n<li>Your app's directory structure shall be as follows:</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">└── /src</span>\n<span class=\"grvsc-line\">  ├── /assets - Contains static assets such as  images, svgs, company logo etc.</span>\n<span class=\"grvsc-line\">  ├── /components - reusable components like navigation bar, buttons, forms</span>\n<span class=\"grvsc-line\">  ├── /services - JavaSript modules</span>\n<span class=\"grvsc-line\">  ├── /store - redux store</span>\n<span class=\"grvsc-line\">  ├── /utils - utilities, helpers, constants.</span>\n<span class=\"grvsc-line\">  ├── /views/pages - majority of the app pages would be here</span>\n<span class=\"grvsc-line\">  ├── index.js</span>\n<span class=\"grvsc-line\">  └── App.js</span></code></pre>\n<ol start=\"2\">\n<li>Each component folder should have its respective files grouped under the same. It maintains the hierarchy throughout the codebase. The necessary files include:\n<code>Component.js</code>, <code>Component.css</code>, <code>Component.test.js</code></li>\n</ol>\n<h3 id=\"code\" style=\"position:relative;\"><a href=\"#code\" aria-label=\"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>Code</h3>\n<ol>\n<li><em>Play the game of <a href=\"https://www.loginradius.com/blog/engineering/react-hooks-guide/\">HOOKS</a> by following all its rules</em>. You can read more about the rules <a href=\"https://www.smashingmagazine.com/2020/04/react-hooks-best-practices/\">here</a>. Either manually follow these rules or use an ESLint plugin called <code>eslint-plugin-react-hooks</code> which enforces these rules. So, add these rules while working on any project</li>\n<li>Remove <code>console. logs</code> — unless you have strong motivation why you would like it.</li>\n<li>Avoid multiple <code>if-else blocks</code>. Instead, use <code>ternary</code> — best for clean code practice</li>\n<li>Remove all <code>commented-out codes</code>. The biggest motivation for writing comments is the bad code that you write. It would be good to spend more time writing descriptive functions, methods, and filenames that are self-explanatory.</li>\n<li>Write <code>Tests</code> for each component. It's a good practice to write test cases for each component developed as it reduces the chances of getting errors when deployed. You can check all the possible scenarios through unit testing — and for that, some of the most commonly used React test frameworks you can use are <code>JEST</code> and <code>ENZYMES</code>.</li>\n</ol>\n<h3 id=\"good-commenting-practices\" style=\"position:relative;\"><a href=\"#good-commenting-practices\" aria-label=\"good commenting practices 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>Good Commenting Practices</h3>\n<ol>\n<li>Use comments to explain <em>why you did something</em>, not <em>how you did it</em>. If you find yourself explaining  <em>how you did something</em>, then it's time to make your code self-explanatory.</li>\n<li>Another point is not to write comments that are obvious and redundant — for example:</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">// Prints out the sum of two numbers</span>\n<span class=\"grvsc-line\">console.log(sum);</span></code></pre>\n<ol start=\"3\">\n<li>Write comments that are legal, informative, explanatory of intent, and offer clarification,</li>\n</ol>\n<h3 id=\"es6\" style=\"position:relative;\"><a href=\"#es6\" aria-label=\"es6 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>ES6</h3>\n<ol>\n<li>Always destructure your props. Destructuring your props helps make your code cleaner and more maintainable. It also makes assigning object properties to variables feels like much less of a chore.</li>\n<li>Know where to use spread/rest operators. You shall read about it before actually using it.</li>\n<li>Try using <code>optional chaining</code> if possible.</li>\n<li>Use <code>const</code> instead of <code>var</code> or <code>let</code> . <code>const</code> lets you check that a variable should always stay constant. <code>let</code> indicates that the values of the variables can be changed.</li>\n<li>Start preferring <code>arrow functions</code> (= >) for more cleaner code. Arrow functions allow simplifying your code to a single line.</li>\n</ol>\n<h3 id=\"basics\" style=\"position:relative;\"><a href=\"#basics\" aria-label=\"basics 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>Basics</h3>\n<ol>\n<li>Always ensure that your app is responsive.</li>\n<li>Your app should contain a proper <code>README.md</code> file that clearly details or explains your app. Clearly mention the features, functionalities, contributions guidelines, installation process, guide, etc.</li>\n<li>Do check that your app runs without any errors.</li>\n<li>Use <code>EsLint</code> throughout your codebase and other automation tools so that most of the best practices are maintained automatically for you.</li>\n<li>Consolidate duplicate code throughout the codebase.</li>\n</ol>\n<p>Please note that I haven't talked about automation extension and tools that can help you maintain most of the best practices easily without looking into separately. But, I wanted to bring this into consideration. Anyhow, you can use extensions like <code>prettier</code>, <code>EsLint</code>, <code>EditorConfig</code>, <code>PLOP</code> etc., to maintain your codebase efficiently.</p>\n<p>These are the best practices that I've learned practically over time by working in a team, reviewing my mates' codebase, observing open-source projects and repositories, and reading great resources, such as the <a href=\"https://reactjs.org/docs/getting-started.html\">offical React docs</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>I hope you gained valuable insights. If you have more suggestions or practices that the React or dev community can follow, please to let us know.</p>\n<p>Until next time, keep learning, build awesome stuff, and uplift the community.</p>\n<p>By the way, if you want to <a href=\"https://www.loginradius.com/blog/engineering/user-authentication-react-application/\">add user registration and authentication to your React apps</a>, you can use LoginRadius. It helps you become more efficient and focus more on the core business features of your React apps.</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</style>","frontmatter":{"date":"October 26, 2021","updated_date":null,"description":"Important React best practices every React developer should follow before, during, & after writing the code. To ensure code maintainability, keep these React coding best practices handy.","title":"32 React Best Practices That Every Programmer Should Follow","tags":["React"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/ad3a41474714ff1458856a6c47795b66/58556/Best-Practices.webp","srcSet":"/static/ad3a41474714ff1458856a6c47795b66/61e93/Best-Practices.webp 200w,\n/static/ad3a41474714ff1458856a6c47795b66/1f5c5/Best-Practices.webp 400w,\n/static/ad3a41474714ff1458856a6c47795b66/58556/Best-Practices.webp 800w,\n/static/ad3a41474714ff1458856a6c47795b66/99238/Best-Practices.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Anjali Rohira","github":"rohiraanjali","avatar":null}}}},{"node":{"excerpt":"A Progressive Web App (PWA) is a more dynamic web application that can run as a standalone. It offers benefits such as:  performance; the…","fields":{"slug":"/engineering/guest-post/how-to-build-a-progressive-web-app-with-react/"},"html":"<p>A Progressive Web App (PWA) is a more dynamic web application that can run as a standalone. It offers benefits such as: </p>\n<ul>\n<li>performance;</li>\n<li>the ability to work with or without an internet connection;</li>\n<li>platform-specific; and, </li>\n<li>installable.</li>\n</ul>\n<blockquote>\n<p>You can learn more about the <a href=\"https://www.loginradius.com/blog/engineering/progressive-app-vs-native-app/\">differences between native apps and PWAs here.</a></p>\n</blockquote>\n<p>In this article, you're going to learn how to build a PWA using React. As React is a popular web framework, this article starts by going over the setup, development process, and spinning it up to see how it looks. For this example, you'll create a simple Counter Page that simply adds or subtracts a number based on button controls.</p>\n<h2 id=\"create-a-react-app-with-the-progressive-web-app-template\" style=\"position:relative;\"><a href=\"#create-a-react-app-with-the-progressive-web-app-template\" aria-label=\"create a react app with the progressive web app template 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>Create a React App with the Progressive Web App Template</h2>\n<p>Before you can begin coding, you need to set up your project. Let's start by ensuring you can use React (if you're already familiar with coding in React, you can probably skip this section!). You need to use Node.js with any development using web frameworks such as Angular, React, or Vue -- especially if you wish to use libraries and packages to assist in developing your project. </p>\n<p>A popular utility in using such packages and libraries is the Node Package Manager, simply referred to as \"npm\". This utility allows you to install/uninstall packages, start your React application build using webpack, and many more other features. For your needs, you can take advantage of npm to create a React application with a PWA template, which allows you to code right away. Whenever you start building a React app, you can use templates offered by Facebook using the 'create-react-app' command with npm. </p>\n<p>Let's build the PWA starter app by running the following command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npx create-react-app name-of-our-PWA-app --template cra-template-pwa</span></span></code></pre>\n<p>The above command can be broken down as follows:</p>\n<ul>\n<li><strong>npx</strong>: Every npm command needs to start with npm (or essentially with whatever node package manager you have installed, but 'npx' is used here, which comes with npm version 5.2.0). This helps you run npm packages and <a href=\"https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager\">takes care of many features</a>.</li>\n<li><strong>create-react-app</strong>: This command initiates the popular Create React App utility that helps you build the starter react project.</li>\n<li><strong>name-of-our-PWA-app</strong>: This is a filler title of your application. Name the app to whatever you would like. Here, the default 'my-app' name is used)</li>\n<li><strong>--template</strong>: This is an argument. When you have an argument, you're essentially enabling an option in the same command. Here, you can specify a specific template for our starter react application.</li>\n<li><strong>cra-template-pwa</strong>: The name of the PWA template for your PWA react application.</li>\n</ul>\n<p>Hitting 'Enter' after this command should initiate the build of your starter PWA React application. You should see a stream of prompts in your command-line interface. It may take a few minutes, but if you can see this screen after the command, you have created the project.</p>\n<p><img src=\"/cf52c47a56fc5794c1a6c2d9a81880f2/cra-pwa.webp\" alt=\"cra-pwa.webp\"></p>\n<p><img src=\"/9fc192e314ec7664132ffb4c76563789/pwa-folder-structure.webp\" alt=\"pwa-folder-structure.webp\"></p>\n<p>Here, you can see the following folder structure of your application so far. There are a few files that you shall pay attention to when it comes to PWA's:</p>\n<ul>\n<li><strong><code>service-worker.js</code></strong>: This is a script that runs in the background once your application starts running. The service worker makes sure that you can use your React application offline and handle multiple requests for the UI. (<a href=\"https://developers.google.com/web/fundamentals/primers/service-workers?hl=en\">learn more here</a>)</li>\n<li><strong><code>manifest.json</code></strong>: This is basically a configuration file that lists different properties that you can customize specifically for progressive web applications. It can determine such things as icons, names, and colors to use when the application is displayed.</li>\n<li><strong><code>serviceWorkerRegistration.js</code></strong>: This file does the job of telling whether or not your service worker was successfully registered. If you look into the file, you'll notice multiple console logs that will be displayed depending on the status of the service worker once you deploy your application.</li>\n</ul>\n<h2 id=\"adding-a-simple-react-component\" style=\"position:relative;\"><a href=\"#adding-a-simple-react-component\" aria-label=\"adding a simple react 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>Adding a Simple React Component</h2>\n<p>For your project, you'll build a simple Counter component, similar (if not exactly the same) to the example provided in the React docs: <a href=\"https://reactjs.org/docs/hooks-state.html\">Hooks State</a></p>\n<p>Let's start by creating a Counter component. Here, it is named as <code>Counter.jsx</code> and placed in a <code>components</code> folder.</p>\n<p>To speed things up, you can copy and paste the following code in your specific files. Here, it is built out as a simple page and some generic stylings for the component.</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=\"mtk3\">//Counter.jsx</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> </span><span class=\"mtk12\">React</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\">Button</span><span class=\"mtk1\"> </span><span class=\"mtk15\">from</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;@mui/material/Button&#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\">Counter</span><span class=\"mtk1\">(</span><span class=\"mtk12\">props</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\">count</span><span class=\"mtk1\">, </span><span class=\"mtk12\">setCount</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">useState</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=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">increment</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk1\"> + </span><span class=\"mtk7\">1</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\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">decrement</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">setCount</span><span class=\"mtk1\">(</span><span class=\"mtk12\">count</span><span class=\"mtk1\"> - </span><span class=\"mtk7\">1</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\">div</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\">textAlign:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;center&#39;</span><span class=\"mtk1\">}</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\">h3</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">Counter App</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">h3</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=\"mtk10\">Button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">variant</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;contained&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">increment</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">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\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\"> </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\">span</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                </span><span class=\"mtk17\">&lt;</span><span class=\"mtk10\">Button</span><span class=\"mtk1\"> </span><span class=\"mtk12\">variant</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;contained&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">onClick</span><span class=\"mtk1\">=</span><span class=\"mtk4\">{</span><span class=\"mtk12\">decrement</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">-</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk10\">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 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\">Counter</span><span class=\"mtk1\">;</span></span></code></pre>\n<p><strong>Note:</strong> Here, Material UI's Button component is used. You don't need to and can substitute the Button component with:</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=\"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\">increment</span><span class=\"mtk4\">}</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">+</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">button</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>To use Material UI, run the following npm commands:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm install </span><span class=\"mtk12\">@mui</span><span class=\"mtk1\">/material</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">npm install </span><span class=\"mtk12\">@emotion</span><span class=\"mtk1\">/react </span><span class=\"mtk12\">@emotion</span><span class=\"mtk1\">/styled //these are additional dependencies </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> me to get Material UI working with the Counter component</span></span></code></pre>\n<h2 id=\"running-your-application\" style=\"position:relative;\"><a href=\"#running-your-application\" aria-label=\"running your application 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>Running Your Application</h2>\n<p>In your command prompt, entering 'npm start' can spin up your application to a specific <code>http://localhost</code> url. You can start to see what work you've done so far.</p>\n<p>With these simple components, let's try to spin this application up and ensure it is working. </p>\n<p>Enter the command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm start</span></span></code></pre>\n<p>This starts the application at a set <code>http://localhost</code> URL. Once the dev server is working and live on the command prompt, go to the URL to view the application. You should see something similar to this:</p>\n<p><img src=\"/6536c4c2d5cdd39bdf2c5d77940e0339/counter-base-app.webp\" alt=\"counter-base-app.webp\"></p>\n<p>Now, it's all good and ready to have the app live and working, but more interested in the PWA aspect.</p>\n<h2 id=\"running-your-progressive-web-application\" style=\"position:relative;\"><a href=\"#running-your-progressive-web-application\" aria-label=\"running your progressive web application 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>Running Your Progressive Web Application</h2>\n<p>Focus back on the <code>index.js</code> file. Make the following change:</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=\"mtk3\">// If you want your app to work offline and load faster, you can change</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// unregister() to register() below. Note this comes with some pitfalls.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Learn more about service workers: https://cra.link/PWA</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">serviceWorkerRegistration</span><span class=\"mtk1\">.</span><span class=\"mtk11\">register</span><span class=\"mtk1\">(); </span><span class=\"mtk3\">//change the service worker registration from &#39;unregistered&#39; to &#39;registered&#39;</span></span></code></pre>\n<p>Essentially, changing the service worker from unregistered to registered will allow you to utilize the app even when it's offline, a key benefit when it comes to PWAs. Check Google's explanation on this topic for more information: <a href=\"https://web.dev/articles/service-workers-registration\">Service Worker Registration</a></p>\n<p>With the PWA files setup, in order to view the difference, you can deploy your application to a static server using the <code>serve</code> package that will serve your application to localhost. In a nutshell, make sure you have the <code>serve</code> package by installing, building the application again, and using <code>serve</code> to deploy the application:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"powershell\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">npm install serve</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">npm run build</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">serve -s build //</span><span class=\"mtk15\">if</span><span class=\"mtk1\"> you encounter an error with this command, </span><span class=\"mtk15\">try</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;npx serve -s build&#39;</span></span></code></pre>\n<p>Once you use the <code>serve</code> command, you should see the following message, having your application deployed to <code>http://localhost:5000</code>. It automatically adds the URL to your clipboard as well for quick pasting in your browser.</p>\n<p><img src=\"/ac55130955a81cf0de6e9bb45a2410a4/pwa-serve.webp\" alt=\"pwa-serve.webp\"></p>\n<p>If you enter the <code>http://localhost</code> URL in your browser, you should see something similar to this:</p>\n<p><img src=\"/e420d6471b18535a23c6ca226349848b/pwa-service-worker.webp\" alt=\"pwa-service-worker.webp\"></p>\n<h2 id=\"pwa-features\" style=\"position:relative;\"><a href=\"#pwa-features\" aria-label=\"pwa features 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>PWA Features</h2>\n<p>With the PWA React application live, let's take a look under the hood and open up the Developer Tools (for Google Chrome, entering F12 opens the Dev Tools).</p>\n<p>After registering your service worker from <code>index.js</code>, you should be able to see it running in the Application tab. Inside that tab, on the left side you should see a Service Workers section. From here, you can see for <code>http://localhost:5000</code>. You have a Service Worker from your <code>service-worker.js</code> file and is activated/running.</p>\n<p>In the section above, you can see <code>Manifest</code> -- opening that should show you the relevant details you listed from your <code>manifest.json</code> files.</p>\n<p><img src=\"/49c0bfe07e2e6f91a095967eb4a63f1b/pwa-manifest.webp\" alt=\"pwa-manifest.webp\"></p>\n<p>With your PWA app running using React, you've successfully built your first PWA React application! From here, you can test many PWA features, such as installation, offline viewing, and Lighthouse audit testing.</p>\n<p><img src=\"/f8aca8e7ef5a80d7a4bf4cc60d853537/pwa-install.webp\" alt=\"pwa-install.webp\"></p>\n<p>If you hit the '+' symbol on the right side of the URL ba,r you can install your PWA, just as done here.</p>\n<p><img src=\"/0f89a25aa088ec175aaa4a561ed74a56/pwa-lighthouse.webp\" alt=\"pwa-lighthouse.webp\"></p>\n<p>Use Workbox Lighthouse for testing the capabilities of your PWA: <a href=\"https://developer.chrome.com/docs/lighthouse/overview/\">Lighthouse</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>You've learned about what PWAs are and how to build a PWA with React.</p>\n<p>If you want to quickly add user registration and authentication to your React PWA, you can <a href=\"https://www.loginradius.com/blog/engineering/user-authentication-react-application/\">use LoginRadius</a>. It eliminates the burden of building and maintaining user authentication from scratch and helps you focus entirely on building your app's core features.</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 .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\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 .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"October 22, 2021","updated_date":null,"description":"Follow this article to understand how to develop a simple React PWA. It explains the step-by-step process to help you easily follow along.","title":"How to Build a Progressive Web App (PWA) with React","tags":["React","PWA","npm"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/a95efcae02df125860df9cb572a3e517/58556/blog-image.webp","srcSet":"/static/a95efcae02df125860df9cb572a3e517/61e93/blog-image.webp 200w,\n/static/a95efcae02df125860df9cb572a3e517/1f5c5/blog-image.webp 400w,\n/static/a95efcae02df125860df9cb572a3e517/58556/blog-image.webp 800w,\n/static/a95efcae02df125860df9cb572a3e517/99238/blog-image.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Abdullah Pathan","github":"aonepathan","avatar":null}}}},{"node":{"excerpt":"Introduction Bootstrap is an open-source tool collection for creating responsive web pages and web apps. It is the combination of HTML, CSS…","fields":{"slug":"/engineering/guest-post/bootstrap4-vs-bootstrap5/"},"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>Bootstrap is an open-source tool collection for creating responsive web pages and web apps. It is the combination of HTML, CSS, and JavaScript framework that makes it easy to develop responsive, mobile-first websites. It mainly aims to resolve the cross-browser compatibility issue. Bootstrap is at the core of every website that is perfect for all screen sizes and looks perfect in every modern browser.</p>\n<h2 id=\"getting-started-with-bootstrap\" style=\"position:relative;\"><a href=\"#getting-started-with-bootstrap\" aria-label=\"getting started with bootstrap 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>Getting Started with Bootstrap</h2>\n<p>In order to start using Bootstrap in your web pages, you need to add a few CSS and JS tags in your template file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">CSS</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tag</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">rel</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;stylesheet&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">href</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">integrity</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">crossorigin</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;anonymous&quot;</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">JS</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Link</span><span class=\"mtk1\"> </span><span class=\"mtk12\">tag</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://code.jquery.com/jquery-3.2.1.slim.min.js&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">integrity</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">crossorigin</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;anonymous&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">integrity</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">crossorigin</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;anonymous&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">integrity</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">crossorigin</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;anonymous&quot;</span><span class=\"mtk17\">&gt;&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<blockquote>\n<p><strong>NOTE:</strong>  Always add the <code>jquery</code> script first, followed by the <code>popper</code> and <code>bootstrap</code> scripts. Then you can add any of your custom scripts below them.</p>\n</blockquote>\n<h2 id=\"bootstrap-versions\" style=\"position:relative;\"><a href=\"#bootstrap-versions\" aria-label=\"bootstrap versions 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>Bootstrap Versions</h2>\n<p>The developers have been working continuously to enrich the developer experience of using Bootstrap for customizing the web pages quite easily. They've released many minor and major versions. But the major releases that are the most popular are the <code>Bootstrap v4.x</code> and <code>Bootstrap v5.x</code>. Let's look at what all v4.x offered and how those things evolved in the v5.x release with additional features.</p>\n<h3 id=\"bootstrap-v4x\" style=\"position:relative;\"><a href=\"#bootstrap-v4x\" aria-label=\"bootstrap v4x 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>Bootstrap v4.x</h3>\n<p>Bootstrap 4 was launched back in January 2018, and it was a great improvement over the existing previous versions. However, the most loved features included the following.</p>\n<ul>\n<li>\n<h4 id=\"flexbox-grid\" style=\"position:relative;\"><a href=\"#flexbox-grid\" aria-label=\"flexbox grid 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><strong>Flexbox Grid</strong></h4>\n<p>Flexbox grids gave the power to web developers to align the columns with ease. Now, you could position the columns at any part of the view simply by using classes like <code>justify-content-center</code> or <code>align-items-end</code>, and so on. You can also change the direction of rows which makes the vertical layouts much easier to implement and maintains responsiveness at the same time.</p>\n</li>\n<li>\n<h4 id=\"grid-tiers\" style=\"position:relative;\"><a href=\"#grid-tiers\" aria-label=\"grid tiers 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><strong>Grid Tiers</strong></h4>\n<p>Bootstrap 3 had only four tiers, but Bootstrap 4 has provided improvements by providing new device-width to enhance the support from phablets to smaller devices. The new grid tiers specified the following device widths.</p>\n<ul>\n<li><strong>sm</strong>: 576px and up</li>\n<li><strong>md</strong>: 768px and up</li>\n<li><strong>lg</strong>: 992px and up</li>\n<li><strong>xl</strong>: 1200px and up</li>\n</ul>\n</li>\n<li>\n<h4 id=\"syntactically-awesome-style-sheets-sass\" style=\"position:relative;\"><a href=\"#syntactically-awesome-style-sheets-sass\" aria-label=\"syntactically awesome style sheets sass 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><strong>Syntactically Awesome Style Sheets (Sass)</strong></h4>\n<p>Bootstrap 4 added the support for Sass, which is a widely-used and very popular CSS preprocessor. A Sass style sheet offers better control and customization and enables defining how you exactly want to use Bootstrap.</p>\n</li>\n<li>\n<h4 id=\"cards\" style=\"position:relative;\"><a href=\"#cards\" aria-label=\"cards 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><strong>Cards</strong></h4>\n<p>You no longer need to design multiple elements and combine them to provide a card view to the users. With the introduction of Cards component, you can directly use this component and further customize it using newly available bootstrap classes to redefine the look and feel of card structures, like profile cards or information tiles. Card component also doesn't have a fixed width and dissolves into the container it is placed into.</p>\n</li>\n<li>\n<h4 id=\"spacing-utilities\" style=\"position:relative;\"><a href=\"#spacing-utilities\" aria-label=\"spacing utilities 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><strong>Spacing Utilities</strong></h4>\n<p>Spacing utilities make your life easier by providing ready-made utility margin and padding classes that you can simply apply to each visual component. The margin classes are like <code>mt-2</code> or <code>mx-2</code>, and the padding classes are like <code>pt-2</code> or <code>px-2</code>, where <strong>m</strong> stands for margin, <strong>p</strong> stands for padding, the <strong>t</strong> for top or <strong>x</strong> for both left and right side, and the number says the amount you need.</p>\n</li>\n</ul>\n<h3 id=\"bootstrap-v5x\" style=\"position:relative;\"><a href=\"#bootstrap-v5x\" aria-label=\"bootstrap v5x 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>Bootstrap v5.x</h3>\n<p>   Bootstrap 5 came into play back in May 2021. This release was launched after several iterations of alpha and beta releases and hence had a stack of major additions and new features. Some of the most talked about features are listed below.</p>\n<ul>\n<li>\n<h4 id=\"enhanced-grid-system\" style=\"position:relative;\"><a href=\"#enhanced-grid-system\" aria-label=\"enhanced grid system 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><strong>Enhanced Grid System</strong></h4>\n</li>\n<li>\n<h4 id=\"enhanced-form-elements\" style=\"position:relative;\"><a href=\"#enhanced-form-elements\" aria-label=\"enhanced form elements 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><strong>Enhanced Form elements</strong></h4>\n</li>\n<li>\n<h4 id=\"utilities-api\" style=\"position:relative;\"><a href=\"#utilities-api\" aria-label=\"utilities 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><strong>Utilities API</strong></h4>\n</li>\n<li>\n<h4 id=\"support-for-ie\" style=\"position:relative;\"><a href=\"#support-for-ie\" aria-label=\"support for ie 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><strong>Support for IE</strong></h4>\n</li>\n<li>\n<h4 id=\"extended-colors\" style=\"position:relative;\"><a href=\"#extended-colors\" aria-label=\"extended colors 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><strong>Extended Colors</strong></h4>\n</li>\n<li>\n<h4 id=\"bootstrap-icons\" style=\"position:relative;\"><a href=\"#bootstrap-icons\" aria-label=\"bootstrap icons 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><strong>Bootstrap Icons</strong></h4>\n</li>\n</ul>\n<p>   Let's dive into its features by comparing how things changed in Bootstrap 5 and understanding what better design perspectives it offers for developers.</p>\n<h2 id=\"bootstrap-5-vs-bootstrap-4\" style=\"position:relative;\"><a href=\"#bootstrap-5-vs-bootstrap-4\" aria-label=\"bootstrap 5 vs bootstrap 4 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>Bootstrap 5 vs. Bootstrap 4</h2>\n<p>The above section talked about the features of both Bootstrap 4 and Bootstrap 5. This section talks about the upgrades that Bootstrap 5 provides over Bootstrap 4.</p>\n<h3 id=\"enhanced-grid-system-1\" style=\"position:relative;\"><a href=\"#enhanced-grid-system-1\" aria-label=\"enhanced grid system 1 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>Enhanced Grid System</h3>\n<p>The grid system is retained in Bootstrap 5. However, an extra grid tier <code>xxl</code> has been introduced to minimize the effort in making the pages responsive on higher resolution displays.</p>\n<p>Columns don't have a default <code>relative</code> position in Bootstrap 5.</p>\n<p>Classes have been added to address <code>vertical spacing</code>.</p>\n<h3 id=\"enhanced-form-elements-1\" style=\"position:relative;\"><a href=\"#enhanced-form-elements-1\" aria-label=\"enhanced form elements 1 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>Enhanced Form Elements</h3>\n<p>The form elements in Bootstrap 4 have defaulted to the browser-provided view. However, in Bootstrap 5, the form elements have a custom design that enables them to have a consistent look and feel in all browsers.</p>\n<p>The new form controls are based on completely semantic, standard form controls. This helps developers to avoid adding extra markups for form controls.</p>\n<h3 id=\"utilities-api-1\" style=\"position:relative;\"><a href=\"#utilities-api-1\" aria-label=\"utilities api 1 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>Utilities API</h3>\n<p>Unlike Bootstrap 4, Bootstrap 5 enables the developers to modify and create their own utilities.</p>\n<p>You can simply use <code>sass</code> to create your own utilities.</p>\n<p>You can use the <code>state</code> option to generate dummy class variations like <code>hover</code> and <code>focus</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">$utilities: (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;opacity&quot;</span><span class=\"mtk1\">: (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">property</span><span class=\"mtk1\">: </span><span class=\"mtk12\">opacity</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">class</span><span class=\"mtk1\">: </span><span class=\"mtk12\">opacity</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">state</span><span class=\"mtk1\">: </span><span class=\"mtk12\">hover</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">values</span><span class=\"mtk1\">: (</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk7\">0</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=\"mtk7\">25</span><span class=\"mtk1\">: </span><span class=\"mtk7\">.25</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk7\">50</span><span class=\"mtk1\">: </span><span class=\"mtk7\">.5</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk7\">75</span><span class=\"mtk1\">: </span><span class=\"mtk7\">.75</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk7\">100</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1</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></code></pre>\n<h3 id=\"support-for-ie-1\" style=\"position:relative;\"><a href=\"#support-for-ie-1\" aria-label=\"support for ie 1 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>Support for IE</h3>\n<p>Bootstrap 5 no longer supports Internet Explorer 10 and 11 like its predecessor, Bootstrap 4.</p>\n<h3 id=\"extended-colors-1\" style=\"position:relative;\"><a href=\"#extended-colors-1\" aria-label=\"extended colors 1 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>Extended Colors</h3>\n<p>Bootstrap 4 had limited color options. But Bootstrap 5 has included many new color options to its color palette, enabling you to choose from the various shades available. You can find some of the color shades below.</p>\n<p><img src=\"/816dccdb459358a5d14357ec4f72234d/colors.webp\" alt=\"Bootstrap 5 Color\"></p>\n<h3 id=\"bootstrap-icons-1\" style=\"position:relative;\"><a href=\"#bootstrap-icons-1\" aria-label=\"bootstrap icons 1 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>Bootstrap Icons</h3>\n<p>Bootstrap 4 didn't have an SVG icon library. You had to use other third-Party libraries like <code>Font Awesome</code> to use icons in your applications. But Bootstrap 5 has taken care of this issue by introducing its own SVG library with 1000+ icons.</p>\n<p>It also includes a web font version in the stable version release of the icon library.</p>\n<p><img src=\"/03fd84a90515e2b339b5919c4dd52e07/BootStrapIcons.webp\" alt=\"Bootstrap 5 Icons\"></p>\n<h3 id=\"site-generation-strategy\" style=\"position:relative;\"><a href=\"#site-generation-strategy\" aria-label=\"site generation strategy 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>Site Generation Strategy</h3>\n<p>Bootstrap 5 has moved to Hugo for its static site generation over Jekyll. Hugo is a fast static site generator implemented in Go and is quite popular. You can learn more about <a href=\"https://gohugo.io/\">Hugo here</a>.</p>\n<h3 id=\"popperjs-update\" style=\"position:relative;\"><a href=\"#popperjs-update\" aria-label=\"popperjs update 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>Popper.js Update</h3>\n<p>Bootstrap 5 update brings in an update for Popper.js as well, <code>Popper.js v2</code>. Popper.js generally helps to design the tooltips and popovers. With v2, the following changes come in:</p>\n<ul>\n<li><code>fallbackPlacement</code> option becomes <code>fallbackPlacements</code></li>\n<li><code>offset</code> option is no longer available. However, you can use the <code>popperConfig</code> parameter to achieve this.</li>\n</ul>\n<h3 id=\"placeholder-components\" style=\"position:relative;\"><a href=\"#placeholder-components\" aria-label=\"placeholder 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>Placeholder Components</h3>\n<p>Bootstrap 5 allows loading placeholders in your pages. This means that you can utilize the space of the components by showing placeholders in their place while they're still loading the actual content.</p>\n<p><img src=\"/c5721b448635aeda1d7d2f2697b098a3/placeholders.webp\" alt=\"Placeholder Components\"></p>\n<h3 id=\"floating-labels\" style=\"position:relative;\"><a href=\"#floating-labels\" aria-label=\"floating labels 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>Floating Labels</h3>\n<p>Bootstrap 5 adds support for floating labels in forms for the input fields. You can simply use the <code>form-floating</code> class to enable a floating label. When you enter some value into the input fields, they automatically adjust their position to their floated area.</p>\n<p><img src=\"/d937339a8b17213105a7403c828e1153/flabels.webp\" alt=\"Floating Labels\"></p>\n<h3 id=\"rtl-support\" style=\"position:relative;\"><a href=\"#rtl-support\" aria-label=\"rtl support 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>RTL Support</h3>\n<p>Bootstrap 5 has added support for RTL (Right-to-Left), which means you can develop content that needs writing from the right side of the page and continues to the left. As a result, websites in languages like Arabic, Sindhi, and Urdu can easily be developed.</p>\n<p><img src=\"/f18b789d3f73dd8d46a078af0c124adf/rtl.webp\" alt=\"RTL Dashboard Example\"></p>\n<h3 id=\"jquery-deprecation\" style=\"position:relative;\"><a href=\"#jquery-deprecation\" aria-label=\"jquery deprecation 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>jQuery Deprecation</h3>\n<p>Bootstrap used jQuery from the very beginning as a dependency to offer dynamic features. With Bootstrap 5, jQuery is dropped, and Vanilla JS is introduced as its replacement.</p>\n<blockquote>\n<p><strong>NOTE:</strong>  There are still JS dependencies that depend on Popper and Vanilla JS modules. However, jQuery is optional and can be added based on the requirement of the project.</p>\n</blockquote>\n<h3 id=\"other-significant-changes\" style=\"position:relative;\"><a href=\"#other-significant-changes\" aria-label=\"other significant changes 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>Other Significant Changes</h3>\n<ul>\n<li>Bootstrap 5 introduces a new data attribute naming structure. <code>data-*</code> attribute has been renamed to <code>data-bs-*</code>.</li>\n<li>Bootstrap 5 now provides easier customizations on the v4 theming pages and provides code snippets to build using Bootstrap's Sass files.</li>\n<li>Bootstrap 5 has added a new <code>accordion</code> component that includes icons that have a state and can be clicked. The <code>accordion-flush</code> class can be used to remove the default background color, borders, or corners to possibly render accordions edge-to-edge with the parent element.</li>\n<li>Bootstrap 5 documentation site is now enhanced to improve the user readability, and new examples have been added with code snippets.</li>\n<li>The <code>inline-block</code> property is removed in Bootstrap 5, and the <code>dropdown-menu-dark</code> class now loads with a default black dropdown.</li>\n<li>The support for <code>jumbotron</code> has been terminated in Bootstrap 5.</li>\n<li>With vertical classes in Bootstrap 5, the columns can be positioned <code>relative</code>.</li>\n<li>Gutters can now be applied using <code>g*</code> class instead of <code>gutter</code>. The font size is now set to <code>rem</code> instead of <code>px</code>.</li>\n<li>Lastly, Bootstrap 5 also adds a new <code>offcanvas</code> component that enables you to create hidden view panes that would pop out when you interact with component tied to it -- e.g., side navigation bars, shopping carts, etc. Here is an example of the bottom <code>offcanvas</code> component.</li>\n</ul>\n<p><img src=\"/b98b75cc8a7a55ccbfe8d7639bb664b3/offcanvas.webp\" alt=\"Offcanvas Bottom Bar\"></p>\n<h2 id=\"summary\" style=\"position:relative;\"><a href=\"#summary\" aria-label=\"summary 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>Summary</h2>\n<p>Bootstrap 4 used to do a great job providing all the flexibility and responsiveness for designing the web pages. However, Bootstrap 5 adds several new aspects that help to reduce the effort to do the same. But still, you need to keep certain parameters in mind before choosing either of these two.</p>\n<p>If you have an existing project that needs to support IE 10 and 11 or depends on jQuery, you should probably stick to Bootstrap 4. Bootstrap 5 can be overwhelming but might break your project structure if not migrated properly.</p>\n<p>But if you're starting a new project and want to provide a more immersive UI for the users, definitely opt for Bootstrap 5 to use its modern components, which this article discussed above.</p>\n<p>This is all for this blog post at the moment. I hope you had a great time reading this and learned something new. Do let me know in the comments if you liked the content.</p>\n<blockquote>\n<p><strong>NOTE:</strong>  All the images used in this blog post are taken from the official <a href=\"https://getbootstrap.com/\">Bootstrap</a> website and are used here for reference purposes only.</p>\n</blockquote>\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 .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"October 21, 2021","updated_date":null,"description":"This article discusses the differences between Bootstrap 4 and Bootstrap 5 and helps you understand which version you should use for your projects.","title":"Bootstrap 4 vs. Bootstrap 5: What is the Difference?","tags":["Bootstrap","Frontend","Sass"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/b8214436ee2553d77f17b33b5fdb3112/58556/coverImage.webp","srcSet":"/static/b8214436ee2553d77f17b33b5fdb3112/61e93/coverImage.webp 200w,\n/static/b8214436ee2553d77f17b33b5fdb3112/1f5c5/coverImage.webp 400w,\n/static/b8214436ee2553d77f17b33b5fdb3112/58556/coverImage.webp 800w,\n/static/b8214436ee2553d77f17b33b5fdb3112/99238/coverImage.webp 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Rutam Prita Mishra","github":"Rutam21","avatar":null}}}}]},"markdownRemark":{"excerpt":"Introduction Ever wondered how apps like Spotify, Netflix, or Slack manage seamless login experiences across devices? Many of them use JWT…","fields":{"slug":"/engineering/how-to-integrate-jwt/"},"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>Ever wondered how apps like Spotify, Netflix, or Slack manage seamless login experiences across devices? Many of them use JWT, or JSON Web Tokens, a compact, stateless method for securely transmitting user identity and session data across services.</p>\n<p>With JWT token authentication, identity information is embedded in a signed token, allowing you to maintain user sessions without server-side storage. This approach is highly scalable and ideal for modern architectures like SPAs, mobile apps, and microservices.</p>\n<p>In this blog, we’ll walk you through what is JWT, why use it, and how to implement JWT authentication using LoginRadius. </p>\n<p>You’ll learn what JWT is, why it’s effective, and how it works in real-world applications. We'll cover both integration methods (IDX and Direct API), generating your signing key, managing sessions, storing the JWT token securely, and applying best practices throughout.</p>\n<p>Whether you're a developer, product manager, or IAM architect, this guide offers a complete foundation for implementing JWT token authentication into your application stack.</p>\n<h2 id=\"what-is-jwt\" style=\"position:relative;\"><a href=\"#what-is-jwt\" aria-label=\"what is jwt 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 JWT?</h2>\n<p><a href=\"https://www.loginradius.com/blog/engineering/jwt/\">JSON Web Token (JWT)</a> is an open standard (RFC 7519) used to transmit information securely between parties as a JSON object. It’s compact, self-contained, and digitally signed, making it a reliable format for authentication and authorization across modern applications.</p>\n<p>A JWT consists of three parts:</p>\n<ol>\n<li><strong>Header –</strong> Contains metadata like the type of token and signing algorithm (e.g., HS256).</li>\n<li><strong>Payload –</strong> Stores the actual data or “claims,” such as user ID, roles, and token expiry.</li>\n<li><strong>Signature –</strong> A cryptographic hash that ensures the token hasn’t been tampered with.</li>\n</ol>\n<p><em>Example of a token structure:</em></p>\n<p>&#x3C;base64Header>.&#x3C;base64Payload>.&#x3C;signature></p>\n<h2 id=\"why-use-jwt\" style=\"position:relative;\"><a href=\"#why-use-jwt\" aria-label=\"why use jwt 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 Use JWT?</h2>\n<ul>\n<li><strong>Stateless Authentication</strong>: No server-side session storage is needed — the token holds all necessary user info. </li>\n<li><strong>Portable</strong>: Works seamlessly across domains, services, and APIs. </li>\n<li><strong>Scalable</strong>: Ideal for microservices, SPAs, mobile apps, and serverless functions. </li>\n<li><strong>Interoperable</strong>: JWTs are supported across many languages and frameworks.</li>\n</ul>\n<h2 id=\"how-jwt-works\" style=\"position:relative;\"><a href=\"#how-jwt-works\" aria-label=\"how jwt works 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 JWT Works?</h2>\n<p><img src=\"/f29edbf2978577390c7ffa02e9bc4dda/lr-JWT-authentication.webp\" alt=\"Flowchart illustrating LoginRadius JWT authentication via Identity Provider (IDP), showing user redirection from login icon to login page, authentication with IDP, JWT token validation, and subsequent redirection to the customer&#x27;s website or error page based on validation results.\"></p>\n<ol>\n<li>A user logs in with credentials. </li>\n<li>Your app (or identity provider like LoginRadius) issues a signed JWT. </li>\n<li>The client stores the token and sends it with each request (usually in the Authorization header). </li>\n<li>The server validates the token’s signature and claims. </li>\n<li>If valid, access is granted — without any session stored on the backend.</li>\n</ol>\n<p>JWT simplifies identity verification, especially when you're building apps that talk to APIs or need to scale without centralized session storage.</p>\n<h2 id=\"jwt-authentication-with-loginradius-overview\" style=\"position:relative;\"><a href=\"#jwt-authentication-with-loginradius-overview\" aria-label=\"jwt authentication with loginradius overview 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>JWT Authentication with LoginRadius: Overview</h2>\n<p>LoginRadius provides robust support for JWT (JSON Web Token) authentication, which allows for flexible and secure access control across different digital platforms. Whether you're building a fully custom identity flow or using a pre-built interface, the platform supports various integration approaches depending on your architecture.</p>\n<p>If you're looking to understand how to implement JWT token authentication effectively, LoginRadius offers two primary implementation models that cater to different levels of customization and control:</p>\n<h3 id=\"1-idx-implementation--jwt-through-a-hosted-login-page\" style=\"position:relative;\"><a href=\"#1-idx-implementation--jwt-through-a-hosted-login-page\" aria-label=\"1 idx implementation  jwt through a hosted 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>1. IDX Implementation – JWT through a Hosted Login Page</h3>\n<p>The IDX-hosted login approach enables secure, standards-compliant, JWT-based authentication without requiring you to build a custom login interface. This is a strategic option for fast, compliant, and user-friendly deployments.</p>\n<ul>\n<li>The Identity Experience Framework (IDX) comes with a fully custom branded hosted login page.</li>\n<li>Once the user logs in and gets enrolled, the user’s JWTs are automatically generated and issued. These tokens can be utilized for managing user sessions and accessing the APIs.</li>\n<li>This approach simplifies deployment without compromising on user experience and security standards.</li>\n</ul>\n<h3 id=\"configuration-steps\" style=\"position:relative;\"><a href=\"#configuration-steps\" aria-label=\"configuration steps 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><strong>Configuration Steps:</strong></h3>\n<ol>\n<li>Enable JWT Login</li>\n<li>Go to <a href=\"https://console.loginradius.com/authentication/authentication-configuration\">authentication configuration settings</a> and enable JWT Login in the Admin Console.</li>\n</ol>\n<p><img src=\"/9fb19dd9c88c7916aeebd03ab6e661b7/lr-admin-console.webp\" alt=\"Screenshot of LoginRadius Admin Console showing JWT Custom IDP configuration interface with options for provider name, algorithm (HS256), key entry, clock skew, and expiration time settings.\"></p>\n<ol start=\"2\">\n<li>Specify your signing algorithm and expiry policy, and define your JWT Secret Key.</li>\n<li>Input a secure JWT signing key.</li>\n<li>Specify token expiry duration (e.g., 15–60 minutes)</li>\n<li>Select the desired algorithm —HS256 for symmetric signing (same key signs and verifies)</li>\n<li>RS256 for asymmetric signing, where LoginRadius securely stores the private key used to sign the JWT.</li>\n<li>Your app or backend service uses the public key to validate the token signature.</li>\n<li>LoginRadius provides a JWKS (JSON Web Key Set) endpoint to dynamically fetch and rotate public keys, ensuring trust without key exposure.</li>\n<li>Update IDX Template for Callback</li>\n<li>Modify your IDX login page template to retrieve the JWT post-login. You can access the token via redirect URL parameters or secure JavaScript callbacks.</li>\n</ol>\n<h3 id=\"example-response\" style=\"position:relative;\"><a href=\"#example-response\" aria-label=\"example response 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>Example Response:</h3>\n<p>{</p>\n<p>  \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR...\",</p>\n<p>  \"expires_in\": 1800</p>\n<p>}</p>\n<p>This integration approach works best for all teams that want effective identity workflows without the complexity of building proprietary login screens, something that is crucial for customer portals, onboarding of mobile applications, and even managing access for business partners.</p>\n<h3 id=\"2-direct-api-implementation--self-managed-login\" style=\"position:relative;\"><a href=\"#2-direct-api-implementation--self-managed-login\" aria-label=\"2 direct api implementation  self managed login 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. Direct API Implementation – Self Managed Login</h3>\n<p>If you’re building a custom login UI or working in a headless environment, LoginRadius lets you generate and handle JWTs directly through its <a href=\"https://www.loginradius.com/docs/api/v2/customer-identity-api/\">Authentication APIs</a>. Here’s how you can programmatically perform token authentication using the classic method:</p>\n<ul>\n<li>For custom front-end applications, LR offers an API to authenticate users and issue JWT tokens.</li>\n<li>In response to the login request, the developers are provided with signed tokens that can be validated on the client’s side or by downstream services.</li>\n<li>This method is best fit for enterprise applications that have complex custom workflows or are designed to be embedded into other applications.</li>\n</ul>\n<h3 id=\"configuration-steps-1\" style=\"position:relative;\"><a href=\"#configuration-steps-1\" aria-label=\"configuration steps 1 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><strong>Configuration Steps:</strong></h3>\n<h4 id=\"step-1-authenticate-via-api\" style=\"position:relative;\"><a href=\"#step-1-authenticate-via-api\" aria-label=\"step 1 authenticate via 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>Step 1: Authenticate via API:</h4>\n<ul>\n<li>\n<p>Send a POST login request to the LR Authentication URL: </p>\n<p>POST /identity/v2/auth/login</p>\n</li>\n</ul>\n<p>Include the user’s credentials (email + password) in the request body.</p>\n<h4 id=\"step-2-get-jwt-in-response\" style=\"position:relative;\"><a href=\"#step-2-get-jwt-in-response\" aria-label=\"step 2 get jwt in response 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: Get JWT in Response</h4>\n<ul>\n<li>If the user credentials are authentic, then the JWT token will be available in response.</li>\n</ul>\n<p>{</p>\n<p> \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",</p>\n<p> \"expires_in\": 3600</p>\n<p>}</p>\n<h4 id=\"step-3-jwt-decoding-and-validation\" style=\"position:relative;\"><a href=\"#step-3-jwt-decoding-and-validation\" aria-label=\"step 3 jwt decoding and validation 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: JWT Decoding and Validation</h4>\n<ul>\n<li>Use any JWT library (e.g., jsonwebtoken for Node.js or pyjwt for Python) to decode the token.</li>\n<li>Validate the signature using your configured secret key.</li>\n<li>Confirm claims like exp, iat, aud, and iss.</li>\n</ul>\n<h4 id=\"step-4-set-custom-claims-optional\" style=\"position:relative;\"><a href=\"#step-4-set-custom-claims-optional\" aria-label=\"step 4 set custom claims optional 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: Set Custom Claims (Optional)</h4>\n<p>With LoginRadius, it is possible to customize the payload to include user roles and/or any additional metadata. You can set custom JWT claims on the Admin Console.</p>\n<p>With this method, you have complete customization over login flows while using LoginRadius to issue signed JWTs for user session management.</p>\n<p><strong>NOTE-</strong> With either method, LoginRadius ensures that JWTs are securely signed, optionally short-lived, and compatible with standard token validation libraries, making integration seamless for everyone.</p>\n<p>To get started with JWT implementation, you can<a href=\"https://www.loginradius.com/docs/single-sign-on/federated-sso/jwt-login/jwt-implementation-guide/\"> read our complete developer documentation</a>. </p>\n<h2 id=\"hosted-login-vs-direct-api\" style=\"position:relative;\"><a href=\"#hosted-login-vs-direct-api\" aria-label=\"hosted login vs direct 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>Hosted Login vs Direct API</h2>\n<p><img src=\"/15ec02ac98d24a9f1f28e5d0f06b9174/IDX-vs-Direct-API-JWT.webp\" alt=\"Illustration showing IDX vs Direct API JWT flow diagram comparing LoginRadius JWT authentication methods via Hosted Login Page (IDX) and Custom Login UI using Direct API, illustrating user login, JWT issuance, and token return process.\"></p>\n<h2 id=\"what-is-session-management-and-how-it-works-with-jwt\" style=\"position:relative;\"><a href=\"#what-is-session-management-and-how-it-works-with-jwt\" aria-label=\"what is session management and how it works with jwt 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 Session Management and How It Works with JWT</h2>\n<p><a href=\"https://www.loginradius.com/blog/identity/user-session-management/\">Session management </a>is how your app keeps track of a user after they log in so they don’t have to prove who they are with every request.</p>\n<p>In traditional apps, sessions are stored on the server using session IDs. Every time a request comes in, the server checks that session ID to verify the user.</p>\n<p>In modern apps, especially SPAs and APIs, JWTs are used to manage sessions without needing server-side storage; this is called stateless session management. The token itself carries the user’s identity, roles, and expiration details. As long as the token is valid, the user stays logged in.</p>\n<p>Good session management ensures:</p>\n<ul>\n<li>Security against session hijacking</li>\n<li>Fast user validation without hitting a database</li>\n<li>Smooth experiences with token refresh strategies</li>\n</ul>\n<h2 id=\"how-loginradius-handles-session-management-with-jwt\" style=\"position:relative;\"><a href=\"#how-loginradius-handles-session-management-with-jwt\" aria-label=\"how loginradius handles session management with jwt 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 Handles Session Management with JWT:</h2>\n<ol>\n<li>\n<p>User Logs In </p>\n<ul>\n<li>LoginRadius returns an access token (JWT) and, optionally, a refresh token.</li>\n</ul>\n</li>\n<li>\n<p>Client Stores the Token </p>\n<ul>\n<li>Access tokens are stored in memory, sessionStorage, or secure cookies. </li>\n<li>They’re sent on every request via the Authorization: Bearer header. </li>\n</ul>\n</li>\n<li>\n<p>Access Token Expiry </p>\n<ul>\n<li>These tokens are short-lived by design (e.g., 15–30 minutes). </li>\n<li>Once expired, the client can use the refresh token to request a new access token. </li>\n</ul>\n</li>\n<li>\n<p>Token Renewal </p>\n<ul>\n<li>LoginRadius validates the refresh token and issues a new JWT, i.e., no user re-authentication is needed. </li>\n<li>Refresh tokens can be revoked at any time.</li>\n</ul>\n</li>\n<li>Logout and Token Revocation Strategy</li>\n</ol>\n<p>When the user logs out, both the access token and refresh token should be cleared from client storage.</p>\n<ul>\n<li>The refresh token can be explicitly revoked via the LoginRadius API, terminating the ability to renew sessions. </li>\n<li>\n<p>However, access tokens are stateless and cannot be revoked mid-lifecycle unless: </p>\n<ul>\n<li>You maintain a blacklist of token IDs (jti claims) and check them on each request. </li>\n<li>You use short-lived access tokens to limit exposure naturally. </li>\n<li>Or, you rotate your JWT signing key, invalidating all previously issued tokens. </li>\n</ul>\n</li>\n</ul>\n<p>Combining these strategies gives you greater control over token misuse and enables a robust, enterprise-grade logout flow. </p>\n<p><a href=\"https://www.loginradius.com/resource/whitepaper/secure-api-using-oauth2\"><img src=\"/e55ae4bbc8ce62e13f03e46e29ebe7cc/api-economy.webp\" alt=\"illustration showing LoginRadius free downloadable resource named API economy is transforming digitization: how to secure it using oauth 2.0.\"></a></p>\n<h2 id=\"how-to-store-jwt-tokens\" style=\"position:relative;\"><a href=\"#how-to-store-jwt-tokens\" aria-label=\"how to store jwt tokens 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 to Store JWT Tokens?</h2>\n<p>When you implement JWT-based authentication, the client (browser or mobile app) needs a way to store the access token and, optionally, the refresh token after they are issued by the authentication server. This stored token is then attached to every subsequent request to prove the user's identity.</p>\n<p>Choosing where to store the JWT is a crucial security decision. The most common storage options are:</p>\n<ul>\n<li>localStorage</li>\n<li>sessionStorage</li>\n<li>HTTP-only cookies</li>\n</ul>\n<p>Each option has trade-offs between security, accessibility, and persistence, and the right choice depends on your application's architecture and threat model.</p>\n<h4 id=\"recommended-storage-strategy\" style=\"position:relative;\"><a href=\"#recommended-storage-strategy\" aria-label=\"recommended storage strategy 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>Recommended Storage Strategy</h4>\n<ul>\n<li>\n<p>Access Tokens </p>\n<ul>\n<li>For SPAs: store in memory or sessionStorage for short-term access </li>\n<li>If stored in the browser, protect against XSS </li>\n</ul>\n</li>\n<li>\n<p>Refresh Tokens</p>\n<ul>\n<li>Always store the JWT refresh token in HTTP-only secure cookies to prevent JavaScript access. This adds a critical layer of protection against XSS attacks.</li>\n<li>Combine with SameSite=Strict or SameSite=Lax attributes to mitigate CSRF risks and ensure the JWT refresh token is only sent in intended contexts.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"best-practices-for-storing-jwts\" style=\"position:relative;\"><a href=\"#best-practices-for-storing-jwts\" aria-label=\"best practices for storing jwts 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>Best Practices for Storing JWTs</h2>\n<ol>\n<li>Never store sensitive tokens (like refresh tokens) in localStorage or sessionStorage.</li>\n<li>Use Secure and HttpOnly flags with cookies to prevent JavaScript access and ensure transmission only over HTTPS.</li>\n<li>Set the SameSite=Strict or Lax attribute on cookies to protect against CSRF.</li>\n<li>Use short-lived access tokens and rotate refresh tokens regularly.</li>\n<li>Implement CSP (Content Security Policy) to reduce XSS risk.</li>\n<li>Avoid storing any tokens in frontend code (e.g., hardcoded in JS files).</li>\n</ol>\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>JWT authentication with LoginRadius offers a modern, stateless approach to managing sessions across distributed systems. The IDX integration is ideal for rapid deployment, while the Direct API model is best for organizations needing deep customization and integration flexibility.</p>\n<p>With robust token signing, refresh capabilities, and centralized control, LoginRadius provides a future-ready foundation for secure, scalable identity architecture. <a href=\"https://www.loginradius.com/contact-us?utm_source=blog&#x26;utm_medium=web&#x26;utm_campaign=how-to-integrate-jwt\">Contact us</a> to know more about JWT authentication and implementation guide. </p>\n<h2 id=\"faqs\" style=\"position:relative;\"><a href=\"#faqs\" aria-label=\"faqs 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>FAQs</h2>\n<h3 id=\"1-what-is-jwt-authentication-used-for\" style=\"position:relative;\"><a href=\"#1-what-is-jwt-authentication-used-for\" aria-label=\"1 what is jwt authentication used for 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. What is JWT authentication used for?</h3>\n<p><strong>A:</strong> JWT authentication securely verifies user identities, enabling stateless session management across web, mobile apps, and microservices without server-side session storage.</p>\n<h3 id=\"2-how-does-loginradius-simplify-jwt-integration\" style=\"position:relative;\"><a href=\"#2-how-does-loginradius-simplify-jwt-integration\" aria-label=\"2 how does loginradius simplify jwt 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>2. How does LoginRadius simplify JWT integration?</h3>\n<p><strong>A:</strong> LoginRadius simplifies JWT integration by offering hosted <a href=\"https://www.loginradius.com/docs/single-sign-on/federated-sso/jwt-login/jwt-implementation-guide/\">IDX login pages </a>and direct API-based authentication methods, enabling rapid deployment and deep customization.</p>\n<h3 id=\"3-is-jwt-authentication-secure\" style=\"position:relative;\"><a href=\"#3-is-jwt-authentication-secure\" aria-label=\"3 is jwt authentication secure 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. Is JWT authentication secure?</h3>\n<p><strong>A:</strong> Yes, JWT authentication is secure when implemented with best practices like short-lived tokens, secure storage methods, signature validation, and refresh token rotation.</p>\n<h3 id=\"4-can-jwt-tokens-be-revoked-with-loginradius\" style=\"position:relative;\"><a href=\"#4-can-jwt-tokens-be-revoked-with-loginradius\" aria-label=\"4 can jwt tokens be revoked 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>4. Can JWT tokens be revoked with LoginRadius?</h3>\n<p><strong>A:</strong> Yes, LoginRadius allows<a href=\"https://www.loginradius.com/docs/api/v2/customer-identity-api/refresh-token/revoke-refresh-token/?q=revoke+jwt\"> revocation of JWT</a> refresh tokens explicitly, and supports strategies like short-lived tokens and key rotation to manage token lifecycles securely.</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":"April 15, 2025","updated_date":null,"description":"Discover JWT (JSON Web Token) authentication, its advantages, and how to integrate it seamlessly using LoginRadius' hosted IDX and Direct API methods for secure, scalable identity management.","title":"JWT Authentication with LoginRadius: Quick Integration Guide","tags":["JWT","JSON Web Token","Authentication","Authorization"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":0.7782101167315175,"src":"/static/4cedb7829f98208cbc6d5a9aea4e983d/58556/how-to-integrate-jwt.webp","srcSet":"/static/4cedb7829f98208cbc6d5a9aea4e983d/61e93/how-to-integrate-jwt.webp 200w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/1f5c5/how-to-integrate-jwt.webp 400w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/58556/how-to-integrate-jwt.webp 800w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/1cc9f/how-to-integrate-jwt.webp 896w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},"pageContext":{"limit":6,"skip":36,"currentPage":7,"type":"//engineering//","numPages":53,"pinned":"5c425581-f474-5ae9-abe7-cf5342db2aaa"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}