{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/7","result":{"data":{"allMarkdownRemark":{"edges":[{"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/05fa72d6fb6ace5ecff9919a78a8ff56/ee604/Best-Practices.png","srcSet":"/static/05fa72d6fb6ace5ecff9919a78a8ff56/69585/Best-Practices.png 200w,\n/static/05fa72d6fb6ace5ecff9919a78a8ff56/497c6/Best-Practices.png 400w,\n/static/05fa72d6fb6ace5ecff9919a78a8ff56/ee604/Best-Practices.png 800w,\n/static/05fa72d6fb6ace5ecff9919a78a8ff56/f3583/Best-Practices.png 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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 592px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 60.641891891891895%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABdUlEQVQoz6VSa0/CQBA8jICU8hI1ooDiBxEQebWUUh4VWkAQG///jxl3r2AaUgyJH+Z2+7i5udkRKd1G0V6jMF7i0dnizv7A7WSFwnQlnxmX5hxJbYJIow9R1yG4HkOsPUTWcpGxHKSNd6jaVG5WCVxT+hQqIUPfTiIUNQ2Jvo300JEbc4OZ3Mx95NWAeO5AVLt+3ZP9RcpLkklGLhRW1ZtA6Y0lWGGiO5Iq2Zqz5uAEhfSDQgpTRMqb9yRK1yeNty2q/vVDCQ+ffcKpJEzufOPriheN0PNR3VWyR4JJanq4BbwkDFteO07KWBEj1hr6oKHFOxaiLRPnbyYuOiNEqfL7cIV08g1FprL0cE/xYRTfN6i4XyjNNtSv8bTwZM9R4r48/8TDfCuHJxUHCfnEa4pNzpjJCedp2lcUoeyulwqCKgJ9aIxEQ4dKBPnxQsbkEEenWT8SH/ZJJek8FPbo13SJYH8iMqaDsuORh98ouR5E0/wXfgDK9lnyHdvUOwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"cra-pwa.png\"\n        title=\"cra-pwa.png\"\n        src=\"/static/56f2c5d2b65cd178c1206a0e8d63a829/1b853/cra-pwa.png\"\n        srcset=\"/static/56f2c5d2b65cd178c1206a0e8d63a829/1b853/cra-pwa.png 592w\"\n        sizes=\"(max-width: 592px) 100vw, 592px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 388px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 110.30927835051547%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACFklEQVQ4y6WUX2/SYBjF3xYKtIU6Bkjihc6NiMg/LdACZdIV1rXMkQhzMNmM+i1k3hgT7zSZH2n3Gv1Exwc6Q8ySxZaLk7dp2l/OeXqesuyDe0h1isioj5DNpJDNppFObyKVTt6uVBIZejaXz2Ent42th/eRp2vGphcQX3+EMpsj/vYTlPefwZ1egE3mYNO5d96mkw+eJtcSvv+E9PUK7MsVuMvfYJe/wL79CC4xX8BdTYXUHULuDhAua2BbebCdAth2AEUqbShqH5IzgezOILQdsFIzuKJlA8n6EJJ9Aql3DLH/ElylBfakAVbU/CtSaWKz1YN8MCXgCLL9ak1gtUm12YPszKAcvkHEcMm6FhwYLumQ2wcI6/sIqaZ3s1D3ziBQjoDR9gCx50OE6+YKEtQhX2ogYZhIvHgHoWGBPVbXA4aKNaQ1g2Z4BtEcIVQzV5GDiKPuxDSbgNTD/jH4qkHu1pghX25Aae0ugVFjQJFrHijoLMOlFjI6rZ0zhWhdl7qo//uQH2iIHCaNhcNTxN0zJNxzKvcU/LPdldu/0P8B86U6NggY2xsj1j3yNsaiWT7tgKN5cuWmX4d1ctgh4GgJk/cXOz1e7rVkjRGh0vsC8kXqYcskGEW2JwRwPcCiOgv5jSyQQ6njej2kf+Ii6o0X/TgUVR13rEPEB+eI04cR9N7NYvuKXO0QxKaoDu2y5X3ZNVbvD+uGhwaPXliAAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-folder-structure.png\"\n        title=\"pwa-folder-structure.png\"\n        src=\"/static/33577ffd80429d8835275ec6105f302a/96c67/pwa-folder-structure.png\"\n        srcset=\"/static/33577ffd80429d8835275ec6105f302a/96c67/pwa-folder-structure.png 388w\"\n        sizes=\"(max-width: 388px) 100vw, 388px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 11.384615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAATElEQVQI12OYOXvu/9lz5/2fPGXa/96+Cf/7+lFxf//E/w0tnWDcP2EihnwfUM+ECZP+z5o95/+MGTP/M/wnApx+9OP/+Sc/iVH6HwAEuITcBlSqFgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"counter-base-app.png\"\n        title=\"counter-base-app.png\"\n        src=\"/static/088d475708c50e6be837f5ddf9ee3534/e5715/counter-base-app.png\"\n        srcset=\"/static/088d475708c50e6be837f5ddf9ee3534/a6d36/counter-base-app.png 650w,\n/static/088d475708c50e6be837f5ddf9ee3534/e5715/counter-base-app.png 768w,\n/static/088d475708c50e6be837f5ddf9ee3534/7ebf9/counter-base-app.png 1919w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 359px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.038997214484674%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABtUlEQVQoz51S207bQBBdk0ICSri0qFBA4iYuSZ0Qr2MbX5JgyEUgEmgq2vKAkPj/fzicWTsqEby0D8dzPDsze2Zn1EZ7gI32EPv9MQ4Gd9jrjbCT3mDr4gbbAxubacz/ERZ1gorXxfH1BOVWF6ragvruv8fCWYRiM0aZwSUnwZLbxpJuY5G85GoUnYDnCebsAIX6uTkTq2rex1A13uTHUA6DmsQZoUMoN6JNaOOMt2hbUXYm3ItzX86DJFOobD9z6ghW2IEVs51GMNuGnYPcotJ3XJR5ScbNh8UUi6n0EmrYNyqtmiTkBU/dDPJuUy440cYnsUaU/UZhgc5vSR+7F9cMZuKxzhKYuB738Dm8wmqQkvex2Rlijf97vTFW6FNHDqwZha4MJkL4+IT0+QXV2wn0zz8GX6IrHHL6tdsHY+3RLzR/POJweI/6+De8hyd85SVmBvIEU4UWW1tgUYGsyLLfRYWQLSg0zs0mCJ/GfGqEmOO0S4ydb4TZwN4qnK+HqHC/ikySlZEgsbImUkgKCC+7HZRY3AzCvGmOmTf08/7rwf9BWp3WMDfp6O9O/Svc3DqhUf0KNFRAHuaCVJ0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-serve.png\"\n        title=\"pwa-serve.png\"\n        src=\"/static/c9a8359e93f7d5a8f4ddea4944617655/f5eb6/pwa-serve.png\"\n        srcset=\"/static/c9a8359e93f7d5a8f4ddea4944617655/f5eb6/pwa-serve.png 359w\"\n        sizes=\"(max-width: 359px) 100vw, 359px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>If you enter the <code>http://localhost</code> URL in your browser, you should see something similar to this:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 40.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEElEQVQoz5XQ7U6DMBQG4F6Djm2ok+8CAxmZsjjjvQDTaKAgC2HTZHeoN+FN+Pu1K9PM+AeaPOnpaXpOW1I3r9hs3pDlBeJkhSR9+CPl4jgV0vTx337Cz7DiBdW6xjNjIOgwPj6/8M51GaTe7sCqBnWzxZp3yTImFGWFnJXI+c1XT6193ObKdj7E2SHPigpEn93hRPVxNtEwUQzI5wpOB2Nu9EuSxsJx7thgKGMoX0IaXYAsogWoZUPVDAThNW6iJSzqwjApZ0M3aC8kmM1hWi4UzYR/FSKcR7yQIzapPeWNTCiq0Rm5Xd5j6gV8oYsCvufBs3VRSNMtMfdB9rcyLQe2G8D1Zvy5Dv8C2vupP74BqkMz+jHTrhwAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-service-worker.png\"\n        title=\"pwa-service-worker.png\"\n        src=\"/static/90d0aef82baba4315cab1a1b8ce921e5/e5715/pwa-service-worker.png\"\n        srcset=\"/static/90d0aef82baba4315cab1a1b8ce921e5/a6d36/pwa-service-worker.png 650w,\n/static/90d0aef82baba4315cab1a1b8ce921e5/e5715/pwa-service-worker.png 768w,\n/static/90d0aef82baba4315cab1a1b8ce921e5/29114/pwa-service-worker.png 1920w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 54.61538461538461%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaklEQVQoz5WSvU7CUBiGewmCQEWkpS30FwopAamocfACpI2TYJwcHIyLJkYKRQaNUfSq0MEJd+EedH/tKWhioIIneXKSc773yXd+qEp1GwWjhHKlipq1j72aPYVt2bAse+YegeQah0eo1xugBoM39PvPGA5HCBov7x94HX1ikUH1Hp9w/9DDze0d3E4XTquNq6aDtnsN1+2i1e7g9LyJswsHLW/PCaDptPw8lc7IiNFxhMJRrCZYrCVTCEdohJfpnzkWpRH1IDVBLIUiWIknQJXKJohUlFSomo6cbkDR8pCV7C8kWYOQlmZC8hyf8bIFUHreAC+I/gIJkZlhebApYYoUlw6EZFQtB8rc2PJFvCD5XfJ/hBYSkg7TogLZk2aLJvTNXb9gXkeBQv84RJBkIZs7KB4cg2W4sXQingepTTIT4XeQ3KPoPQYvqmBZ7t9dkg4lWR0LfciCsQ7z5BKiUQHjfZ//HlmUFHwBERWGuHTl+YgAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-manifest.png\"\n        title=\"pwa-manifest.png\"\n        src=\"/static/72e264704e37dc7bb2a9dec4ad37ca4c/e5715/pwa-manifest.png\"\n        srcset=\"/static/72e264704e37dc7bb2a9dec4ad37ca4c/a6d36/pwa-manifest.png 650w,\n/static/72e264704e37dc7bb2a9dec4ad37ca4c/e5715/pwa-manifest.png 768w,\n/static/72e264704e37dc7bb2a9dec4ad37ca4c/29114/pwa-manifest.png 1920w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 39.07692307692307%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaElEQVQoz52MzUoCURiG5zq00XF0nD+jH3KcH0VoZbRQZ7KNURYE0S6XrYJWte8euo2kK4iypSuLWgQ6ajTj+HY8ipHhpg8e3u+8D99hjk9OsV87Qqns/KFIsG0HFcemWSw5KNsVFLa2IUoqkqIMSVZRsndwUDvEbrUKxvd9/DCc7R4BCNB6c3F738LrxwCj4bgDHh6fwIsqJGUFIZbHXaNBe8/zwGDBjEaT/PQCvLs+vvxgVrbbLzir13F5fYPziys8N5u0D4bB4g//O0y/38c8nW4HvV6P7AOaLqE3xXVdSrfbnSR9j93kltGNHHQji4xuQSOYZg6b+QI2NAtjp2VMSlozYRCXzeVhZfP0RssYM5/RJ55h2QhYNgouGkM0yiEel2FZe4hwIuk40vHUh8MsBEGix4mkTHwcoTDpl37DKEIcajKBtZSM1ZRCUJFSU9NdwbKiQCZeFnjIEunW04jxArhYguY833RDrR15xU/mAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-install.png\"\n        title=\"pwa-install.png\"\n        src=\"/static/3cb9b63c38ee39150c91b5e790a9997b/e5715/pwa-install.png\"\n        srcset=\"/static/3cb9b63c38ee39150c91b5e790a9997b/a6d36/pwa-install.png 650w,\n/static/3cb9b63c38ee39150c91b5e790a9997b/e5715/pwa-install.png 768w,\n/static/3cb9b63c38ee39150c91b5e790a9997b/29114/pwa-install.png 1920w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>If you hit the '+' symbol on the right side of the URL ba,r you can install your PWA, just as done here.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 20.153846153846153%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAvklEQVQY022OS47CMBBEc40Rwk63HZO0fwOJCAo7dswh5v63KGyDsmLx1FJVdak68QmVSWIhNMbpfVNe4ZyHSMlIhjvJzuAmhPgLHzKkUP+r1iltcPygetvoyeJHGTwf/wjhjoPSu6f6d+5wJKSUsd42jKWsjlCa0Rk2kKHCOPsTluRxiYIlRyzXP8yXDXMcMRc9ed+y3jEcE2LMuK4b2LhWVod0RAa19Cuky6WC/Wh295gYdhjbOuIBuiyvhS8jyHS+MbNuyQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"pwa-lighthouse.png\"\n        title=\"pwa-lighthouse.png\"\n        src=\"/static/0540c7c3e60a931d7c2083aad390cb53/e5715/pwa-lighthouse.png\"\n        srcset=\"/static/0540c7c3e60a931d7c2083aad390cb53/a6d36/pwa-lighthouse.png 650w,\n/static/0540c7c3e60a931d7c2083aad390cb53/e5715/pwa-lighthouse.png 768w,\n/static/0540c7c3e60a931d7c2083aad390cb53/dd507/pwa-lighthouse.png 1528w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>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/c7e3ca9131877e6d122821800050a259/ee604/blog-image.png","srcSet":"/static/c7e3ca9131877e6d122821800050a259/69585/blog-image.png 200w,\n/static/c7e3ca9131877e6d122821800050a259/497c6/blog-image.png 400w,\n/static/c7e3ca9131877e6d122821800050a259/ee604/blog-image.png 800w,\n/static/c7e3ca9131877e6d122821800050a259/f3583/blog-image.png 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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 668px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 91.53846153846155%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAE+0lEQVQ4yx2SeVTNeRjGf8YwtrFvWYtzsoVQmqKUbBNCCHWKEim7TqbtJoPQHGslc7UbRWWIEBKthKQsdZVtSNxO2+1271Xd+5mf/vic5/v95znv8z6vEFegY/kZLSujtCyJ0OIo1bEsSkdWmY5Lu9VEOKsId2zhpIOK06tVxHtrKH/UxLmgF8Tue8UZ31KkgS+J2FPK/dRPCD6pWgb5tNNnRzuCi5ZeW1vovbOV6CwdoabN7BmnwL27gjVCPRv7yQkwUpOb9g3fxbkELCvA3fguW2bdwWt2FgkHyxEuPtHhEgtbk3RsTBCJVYnaRr5MR7pEwzkPNbGeP1RJlFs9lyWtVD5TkHionAtHKjgfKiP+YBnRwWU8vFmDIG9so6SygdK3jVRUa/hQB5XfoFkDX6qUVBTXUlVWz8fXzcjfQe1HLWplG+8qvvFeJudtRQ1fPymRf1KjqP+O8KpaS2qRivRnaq4/b+fmCx3XSnV8Eo3LszUUpil4nK6k+LqakoxWXt9vp75Gw9P71RT/4MEXygpqeZ5Ty+fKZoSCylbCrtcRnllPVLaamAKIytHypgYeJim4cuwrN8Ll3I5q5L60jaJLbXx938KtpHIyk2Wivibnyn88SPvMm5IGhIzSdnb804J/qhL/tO8EXdWx97KWYjHe7eNKEn0bSA5o4GKggkv+Gm4ea+WDGD/l9CvSIspJCX/J1bOVpJ6qpOSBHCG5qJ2V4QrcopW4xbXikfijJC0FMkj1a+IvxxrCXeViIY1I3VSi6XexlCakwcVEh5R0kBj6mmjJSwozviBEZrdiLKnD5nAd1mEq5p3QMStM3GWJliQvNSccNESsUXNyhYoDlkrOumh4mV/PIY9cjmzOJ3RTDse3P+Ww2xPuXPiIcPhWO3o+KibvUzNBPInxwVpGB7RzuUhLpH0Leyc1IzFpJnB6M7vHKDg6X82zrDoCV+UiccwneE0eIU4P8bXLE6O/RQgUd9Zrhw79AB0D9ujosU1Lpy1aEnJ0HLVQ4qWnYNdoBVtFdf25CX8jFY8yajsM/JYW4m9fiM+CPNynZZEUJkPwT5bT1VnGMK8q+rq/odd6GT85VZBwrwGJuQyngWW4D3+B6+AyHLo+Y+cUGXnXPuJhlYzn3JQOPKwusmpiHDGhjxACEqvo5pDNKPd8+q3NofvKBwj294jPrMbXogCHQbdxGpWF49C7LOh8g81G+WRfleFsEYmr1Vk2WP+Nk3kkC8eEEfVnljih9DFdbWMYvvICfe3i6Sa+BSspcdcq8DJPZV5/KUuGxbBo8DnMOp1i3aQkbl8uYck0CctNQ1hhtp/FxkGY6W3nWFAawt7TdxCmBzNg7hF6zDrIL+YHOv5xV4pxMYnEtKcEywH7Me+9j8nCHyyfcJKMlEJmG27CZpIXcyZswWqcJxP7rSXUL16c8Hga3ad6YmDrS19Tb7oYbUIw3EBMSg7rLA5gOsgbq9G7mDnYGwPBiYXj/bh6KRvzcWuwNHLG2tgVk7GrGNF9DsE+pxH2hEQi9DXjV0M7Oo+wQRhiidBnJtLEa9hOWc8gwQKDnvMY2c2GnsJ0TA1Wc/F8OsP7GKM/0JSxQ35jVP8ZdBFGsts7WLzDE9GMnW6Hqe06xpvZo2+8CL0Jc0lOu4mz/TYsJi/HesZqzI2WYTjEisVzNpD+byazTX7H2nxpB2bG89EfOpWQoKP8D0eAxqU+ueIrAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Bootstrap 5 Color\"\n        title=\"Bootstrap 5 Color\"\n        src=\"/static/4b5ffdd71eeb7f85b97b02e4af17a88b/74866/colors.png\"\n        srcset=\"/static/4b5ffdd71eeb7f85b97b02e4af17a88b/a6d36/colors.png 650w,\n/static/4b5ffdd71eeb7f85b97b02e4af17a88b/74866/colors.png 668w\"\n        sizes=\"(max-width: 668px) 100vw, 668px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 101.38461538461539%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACU0lEQVQ4y22Ui27bMAxF+///MwwFhmF/0i7rmofzcuKnJJvjoR6xlxpQU0rkFXl5qRfRr+t6aZpGpmnClHmeV2u5x+e9l2EcZWQ5p3GPsxf+VNVRPrfbFeDyW4LxjaOTtusskWEYLe4BaM6iNzqp65s4HySEyW6ujifpNSBoAPutAnT9YDZZjc6XtcrQK8DxdJb3zR8L9LoI/Pb9VU7nSwH8+NxKpX4+BIs5na+y+fhrgLk6A8RwLvJCdtzu4Emz4xcbkHWGk2XPHpetMsQgaFo0ggBAQuLHbLLXvewXM40+GaeUfK3v2pi9ZYoTt+8PlWWUgbBPl6v5Y9/ujfH8VDIBTdspjxc7zIAH7X4GpKyzgtUKYjwraH27m88KcE5dhqt4kLUWIoe6ZzzPs3UeDVpM8mFvqVnLMCyaYhzRFLX7YSjCpVnYvWY8paagR2xiVk0hu7uWfL7UpkdupuTtbq9U9KXk3f6gewcDBwQK3n5vvuAwxPLgC/AobC+tXsIF2C7xjEyss2Ss/vemtZgn2azHTIos8hkZcCllLvcAW2IUDpHAbl9ZeYGMNdBm1TIMJcOljKCFDFejl/95e9/Ij5+/ZEodJxCNAYhNky7X2qTiEqfwji7xeR49grwvZdJxQO01ofz0ZNHpkKaDDFlROrLm0KWA/BThBBh72JGGsTxXxukYAbNWH6Pn4xixbFKSbCiR3yhgb+exq6E8Z1AwjF/IBsKvergcPQAMkKYYYKuAXXniAMTHOPxfNqZDe4pi+pSMzqzkxLNNiq48ZlZy0m7G+Qdq9yAITD76cgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Bootstrap 5 Icons\"\n        title=\"Bootstrap 5 Icons\"\n        src=\"/static/c0c3f76afb2d4b85a44266a248169923/e5715/BootStrapIcons.png\"\n        srcset=\"/static/c0c3f76afb2d4b85a44266a248169923/a6d36/BootStrapIcons.png 650w,\n/static/c0c3f76afb2d4b85a44266a248169923/e5715/BootStrapIcons.png 768w,\n/static/c0c3f76afb2d4b85a44266a248169923/715a3/BootStrapIcons.png 830w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 684px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 64.3076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACdUlEQVQ4y42TX0/TUBjGd2/iDTeaEIxo4qXRr6AXRm+993toUANMCI4NGdvUREg0qCwRZsgMTmMiAmMESUAGJDDW0Xa2pdvcn45t7TmP57RsgDfY5Nfzvm+ePDnP6amLEAqtbkA+KCFbKzNKxyhDYvM/Zg1Vo4pCsYRiifXFI5p9xTBAKYXLJBbuJqdwZeklri2P4uoxrv8cQ+diCAPZJcQ+fYPbF4QvOApv4FUL3vf7QghHouCPq8EMb66+Q9vCM3QsBtG+GGhxgfVnf3jxSJzHdGQG992DcA8G0OsZacH7LrcXbyamjgxvrU3gXNyPS4nnuJgItbjM+rb5IXRLC4h+jKGrz2fv5ok32IL3j/uHMB6O/GO44Efnfxj2nWpoWbjBI8eH0bEUwvn4CMNv0x4P4MysBw/FOUxPnYzc89SP7oFh9LD6Qa8Hr99POoaEfZnvOQEf5CQiUhIzuV18KQiIFdL2Gs2lsFnVIUtZrKytYy25idVfG9jY2sZ2SrDZ2k5hT5IdQ/4ixgHysgJdUoC6BVh8CGeltg6m2YCqqtA0DcpvBZVKxZ5TQtB8CKttwzK7QxITydo+0qIEgSFlsxBlGaqu22KD3cPddAaCsAchIyEt8DqDnZ0Ucrm8fQdtQx7ZalRhGvuoVXSQah7Vch6qpqNhmraIb7JRYyk0EQVNQlGXoWRFKIqKer3u7LRpyLPFkgS3/QT3xgjusHU8QeysFuFCOwwyOYKBzxRDXyncUYK5HecsaJMjQ4pVkTIxwYtZAk+sKeaGTESdWi1RhJcpJlco3iYo1mVnzn9dbtbEZZrW4emfpMHmpnUIqyk5RcOwWKS/vVd0z59Fc+AAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Placeholder Components\"\n        title=\"Placeholder Components\"\n        src=\"/static/2368a2aec32e17c9c21c107e4d039e5c/2c288/placeholders.png\"\n        srcset=\"/static/2368a2aec32e17c9c21c107e4d039e5c/a6d36/placeholders.png 650w,\n/static/2368a2aec32e17c9c21c107e4d039e5c/2c288/placeholders.png 684w\"\n        sizes=\"(max-width: 684px) 100vw, 684px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 683px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 17.846153846153847%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAh0lEQVQY03WPiQoDIQxE/f8flSpdD5BlNTp1PJZ2oYEhRt+EUWFVa1RDrVT9FR8fNdlvbnqVcw7Oe5zniVIKROaCDdCYc4YPATFGeB+QUhrsvagz9EmfldYaL2NgrR2Lad4J2kp2XRmmM+/jGBw7WRG5E/NMqf1FDuWPBrzSsA/1RKU8mH73AQbwOizFJPITAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Floating Labels\"\n        title=\"Floating Labels\"\n        src=\"/static/b8c7c0c42fcfdb4ad477e37aea1b7ac7/bca35/flabels.png\"\n        srcset=\"/static/b8c7c0c42fcfdb4ad477e37aea1b7ac7/a6d36/flabels.png 650w,\n/static/b8c7c0c42fcfdb4ad477e37aea1b7ac7/bca35/flabels.png 683w\"\n        sizes=\"(max-width: 683px) 100vw, 683px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 685px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 53.84615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABe0lEQVQoz31Ti27bMAz0///fgDVInaJJsSaurYfllyzyJop2l2VDBBC+MLwjxbMrYyysdWi+Whhr4ZxHZ0x5LsuCdV0RY/wrJDfPMy6XD7wcDjifz6jrOvMdqnGaMIwjwjBgHKcS8lueRAw5zJwDWyhORPi83nB8rdF1BqfTG3wfUIUQwPnP/TDjDvMmSls84n9P5b0v11ByLmQqIoITKbEbCW8dw4yMW09oAhV8/GK0IZUGKaWiUfV9j5h3IkeE/MTanXUaPyvRZoEmMC6W8eGkSc7l2rrVeuEWwX1CSZ5awo8r4ZxJUyR0A+G13Sb/75UJ74bgJsW0T8gp4pSvdAta3OepDg3h502JzHp9IaRtFWW3OT8uVLh3gh7HJmYxTa5p6866z323Eo84bZO/m7yqWXlVaz1+ufV7D7RNopi/RfR1ecCsjYfIxbQi6JzFGudCFqfkpS0OP8ESO1ZDKRuXivOVGLIssbgsJPk6nmGt/4PVUGCJazYy4TcZL1z6AQAilgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"RTL Dashboard Example\"\n        title=\"RTL Dashboard Example\"\n        src=\"/static/6a4ae736793c0804d6c89471e9c8680a/8ce22/rtl.png\"\n        srcset=\"/static/6a4ae736793c0804d6c89471e9c8680a/a6d36/rtl.png 650w,\n/static/6a4ae736793c0804d6c89471e9c8680a/8ce22/rtl.png 685w\"\n        sizes=\"(max-width: 685px) 100vw, 685px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h3 id=\"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><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 53.84615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABGUlEQVQoz62PzY6DMAyE88os+cMJEIrEay5curet4FwxaweBop5Wai19MmPisa26rkOMEZJTSnDOoW1bxEyXv09KLd+lDrFjeigRRIS+7y/DwANcQ0wA+QaBIe+zbpyH53+2iTCOQPxe3tQuwlMLJZtdhsOQDWU7y83SELQBGUbr3GhJGnkQE6lBbDxCCHDh2FqJ8DxdNhVzw82yobYOlXawXxq+qmBqA82mljF1DWvtMZRxcoFcxl5qHMd86jRNGSkOtxsCT6O2R8c55WHHBSkNGNKR+wLxkD41LwvmecH3PON+/8G2bVjXFWvOG+s16+2sFWwXa86/jwfU8/nEyb7veDfUa0FM30G9FkrT/0bZp0rxiVD4cPwBdrPN7/GxZZsAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Offcanvas Bottom Bar\"\n        title=\"Offcanvas Bottom Bar\"\n        src=\"/static/2b27ba639040368aec3106810ada8a19/e5715/offcanvas.png\"\n        srcset=\"/static/2b27ba639040368aec3106810ada8a19/a6d36/offcanvas.png 650w,\n/static/2b27ba639040368aec3106810ada8a19/e5715/offcanvas.png 768w,\n/static/2b27ba639040368aec3106810ada8a19/906b5/offcanvas.png 950w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"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/8f7ef876ee3ee88f8ddb1becc34c70fa/ee604/coverImage.png","srcSet":"/static/8f7ef876ee3ee88f8ddb1becc34c70fa/69585/coverImage.png 200w,\n/static/8f7ef876ee3ee88f8ddb1becc34c70fa/497c6/coverImage.png 400w,\n/static/8f7ef876ee3ee88f8ddb1becc34c70fa/ee604/coverImage.png 800w,\n/static/8f7ef876ee3ee88f8ddb1becc34c70fa/f3583/coverImage.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Rutam Prita Mishra","github":"Rutam21","avatar":null}}}},{"node":{"excerpt":"One of the most used authentication standards in web applications is the JSON Web Token standard. It is mostly used for authentication…","fields":{"slug":"/engineering/guest-post/jwt-authentication-best-practices-and-when-to-use/"},"html":"<p>One of the most used authentication standards in web applications is the JSON Web Token standard. It is mostly used for authentication, authorization, and information exchange.</p>\n<p>JSON Web tokens are made of three parts separated by dots <code>(.)</code> — and look like this typically: <code>xxxxx.yyyyy.zzzzz</code>. These correspond to the Header, the Payload, and the Signature. You can learn more about <a href=\"https://www.loginradius.com/blog/engineering/jwt/\">JWT tokens here</a>.</p>\n<p>And before using them and continuing to read this article, you might want to check the advantages compared to the session authentication method. You can learn more about <a href=\"https://www.loginradius.com/blog/engineering/guest-post/jwt-vs-sessions/\">JWTs vs. Sessions here</a>.</p>\n<h2 id=\"when-to-use-jwt-authentication\" style=\"position:relative;\"><a href=\"#when-to-use-jwt-authentication\" aria-label=\"when to use jwt authentication 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>When to Use JWT Authentication?</h2>\n<h3 id=\"authentication\" style=\"position:relative;\"><a href=\"#authentication\" aria-label=\"authentication 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>Authentication</h3>\n<p>Authentication is done when a client successfully proves its identity via a login endpoint. If it's successful, the server will create JSON Web Token and send it in response to the client.</p>\n<p>The client will use this JWT on every request for a protected resource. </p>\n<h3 id=\"authorization\" style=\"position:relative;\"><a href=\"#authorization\" aria-label=\"authorization 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>Authorization</h3>\n<p>A server built on JWT for authorization will create a JWT when a client logs in. This JWT is signed, so any other party can’t alter it.</p>\n<p>Each time the client has access to protected resources, the server will verify that the JWT’s signature matches its payload and header to determine that the JWT is valid.</p>\n<p>Then if the JWT is successfully verified, it can grant or deny access to the resource. </p>\n<h3 id=\"data-exchanges\" style=\"position:relative;\"><a href=\"#data-exchanges\" aria-label=\"data exchanges permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Data Exchanges</h3>\n<p>JWT is also a great way to secure information transmission between parties — two servers, for example — and because you can verify the validity of the token (signature, structure, or the standards claimed in the JWT). </p>\n<h2 id=\"when-not-to-use-jwt-authentication\" style=\"position:relative;\"><a href=\"#when-not-to-use-jwt-authentication\" aria-label=\"when not to use jwt authentication 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>When Not to Use JWT Authentication?</h2>\n<h3 id=\"revocable-tokens\" style=\"position:relative;\"><a href=\"#revocable-tokens\" aria-label=\"revocable 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>Revocable Tokens</h3>\n<p>JWT doesn’t require any lookup of the database, so revoking them before the expiration is quite difficult. </p>\n<p>Revocation is very important in many cases.</p>\n<p>For example, when logging out users or banning users, or changing permissions or passwords instantly, if the token hasn't been revoked, it might be possible for the user to continue to make requests even if this user no longer has the required authorization to do so.</p>\n<h3 id=\"sensitive-information\" style=\"position:relative;\"><a href=\"#sensitive-information\" aria-label=\"sensitive information 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>Sensitive Information</h3>\n<p>JWT is usually signed to protect against data manipulation or alteration. With this, the data can be easily read or decoded.</p>\n<p>So, you can’t include sensitive information such as the user’s record or any identifier because the data is not encrypted.</p>\n<h3 id=\"cookie-size-factor\" style=\"position:relative;\"><a href=\"#cookie-size-factor\" aria-label=\"cookie size factor 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>Cookie Size Factor</h3>\n<p>The size of a JWT is greater than the size of a session token. And this can quickly increase linearly as you add more data to the JWT. And because you need to send the JWT at each request, you're increasing the payload size. This can become heavily complex if there is a low-speed internet connection.</p>\n<h2 id=\"jwt-best-practices\" style=\"position:relative;\"><a href=\"#jwt-best-practices\" aria-label=\"jwt 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>JWT: Best Practices</h2>\n<h3 id=\"1-jwt-as-access-token\" style=\"position:relative;\"><a href=\"#1-jwt-as-access-token\" aria-label=\"1 jwt as access 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>1) JWT as Access Token</h3>\n<p>JWT can be used as an access token to prevent unwanted access to a protected resource. They're often used as Bearer tokens, which the API will decode and validate before sending a response.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Authorization: Bearer &lt;token&gt;</span></code></pre>\n<h3 id=\"2-refresh-tokens-logic-with-jwt\" style=\"position:relative;\"><a href=\"#2-refresh-tokens-logic-with-jwt\" aria-label=\"2 refresh tokens logic 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>2) Refresh Tokens Logic with JWT</h3>\n<p>How do you get a new access token if this one is expired? The natural first idea is to log in again. But from a User Experience point, this can be quite painful.</p>\n<p>JWT can be used as <a href=\"https://www.loginradius.com/blog/engineering/guest-post/what-are-refresh-tokens-and-when-to-use-them/\">refresh tokens</a>; these tokens are used to retrieve a new access token.</p>\n<p>For example, when a client requests a protected resource and receives an error, which can mean that the access token has expired, the client can be issued a new access token by sending a request with a refresh token in the headers or the body.\nIf the refresh token is valid, a new access token will be created and sent as a response.</p>\n<p>Note that the refresh token is obtained at authentication and has a bigger lifetime.</p>\n<h3 id=\"3-which-signing-algorithm-to-use\" style=\"position:relative;\"><a href=\"#3-which-signing-algorithm-to-use\" aria-label=\"3 which signing algorithm to use 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) Which Signing Algorithm to Use?</h3>\n<p>Interestingly enough, JWT can be <a href=\"https://www.loginradius.com/blog/engineering/jwt-signing-algorithms/\">signed using many different algorithms</a>. But let’s quickly talk about the <code>alg</code> value in the JWT header. When it’s decoded:</p>\n<p>The <code>alg</code> value in JWT headers simply tells you how the JWT was signed. For example, with an <code>alg</code> value of <code>RS512</code>. </p>\n<p><code>RS512 => RS 512</code> where RS is the signature algorithm and <code>SHA-512</code> is the hashing algorithm.</p>\n<p><code>SHA-512</code> will produce a <code>512-bits</code> hash while <code>SHA-256</code> will produce a <code>256-bit</code> hash. And each of these algorithms gives you 50% of their output size of security level. This means that, for example, <code>SHA-512</code> will provide you with <code>256-bits</code> security.</p>\n<p>In any case, make sure to use a minimum of <code>128-bit</code> security.</p>\n<h3 id=\"4-expiration-issued-time-and-clock-skew\" style=\"position:relative;\"><a href=\"#4-expiration-issued-time-and-clock-skew\" aria-label=\"4 expiration issued time and clock skew 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) Expiration, Issued Time, and Clock Skew</h3>\n<p>JWTs are hard to revoke when they are created. Most of the time, you’ll have to wait until expiry. That’s why you should use a short expiration time. </p>\n<p>Additionally, you can implement your own revocation system.</p>\n<p>JWT comes with a time-based claim <code>iat</code> — issued at. It can be used to reject tokens that are too old to be used by the resource server.\nAnd clock skew specifies the allowed time difference (in seconds) between the server and the client clocks when verifying <code>exp</code> and <code>nbf</code> time-based claims. The default recommended default value is 5.</p>\n<h3 id=\"5-jwt-signature\" style=\"position:relative;\"><a href=\"#5-jwt-signature\" aria-label=\"5 jwt 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>5) JWT Signature</h3>\n<p>The last part of a JWT is the signature, which is simply a MAC (or Message Authentication Code). This signature is created by the server using a secret key. This secret key is an important part of the JWT signature.</p>\n<p>There are two things to respect to decrease the probability of a secret key leaking or a successful brute force attack:</p>\n<ul>\n<li>Keep the secret key <strong>secret</strong></li>\n<li>\n<p>The minimum key length must be equal to the size of bits of the hash function used along with the HMAC algorithm.</p>\n<blockquote>\n<p>\"A key of the same size as the hash output (for instance, 256 bits for \"HS256\") or larger MUST be used with this algorithm.\" - <a href=\"https://tools.ietf.org/html/rfc7518#section-3.2\">JSON Web Algorithms (RFC 7518), 3.2 HMAC with SHA-2 Functions</a></p>\n</blockquote>\n</li>\n</ul>\n<h3 id=\"6-where-to-store-the-tokens\" style=\"position:relative;\"><a href=\"#6-where-to-store-the-tokens\" aria-label=\"6 where to store the 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>6) Where to Store the Tokens?</h3>\n<p>The easiest ways to store a token on the client side are <code>localStorage</code> and <code>sessionStorage</code>. However, both are vulnerable to XSS attacks, and <code>sessionStorage</code> is cleaned if the browser is closed.</p>\n<p>A better, secure way is to store JWT in cookies. Cookies are not accessible via JavaScript, they can’t be read and written, and interestingly, they are automatically sent to the server.</p>\n<h3 id=\"7-always-use-https\" style=\"position:relative;\"><a href=\"#7-always-use-https\" aria-label=\"7 always use https permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>7) Always Use HTTPS</h3>\n<p>One of the main benefits of <code>HTTPS</code> is that it comes with security and trust. <code>HTTP</code> path and query parameters are encrypted when using <code>HTTPS</code>.</p>\n<p>Then, there is no risk of someone intercepting the request, particularly the token in transit. These types of attacks are commonly called <strong>MitM</strong> (man in the middle) attacks that can be successful on compromised or insecure networks.</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>This article discussed JWT and some best practices to fully use its potential.</p>\n<p>JWT is simply an authentication standard with its pros and cons. Thus, knowing some best practices can really help you use JWT better.</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 14, 2021","updated_date":null,"description":"JWT is a common way of implementing authentication in web and mobile apps. Read more to know how you can use JWT and learn the necessary best practices.","title":"JWT Authentication — Best Practices and When to Use","tags":["JWT","Authentication"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/dd60f505aa7484a17a6cd0b90a5b0fae/ee604/cover-image.png","srcSet":"/static/dd60f505aa7484a17a6cd0b90a5b0fae/69585/cover-image.png 200w,\n/static/dd60f505aa7484a17a6cd0b90a5b0fae/497c6/cover-image.png 400w,\n/static/dd60f505aa7484a17a6cd0b90a5b0fae/ee604/cover-image.png 800w,\n/static/dd60f505aa7484a17a6cd0b90a5b0fae/f3583/cover-image.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kolawole Mangabo","github":"koladev32","avatar":null}}}},{"node":{"excerpt":"Ever wondered how amazing it would be if an application knows you are trying to access it, without having to re-validate your credentials…","fields":{"slug":"/engineering/guest-post/what-are-refresh-tokens-and-when-to-use-them/"},"html":"<p>Ever wondered how amazing it would be if an application knows you are trying to access it, without having to re-validate your credentials time and again?!</p>\n<p>Let's say you try accessing the application after a day or two, or even at the end of an entire week, and somehow... magically (not really xD) the system just knows it's you.</p>\n<p>Furthermore, the Security aspect of the app being completely robust, no other individual with malicious intent can access confidential information. Now that's music to a developer's ears -- or, at least, a powerful way to secure applications and systems at scale.</p>\n<p>Before diving into the know-hows of refresh tokens, let's understand why it is even needed in the first place.</p>\n<h2 id=\"conventional-approach-of-securing-apps\" style=\"position:relative;\"><a href=\"#conventional-approach-of-securing-apps\" aria-label=\"conventional approach of securing apps 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>Conventional Approach of Securing Apps</h2>\n<p>Many applications utilize the so-called <em>token-based authentication</em> to permit a user to access information (or resources) that would normally not be available for the general public (unauthenticated users).</p>\n<p>A <a href=\"https://www.loginradius.com/blog/identity/pros-cons-token-authentication/\"><strong>token</strong></a> is an unique approval given to you (more like a digital signature) for accessing any resource. The application issues it to you once you have authenticated yourself with valid credentials. These tokens are generally short-lived, i.e., valid only for a short amount of time (say 5-15 minutes). This is plenty for you to perform a particular task requiring validation but makes it harder for individuals with malicious intent to get their hands on confidential resources. Now, until the token expires, the user would not have to enter the credentials again.</p>\n<p>This kind of system is widely used to perform online transactions where security is of utmost importance. However, due to the short-lived nature of such access tokens, the user would have to re-validate themselves to be re-issued a new access token.</p>\n<h2 id=\"refresh-tokens-to-the-rescue\" style=\"position:relative;\"><a href=\"#refresh-tokens-to-the-rescue\" aria-label=\"refresh tokens to the rescue 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>Refresh Tokens to The Rescue</h2>\n<p>We can clearly make out that access tokens overall provide better security but hampers the user experience (UX) of the application. Imagine having to log in again and again just because the application has to make sure that you're still, well... you!</p>\n<p>Here is where refresh tokens come to the rescue. A <strong>refresh token</strong> just helps you re-validate a user without them having to re-enter their login credentials multiple times. The access token is re-issued, provided the refresh token is a valid one requesting permission to access confidential resources. This method provides an enhanced user experience all while keeping a robust security interface.</p>\n<p><a href=\"https://www.loginradius.com/blog/engineering/oauth2/\"><em>OAuth 2.0</em></a> is a popular authentication framework that essentially allows client applications to access resources provided by other applications &#x26; servers on behalf of the user. This architecture leverages the benefits of utilizing access and refresh tokens.</p>\n<p>Now, having discussed the impact a refresh token has on enhancing the user experience of the application, is there any other benefit to using them?</p>\n<p>It is true that, generally, web applications and SPAs (Single-Page Applications) are meant to have short-term access to any resource leveraging authentication. When you do need access after a few days to the resources, you could definitely log in again, right? So why bother setting up refresh tokens?</p>\n<h3 id=\"when-to-use-refresh-tokens\" style=\"position:relative;\"><a href=\"#when-to-use-refresh-tokens\" aria-label=\"when to use refresh 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>When to use Refresh Tokens?</h3>\n<p>The main purpose of using a refresh token is to considerably shorten the life of an access token. The refresh token can then later be used to authenticate the user as and when required by the application without running into problems such as cookies being blocked, etc. If that does not make much sense, think of it this way:</p>\n<p>When a browser makes a request to an API endpoint to use a resource provided only to authenticated users, the application would require the credentials of the user. And upon authentication (login), the application on the user's browser is granted access to the resource. This access is provided by sharing an access token with the user's browser so that subsequent API calls from the browser -- which requires the credentials -- can be sent without any hassle.</p>\n<p>Now in the process of sharing the access token with the user, the system may also provide a refresh token that would later authenticate the user while making the subsequent API calls -- even if the access token has expired -- by requesting a new access token when required.</p>\n<p>Hence, the refresh tokens allow applications to obtain new access tokens utilizing mere API calls without any need of having users approve cookies, login multiple times, etc.</p>\n<h3 id=\"drawbacks-and-ways-to-conquer\" style=\"position:relative;\"><a href=\"#drawbacks-and-ways-to-conquer\" aria-label=\"drawbacks and ways to conquer 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>Drawbacks and Ways to Conquer</h3>\n<p>It's also true that you may not need the \"added superpowers\" offered by the refresh tokens to keep the user session and experience smooth. After all, methods such as <em>cookies</em> and <em>silent authentication</em> are beneficial in their own ways too! Let's talk about a scenario when refresh tokens might actually turn out to be an application's kryptonite... (not really xD).</p>\n<p>If a refresh token is compromised (someone else got their hands on it or, even worse -- steals it), the individual would not only gain access to the resources provided by the API but also the amount of time the access has been granted would be more. Now that's a dreadful scenario for developers and users alike.</p>\n<p>Having said that, counter-measures such as <strong><em>Refresh Token Rotation</em></strong> and <strong><em>Automatic Reuse Detection</em></strong> help limit the destructive nature -- and highlight the benefits of these refresh tokens.</p>\n<p>In such methods, when a refresh token is utilized to access any resource, the system not only responds with the access token but also with a new refresh token in turn. Any subsequent API requests can be made through newer refresh tokens from there onwards. If a request is made utilizing an older refresh token, the request is efficiently rejected (assuming the person/client requesting is unauthenticated).</p>\n<p>Also, <a href=\"https://www.loginradius.com/blog/engineering/risk-based-authentication/\"><em>Risk-Based Authentication (RBA)</em></a> method suggests that if a refresh token is utilized multiple times, the tokens are revoked; thereby, preventing further access to valuable resources. Such a mechanism further helps strengthen the security of applications using refresh tokens.</p>\n<h3 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</h3>\n<p>Refresh Tokens are really a consummate way of providing sturdy security all while providing a great experience for users, provided it being used in appropriate ways. That being said, it might not be completely essential for your applications and their needs, so the final decision rests with you.</p>\n<p>I hope this blog provided an insight into refresh tokens and how you may utilize these in your applications. Thanks for reading!</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":"October 05, 2021","updated_date":null,"description":"This is your guide to understanding refresh tokens, and why you may need to use them to enhance the user experience of your applications.","title":"What Are Refresh Tokens? When & How to Use Them","tags":["Authentication","Tokens","UX"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/395429ed9397d1de86cac90d1168da9a/ee604/coverImage.png","srcSet":"/static/395429ed9397d1de86cac90d1168da9a/69585/coverImage.png 200w,\n/static/395429ed9397d1de86cac90d1168da9a/497c6/coverImage.png 400w,\n/static/395429ed9397d1de86cac90d1168da9a/ee604/coverImage.png 800w,\n/static/395429ed9397d1de86cac90d1168da9a/f3583/coverImage.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Mcvean Soans","github":"McTechie","avatar":null}}}},{"node":{"excerpt":"You might have already participated in Hacktoberfest as a contributor. But what if you have a project that you want to open source and get…","fields":{"slug":"/engineering/hacktoberfest-participation-as-maintainer/"},"html":"<p>You might have already participated in Hacktoberfest as a contributor. But what if you have a project that you want to open source and get contributions during Hacktoberfest?</p>\n<p>Well, this guide covers everything you need to know:</p>\n<ul>\n<li>How to make your repo open source?</li>\n<li>How to get valuable contributions from the open source community?</li>\n<li>How to participate in Hacktoberfest as a maintainer?</li>\n</ul>\n<blockquote>\n<p>Most Important: The project should be in Working Condition or at both Logical and Coding End (if coding project). Here are the list of <a href=\"https://www.loginradius.com/open-source/\">OpenSource repos</a> by LoginRadius and the <a href=\"/hacktoberfest-2021/\">issues/guidelines</a> for contributers.</p>\n</blockquote>\n<p>If your project satisfies the above condition, you can just go ahead and implement the steps described as follows. By implementing these steps, you can successfully open source your project and get contributions for your open source project, especially during Hacktoberfest.</p>\n<h2 id=\"title\" style=\"position:relative;\"><a href=\"#title\" aria-label=\"title 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>Title</h2>\n<p>Your project should have a concise title. This title will be the name of your project repo on GitHub.</p>\n<ul>\n<li>The title should be simple and easy to understand.</li>\n<li>No longer than 15 characters.</li>\n<li>Use a hyphen (-) to separate words, not pascal or camel casing. E.g., <strong>engineering-portal</strong></li>\n</ul>\n<h2 id=\"repository-description\" style=\"position:relative;\"><a href=\"#repository-description\" aria-label=\"repository description 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>Repository Description</h2>\n<ul>\n<li>Each project must have a description of the project. The description should give a gist of the project and what the project does.</li>\n<li>The description should not be more than two lines.</li>\n</ul>\n<h2 id=\"topiclabels\" style=\"position:relative;\"><a href=\"#topiclabels\" aria-label=\"topiclabels 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>Topic/Labels</h2>\n<p>As part of Hacktoberfest and to make it easy to find the project, the repository should have one or more of the following labels</p>\n<ul>\n<li>hacktoberfest (mandatory)</li>\n<li>The technology it’s using (golang, react, javascript, etc.)</li>\n<li>open-source </li>\n<li>contributions-welcome</li>\n<li>hacktoberfest2021</li>\n</ul>\n<h2 id=\"project-readme\" style=\"position:relative;\"><a href=\"#project-readme\" aria-label=\"project readme permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Project README</h2>\n<p>Each project must have a README file.</p>\n<ul>\n<li>README should be in Markdown format (README.md)</li>\n<li>\n<p>README should have the following sections:</p>\n<ul>\n<li>Name of the project in h1 Heading at the top of your README.</li>\n<li>\n<p>A Table of Contents in which each item will link to the following headings:</p>\n<ul>\n<li>\n<p>Introduction to the project </p>\n<ul>\n<li>The introduction should start after the heading. </li>\n<li>The introduction should be well written and clarify what your project is doing and what it is about.</li>\n<li>You can also provide a Get Started heading, which should link to the How to Section (Installation).</li>\n</ul>\n</li>\n<li>Features (Optional): If you want to highlight any features, add a list here.</li>\n<li>\n<p>How to install and run the project (h2 Heading: Installation)</p>\n<ul>\n<li>This section should clearly describe how someone can run the project locally and if it requires any installations — e.g., <code>npm i</code> for node projects.</li>\n<li>Add any extra information like creating a .env file or anything needed to run the application locally.</li>\n</ul>\n</li>\n<li>If it’s a library or utility that the user can directly access or use, add an API or Usage section providing a code snippet.</li>\n<li>\n<p>How to Contribute section (h2 Contributing)\t</p>\n<ul>\n<li>\n<p>Section 1 with a link to the open issues tab. </p>\n<ul>\n<li>If you want to contribute, please check the open issues (link of the issues).</li>\n</ul>\n</li>\n<li>\n<p>Section 2 with a link to CONTRIBUTING.md. <a href=\"https://github.com/LoginRadius/business-email-validator/blob/master/CONTRIBUTING.md\">Sample</a> here.</p>\n<ul>\n<li>LICENSE: Mention the license of your project. <a href=\"https://github.com/LoginRadius/engineering-portal#license\">Sample</a> here.</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"contributingmd\" style=\"position:relative;\"><a href=\"#contributingmd\" aria-label=\"contributingmd 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>CONTRIBUTING.MD</h2>\n<p>It should have instructions on how to contribute to the project. Contributions guidelines should have at least three different sections.</p>\n<ul>\n<li>\n<p>Guidelines on Reporting New Issues</p>\n<ul>\n<li>Title and description of the issue.</li>\n<li>Useful tags, if any.</li>\n<li>Steps required to reproduce the issue, if applicable.</li>\n<li>You can also mention an issue template here if required. Issue and PR Templates <a href=\"https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates\">here</a>.</li>\n</ul>\n</li>\n<li>\n<p>Submitting PRs</p>\n<ul>\n<li>How to submit a PR? — e.g., details on what changed, what was removed, any action items needed before submitting a PR like running tests, etc.</li>\n<li>You can add a <code>PULL_REQUEST_TEMPLATE.md</code> in the project root to automatically populate templated content while creating a PR.</li>\n</ul>\n</li>\n<li>\n<p>Commit Message Format</p>\n<ul>\n<li>You can add an optional commit message format to maintain commit consistency. Recommended <a href=\"https://github.com/LoginRadius/business-email-validator/blob/master/CONTRIBUTING.md#commit-messages\">Commit Message Format</a> here.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"license\" style=\"position:relative;\"><a href=\"#license\" aria-label=\"license 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>License</h2>\n<p>Choose an appropriate open source license for your project</p>\n<p>MIT license is one of the <a href=\"https://opensource.org/licenses\">popular open source licenses</a> used by many open source projects on GitHub. <a href=\"https://opensource.org/licenses\">Click here</a> to know more about open source licenses and choose the license most appropriate for your project.</p>\n<h2 id=\"issues-in-repos\" style=\"position:relative;\"><a href=\"#issues-in-repos\" aria-label=\"issues in repos 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>Issues in Repos</h2>\n<p>Each repo should have at least 5-10 well-labeled issues to be considered for Hacktoberfest.</p>\n<ul>\n<li>\n<p>Following are the different issue types:</p>\n<ul>\n<li>hacktoberfest (mandatory)</li>\n<li>good-first-contribution</li>\n<li>good-first-issue</li>\n<li>exp/beginner</li>\n<li>help-wanted</li>\n<li>kind/docs</li>\n<li>kind/enhancement</li>\n<li>up-for-grabs</li>\n</ul>\n</li>\n<li>For more information about managing issues with labels, follow these <a href=\"https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels\">GitHub guidelines</a></li>\n</ul>\n<p>As a maintainer, you could also be eligible to win swag from DigitalOcean for participating in Hacktoberfest. For more information, <a href=\"https://hacktoberfest.digitalocean.com/resources/maintainers\">click here</a>.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"September 28, 2021","updated_date":null,"description":"This ultimate guide is the resource you need to open source your project and participate in Hacktoberfest to get valuable contributions from the community.","title":"How to Participate in Hacktoberfest as a Maintainer","tags":["Hacktoberfest","Hacktoberfest 2021","Open Source"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/9b4d9cbebcded6e980c32d1f168669e4/ee604/cover.png","srcSet":"/static/9b4d9cbebcded6e980c32d1f168669e4/69585/cover.png 200w,\n/static/9b4d9cbebcded6e980c32d1f168669e4/497c6/cover.png 400w,\n/static/9b4d9cbebcded6e980c32d1f168669e4/ee604/cover.png 800w,\n/static/9b4d9cbebcded6e980c32d1f168669e4/f3583/cover.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Narendra Pareek","github":"pareek-narendra","avatar":null}}}}]},"markdownRemark":{"excerpt":"Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie…","fields":{"slug":"/engineering/identity-impact-of-google-chrome-thirdparty-cookie-restrictions/"},"html":"<p>Google has prepared a roadmap to restrict third-party cookies in Chrome. Since 04 January 2024, Chrome has rolled out third-party cookie restrictions for 1% of stable clients and 20% of Canary, Dev, and Beta clients.</p>\n<p><strong>What does it mean for user authentication?</strong></p>\n<p>On one hand, Google believes third-party cookies are widely used for cross-site tracking, greatly affecting user privacy. Hence, Google wants to phase out (or restrict) supporting third-party cookies in Chrome by early Q2 2025 (subject to regulatory processes).</p>\n<p>On the other hand, Google introduced Privacy Sandbox to support the use cases (other than cross-site tracking and advertising) previously implemented using third-party cookies.</p>\n<p>In this article, we’ll discuss:</p>\n<ul>\n<li>How is user authentication (identity) affected?</li>\n<li>What is Google offering as part of Privacy Sandbox to support various identity use cases when third-party cookies are phased out?</li>\n</ul>\n<h2 id=\"how-is-user-authentication-affected\" style=\"position:relative;\"><a href=\"#how-is-user-authentication-affected\" aria-label=\"how is user authentication affected permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is User Authentication Affected?</h2>\n<p>Third-party cookie restrictions affect user authentication in three ways, as follows.</p>\n<h3 id=\"external-identity-providers\" style=\"position:relative;\"><a href=\"#external-identity-providers\" aria-label=\"external identity providers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>External Identity Providers</h3>\n<p>If your website or app uses an external Identity Provider (IdP) — like LoginRadius, the IdP sets a third-party cookie when the user authenticates on your app.</p>\n<h3 id=\"web-sso\" style=\"position:relative;\"><a href=\"#web-sso\" aria-label=\"web sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Web SSO</h3>\n<p>If you have multiple apps across domains within your organization and authentication is handled using an IdP (internal or external) with web SSO, you already use third-party cookies to facilitate seamless access for each user using a single set of credentials.</p>\n<p>If you have implemented web SSO with one primary domain and multiple sub-domains of the primary domain, third-party cookie restrictions may not apply. For now, Google doesn’t consider the cookies set by sub-domains as third-party cookies, although this stance may change in the future.</p>\n<p>For example, you have apps at <code>example.com</code>, <code>travel.example.com</code>, <code>stay.example.com</code>, and web SSO is handled by <code>auth.example.com</code>. In this case, third-party cookie restrictions don’t apply.</p>\n<h3 id=\"federated-sso\" style=\"position:relative;\"><a href=\"#federated-sso\" aria-label=\"federated sso permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated SSO</h3>\n<p>Federated SSO is similar to, albeit different from, web SSO. It can handle multiple IdPs and applications—aka., Service Providers (SPs)—spanning multiple organizations. It can also implement authentication scenarios that are usually implemented through web SSO.</p>\n<p>Usually, authentication is handled on a separate pop-up or page when the user wants to authenticate rather than on the application or website a user visits. </p>\n<p>For example, you already use federated SSO if you facilitate authentication for a set of apps through multiple social identity providers as well as traditional usernames and passwords.</p>\n<blockquote>\n<p><strong>Note</strong>: It is also possible to store tokens locally, not within cookies. In this case, third-party cookie restrictions won’t affect token-based authentication. However, the restrictions still affect authentication where tokens are stored within third-party cookies (a common and secure method).</p>\n</blockquote>\n<h2 id=\"chromes-alternatives-for-third-party-cookies\" style=\"position:relative;\"><a href=\"#chromes-alternatives-for-third-party-cookies\" aria-label=\"chromes alternatives for third party cookies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Chrome’s Alternatives for Third-Party Cookies</h2>\n<p>Google has been developing alternative features and capabilities for Chrome to replace third-party cookies as part of its Privacy Sandbox for Web initiative.</p>\n<p>Specific to authentication, Google recommends the following:</p>\n<ol>\n<li>Cookies Having Independent Partitioned State (CHIPS)</li>\n<li>Storage Access API</li>\n<li>Related Website Sets</li>\n<li>Federated Credential Management (FedCM) API</li>\n</ol>\n<h3 id=\"cookies-having-independent-partitioned-state-chips\" style=\"position:relative;\"><a href=\"#cookies-having-independent-partitioned-state-chips\" aria-label=\"cookies having independent partitioned state chips permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cookies Having Independent Partitioned State (CHIPS)</h3>\n<p><a href=\"https://developers.google.com/privacy-sandbox/3pcd/chips\">CHIPS</a> are a restricted way of setting third-party cookies on a top-level site without making them accessible on other top-level sites. Thus, they limit cross-site tracking and enable specific cross-site functionalities, such as maps, chat, and payment embeds.</p>\n<p>For example, a user visits <code>a.com</code> with a map embed from <code>map-example.com</code>, which can set a partitioned cookie that is only accessible on a.com. </p>\n<p>If the user visits <code>b.com</code> with a map embed from <code>map-example.com</code>, it cannot access the partitioned cookie set on <code>a.com</code>. It has to create a separate partitioned cookie specific to <code>b.com</code>, thus blocking cross-site tracking yet allowing limited cross-site functionality.</p>\n<p>You should specifically opt for partitioned cookies (CHIPS), which are set with partitioned and secure cookie attributes.</p>\n<p>If you’re using an external identity provider for your application, CHIPS is a good option to supplant third-party cookie restrictions. </p>\n<p>However, CHIPS may not be ideal if you have a web SSO or federated SSO implementation. It creates separate partitioned cookies for each application with a separate domain, which can increase complexity and create compatibility issues.</p>\n<h3 id=\"storage-access-api\" style=\"position:relative;\"><a href=\"#storage-access-api\" aria-label=\"storage access api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Storage Access API</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/storage-access-api\">Storage Access API</a>, you can access the local storage in a third-party context through iframes, similar to when users visit it as a top-level site in a first-party context. That is, it gives access to unpartitioned cookies and storage.</p>\n<p>Storage Access API requires explicit user approval to grant access, similar to locations, camera, and microphone permissions. If the user denies access, unpartitioned cookies and storage won’t be accessible in a third-party context.</p>\n<p>It is most suitable when loading cross-site resources and interactions, such as:</p>\n<p>Verifying user sessions when allowing interactions on an embedded social post or providing personalization for an embedded video.\nEmbedded documents requiring user verification status to be accessible.</p>\n<p>As it requires explicit user approval, it is advisable to use Storage Access API when you can’t implement an identity use case with the other options.</p>\n<h3 id=\"related-website-sets\" style=\"position:relative;\"><a href=\"#related-website-sets\" aria-label=\"related website sets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Related Website Sets</h3>\n<p>With <a href=\"https://developers.google.com/privacy-sandbox/3pcd/related-website-sets\">Related Website Sets</a>, you can declare a <code>primary</code> website and <code>associatedSites</code> for limited purposes to grant third-party cookie access and local storage for a limited number of sites.</p>\n<p>Chrome automatically recognizes related website sets declared, accepted, and maintained in this open-source GitHub repository: <a href=\"https://github.com/GoogleChrome/related-website-sets\">Related Website Sets</a></p>\n<p>It provides access through Storage Access API directly without prompting for user approval, but only after the user interacts with the relevant iframe.</p>\n<p>It is important to declare a limited number of domains in related website sets that are meaningful and used for specific purposes. Google may block or suspend any exploitative use of this feature.</p>\n<p>The top-level site can also request approval for specific cross-site resources and scripts to Storage Access API using <code>resuestStorageAccessFor()</code> API.</p>\n<p>If you’re using an external identity provider for your web application, you can declare the domain of the identity provider in the related set to ensure limited third-party cookies and storage access to the identity provider, thus ensuring seamless user authentication.</p>\n<p>Related Website Sets can also work to supplement third-party cookie restrictions in web SSO and federated SSO if the number of web applications (or domains) is limited.</p>\n<h3 id=\"federated-credential-management-fedcm-api\" style=\"position:relative;\"><a href=\"#federated-credential-management-fedcm-api\" aria-label=\"federated credential management fedcm api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Federated Credential Management (FedCM) API</h3>\n<p>FedCM API enables federated SSO without third-party cookies.</p>\n<p>With FedCM API, a user follows these steps for authentication:</p>\n<ol>\n<li>The User navigates to a Service Provider (SP) — aka., Relying Party (RP)</li>\n<li>As the user requests to authenticate, the SP requests the browser through FedCM API to initiate authentication.</li>\n<li>The browser displays a list of available identity providers (supported by the RP), such as social IdPs like Google, Apple, LinkedIn, and Facebook, or other OAuth IdPs like LoginRadius.</li>\n<li>Once the user selects an IdP, the browser communicates with the IdP. Upon valid authentication, the IdP generates a secure token.\nThe browser delivers this secure token to the RP to facilitate user authorization.</li>\n</ol>\n<p>You can access a user demo of FedCM here: <a href=\"https://fedcm-rp-demo.glitch.me/\">FedCM</a>. </p>\n<p>For more information about implementing federated SSO with FedCM API, go through the <a href=\"https://developers.google.com/privacy-sandbox/3pcd/fedcm-developer-guide\">FedCM developer guide</a>.</p>\n<h2 id=\"how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" style=\"position:relative;\"><a href=\"#how-is-loginradius-preparing-for-the-third-party-cookie-phase-out\" aria-label=\"how is loginradius preparing for the third party cookie phase out permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How is LoginRadius Preparing for the Third-party Cookie Phase-out?</h2>\n<p>Firstly, we’re committed to solving our customers' user identity pain points — and preparing for the third-party cookies phase-out is no different.</p>\n<p>We’ll implement the most relevant and widely useful solutions to facilitate a smooth transition for our customers.</p>\n<p>Please subscribe to our blog for more information. We’ll update you on how we help with the third-party cookie phase-out.</p>\n<h2 id=\"in-conclusion\" style=\"position:relative;\"><a href=\"#in-conclusion\" aria-label=\"in conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>In Conclusion</h2>\n<p>The proposed changes to phase out third-party cookies and suggested alternatives are evolving as Google has been actively collaborating and discussing changes with the border community.</p>\n<p>Moreover, browsers like Firefox, Safari, and Edge may approach restricting third-party cookies differently than Google does.</p>\n<p>From LoginRadius, we’ll keep you updated on what we’re doing as a leading Customer Identity and Access Management (CIAM) vendor to prepare for the third-party cookie phase-out.</p>\n<h2 id=\"glossary\" style=\"position:relative;\"><a href=\"#glossary\" aria-label=\"glossary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Glossary</h2>\n<p><strong>Top-level site</strong>: It is the primary site a user has visited.</p>\n<p><strong>First-party cookie</strong>: A cookie set by the top-level site.</p>\n<p><strong>Third-party cookie</strong>: A cookie set by a domain other than the top-level site. For example, let’s assume that a user has visited <code>a.com</code>, which might use an embed from <code>loginradius.com</code> to facilitate authentication. If <code>loginradius.com</code> sets a cookie when the user visits <code>a.com</code>, it is called a third-party cookie as the user hasn’t directly visited <code>loginradius.com</code>.</p>\n<h2 id=\"references\" style=\"position:relative;\"><a href=\"#references\" aria-label=\"references permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>References</h2>\n<ul>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/prepare/prepare-for-phaseout\">Changes to Chrome's treatment of third-party cookies</a></li>\n<li><a href=\"https://developers.google.com/privacy-sandbox/3pcd/guides/identity\">Check the impact of the third-party cookie changes on your sign-in workflows</a></li>\n</ul>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"July 08, 2024","updated_date":null,"description":"Google Chrome has planned to phase out third-party cookies, which will affect different website functionalities depending on third-party cookies. This blog focuses on how this phase-out affects identity and user authentication and discusses alternatives for overcoming challenges.","title":"How Chrome’s Third-Party Cookie Restrictions Affect User Authentication?","tags":["Identity","Cookies","Chrome"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png","srcSet":"/static/eb7396060c0adc430dbed2d04b63d431/69585/third-party-cookies-phaseout-chrome.png 200w,\n/static/eb7396060c0adc430dbed2d04b63d431/497c6/third-party-cookies-phaseout-chrome.png 400w,\n/static/eb7396060c0adc430dbed2d04b63d431/ee604/third-party-cookies-phaseout-chrome.png 800w,\n/static/eb7396060c0adc430dbed2d04b63d431/f3583/third-party-cookies-phaseout-chrome.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Raghunath Reddy","github":"raghunath-r-a","avatar":null}}}},"pageContext":{"limit":6,"skip":36,"currentPage":7,"type":"//engineering//","numPages":52,"pinned":"17fa0d7b-34c8-51c4-b047-df5e2bbaeedb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}