{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/24","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"Writing a foolproof code is hard, especially with a team collaborating on a single project. Thus it becomes increasingly important to ensure…","fields":{"slug":"/engineering/e2e-testing-with-jest-puppeteer/"},"html":"<p>Writing a foolproof code is hard, especially with a team collaborating on a single project. Thus it becomes increasingly important to ensure that no new code breaks existing functionality. And for this purpose, automated tests are used. </p>\n<h2 id=\"requirements\" style=\"position:relative;\"><a href=\"#requirements\" aria-label=\"requirements permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Requirements</h2>\n<ol>\n<li>Basic knowledge of Javascript</li>\n<li>Familiarity with Node.js</li>\n</ol>\n<p>In this blog, we will learn how to integrate Jest and Puppeteer in our project for End-to-End Testing. <a href=\"https://github.com/facebook/jest\">Jest</a> is a javascript testing framework maintained by Facebook. <a href=\"https://github.com/puppeteer/puppeteer\">Puppeteer</a> is a Node library created by Google, which provides a high-level API to control headless Chrome. Before we delve deeper into Jest and Puppeteer, let's familiarise ourselves with a few things.</p>\n<p><strong>End-to-End(E2E) Testing:</strong> E2E testing refers to the testing of a complete functionality of some application. It checks that a functionality acts as intended.</p>\n<p><strong>Headless Testing:</strong> Headless testing is a way or running browser UI tests without any browser UI. It is a preferred method mainly due to its performance. It is fast, light-weight, and less resource-intensive. </p>\n<h2 id=\"installation\" style=\"position:relative;\"><a href=\"#installation\" aria-label=\"installation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Installation</h2>\n<p>To install Jest and Puppeteer, open the command line in your project directory and run:</p>\n<p><strong>For npm users:</strong><br>\n<code>npm install --save-dev jest puppeteer jest-puppeteer</code></p>\n<p><strong>For yarn users:</strong><br>\n<code>yarn add --dev jest puppeteer jest-puppeteer.</code></p>\n<p>Now that we've installed Jest and Puppeteer, it is time to set up the testing environment. Create a file <code>jest.config.js</code> in the project root directory and write the following code in it:</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=\"mtk10\">module</span><span class=\"mtk1\">.</span><span class=\"mtk10\">exports</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">preset:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;jest-puppeteer&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">globals:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">URL:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;http://localhost:8080&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">testMatch:</span><span class=\"mtk1\"> [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk8\">&quot;&lt;path-to-the-tests-folder&gt;/**.test.js&quot;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">verbose:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">true</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<p>Defining the preset sets up a puppeteer environment for testing. Test match directs it to the folder where tests are defined, for a piece of more detailed knowledge about running Jest with Puppeteer <a href=\"https://jestjs.io/docs/en/puppeteer\">check this out</a>.</p>\n<p>Now create a file <code>jest-puppeteer.config.js</code> in the project root directory. Here we define the testing environment further. To begin with you can add the following in this file:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">module</span><span class=\"mtk1\">.</span><span class=\"mtk10\">exports</span><span class=\"mtk1\"> = {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">launch:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">headless:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">HEADLESS</span><span class=\"mtk1\"> !== </span><span class=\"mtk8\">&#39;false&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">slowMo:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">SLOWMO</span><span class=\"mtk1\"> ? </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">SLOWMO</span><span class=\"mtk1\"> : </span><span class=\"mtk7\">0</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">devtools:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">true</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<h2 id=\"testing\" style=\"position:relative;\"><a href=\"#testing\" aria-label=\"testing permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Testing</h2>\n<p>Now we can begin writing our tests. In this example, we'll start writing a basic test to check the title of the page opened. Now head over to the tests folder defined and create a file <code>title.test.js</code>. As you might have noticed, <code>.test.js</code> would be the file extension of the jest tests defined. </p>\n<p>This is what a typical <code>title.test.js</code> would look like:</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=\"mtk3\">// Defining the timeout for the test</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">timeout</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">SLOWMO</span><span class=\"mtk1\"> ? </span><span class=\"mtk7\">6000</span><span class=\"mtk1\"> : </span><span class=\"mtk7\">4000</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">fs</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">require</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;fs&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Go to the specified path and wait for the domcontent to load before running the tests</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">beforeAll</span><span class=\"mtk1\">(</span><span class=\"mtk4\">async</span><span class=\"mtk1\"> () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">path</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">fs</span><span class=\"mtk1\">.</span><span class=\"mtk11\">realpathSync</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;file://&lt;file-path&gt;&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">page</span><span class=\"mtk1\">.</span><span class=\"mtk11\">goto</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;file://&#39;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">path</span><span class=\"mtk1\">, {</span><span class=\"mtk12\">waitUntil:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;domcontentloaded&#39;</span><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">describe</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;Title of the page&#39;</span><span class=\"mtk1\">, () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">test</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;Title of the page&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk4\">async</span><span class=\"mtk1\"> () </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Gets page title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">title</span><span class=\"mtk1\"> = </span><span class=\"mtk15\">await</span><span class=\"mtk1\"> </span><span class=\"mtk12\">page</span><span class=\"mtk1\">.</span><span class=\"mtk11\">title</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// Compares it with the intended behaviour</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">expect</span><span class=\"mtk1\">(</span><span class=\"mtk12\">title</span><span class=\"mtk1\">).</span><span class=\"mtk11\">toBe</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;&lt;title-of-the-page&gt;&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  }, </span><span class=\"mtk12\">timeout</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>Hurray! You've added Headless UI tests to your project. Now you can similarly define tests for different functionalities using the docs <a href=\"https://devdocs.io/puppeteer/\">here</a>.</p>\n<h2 id=\"cons-of-using-jest-puppeteer\" style=\"position:relative;\"><a href=\"#cons-of-using-jest-puppeteer\" aria-label=\"cons of using jest puppeteer permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Cons of using jest-puppeteer</h2>\n<ol>\n<li>It is headless and hence fast, light-weight, and less resource-intensive. </li>\n<li>It can stimulate keyboard-press and mouse-click akin to manual testing functions.</li>\n<li>It is simple and easy to use and works out of the box.</li>\n</ol>\n<h2 id=\"problems-that-you-might-face\" style=\"position:relative;\"><a href=\"#problems-that-you-might-face\" aria-label=\"problems that you might face permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Problems that you might face</h2>\n<p>It could give a sandbox-ing error if you run it in a container without a defined user. When running headless Chrome in a container without a defined user, the chromeOptions environment property needs a --no-sandbox args (in addition to the other headless args), or Chrome won't be able to startup. The <strong>possible solutions</strong> to this are:</p>\n<ol>\n<li>Make sure you're not running them as a root user. </li>\n<li>If running them as a root user, include <code>args: ['--no-sandbox']</code> in jest-puppeteer.config.js (not recommended).</li>\n<li>Make sure you have all the required dependencies installed.\nFor Debian systems that can be installed using:\n<code>sudo apt-get install gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget</code>  </li>\n</ol>\n<p><strong>Happy coding! =)</strong></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"October 15, 2020","updated_date":null,"description":"Learn how to integrate Jest and Puppeteer in your project for End-to-End Testing.","title":"End-to-End Testing with Jest and Puppeteer","tags":["Testing","Jest","Puppeteer"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.6129032258064515,"src":"/static/bc9e7eb8f88f913bb3f3ba67edf01319/01a28/jest-puppeteer.png","srcSet":"/static/bc9e7eb8f88f913bb3f3ba67edf01319/69585/jest-puppeteer.png 200w,\n/static/bc9e7eb8f88f913bb3f3ba67edf01319/497c6/jest-puppeteer.png 400w,\n/static/bc9e7eb8f88f913bb3f3ba67edf01319/01a28/jest-puppeteer.png 799w","sizes":"(max-width: 799px) 100vw, 799px"}}},"author":{"id":"Shreya Sharma","github":"cypherean","avatar":null}}}},{"node":{"excerpt":"A Few Ways to Speed Up Your Python Code Python is one of the most popular languages all over the world. Nowadays it is being used in…","fields":{"slug":"/engineering/speed-up-python-code/"},"html":"<h1 id=\"a-few-ways-to-speed-up-your-python-code\" style=\"position:relative;\"><a href=\"#a-few-ways-to-speed-up-your-python-code\" aria-label=\"a few ways to speed up your python 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>A Few Ways to Speed Up Your Python Code</h1>\n<p>Python is one of the most popular languages all over the world. Nowadays it is being used in competitive programming also because of its simple syntax and rich libraries. Most of us probably started coding with python. At first, everything goes simple and easy. But while solving a hard algorithmic problem, most of us suffer from <code>Time Limit Exceeded</code>. However, it is not a problem of python; it is the programmer's problem. I am not saying that language is not slow, but if a programmer writes an efficient programme, it will get <code>Accepted</code> for sure. Here are some tips to speed up your python programme.</p>\n<h2 id=\"use-proper-data-structure\" style=\"position:relative;\"><a href=\"#use-proper-data-structure\" aria-label=\"use proper data 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>Use proper data structure</h2>\n<p>Use of proper data structure has a significant effect on runtime. Python has list, tuple, set and dictionary as the built-in data structures. However, most of the people use the list in all cases. But it is not a right choice. Use proper data structures depending on your task. Especially use a tuple instead of a list. Because iterating over tuple is easier than iterating over a list.</p>\n<h2 id=\"decrease-the-use-of-for-loop\" style=\"position:relative;\"><a href=\"#decrease-the-use-of-for-loop\" aria-label=\"decrease the use of for loop permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Decrease the use of for loop</h2>\n<p>As for loop is dynamic in python, it takes more time than while loop. So, use while loop instead of for loop.</p>\n<h2 id=\"use-list-comprehension\" style=\"position:relative;\"><a href=\"#use-list-comprehension\" aria-label=\"use list comprehension permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use list comprehension</h2>\n<p>Do not use any other technique if you can use list comprehension. For example, here is a code to list all the numbers between 1 and 1000 that is the multiplier of 3:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">L = []</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> i </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> </span><span class=\"mtk11\">range</span><span class=\"mtk1\"> (</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">1000</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> i%</span><span class=\"mtk7\">3</span><span class=\"mtk1\"> == </span><span class=\"mtk7\">0</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        L.append (i)</span></span></code></pre>\n<p>Using list comprehension, it would be:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">L = [i </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> i </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> </span><span class=\"mtk11\">range</span><span class=\"mtk1\"> (</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">1000</span><span class=\"mtk1\">) </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> i%</span><span class=\"mtk7\">3</span><span class=\"mtk1\"> == </span><span class=\"mtk7\">0</span><span class=\"mtk1\">]</span></span></code></pre>\n<p>List comprehension works faster than using the append method.</p>\n<h2 id=\"use-multiple-assignments\" style=\"position:relative;\"><a href=\"#use-multiple-assignments\" aria-label=\"use multiple assignments permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use multiple assignments</h2>\n<p>Do not assaign variables like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">a = </span><span class=\"mtk7\">2</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">b = </span><span class=\"mtk7\">3</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">c = </span><span class=\"mtk7\">5</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">d = </span><span class=\"mtk7\">7</span></span></code></pre>\n<p>Instead, assign variables like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">a, b, c, d = </span><span class=\"mtk7\">2</span><span class=\"mtk1\">, </span><span class=\"mtk7\">3</span><span class=\"mtk1\">, </span><span class=\"mtk7\">5</span><span class=\"mtk1\">, </span><span class=\"mtk7\">7</span></span></code></pre>\n<h2 id=\"do-not-use-global-variables\" style=\"position:relative;\"><a href=\"#do-not-use-global-variables\" aria-label=\"do not use global variables permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Do not use global variables</h2>\n<p>Python has <code>global</code> keyword to declare global variables. But global variables take higher time during operation than a local variable. So, do not use global variables if it is not necessary.</p>\n<h2 id=\"use-library-function\" style=\"position:relative;\"><a href=\"#use-library-function\" aria-label=\"use library function permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use library function</h2>\n<p>Do not write your function (manually) if it is already in the library. Library functions are highly efficient, and you will probably won't be able to code with that efficiency.</p>\n<h2 id=\"concatenate-strings-with-join\" style=\"position:relative;\"><a href=\"#concatenate-strings-with-join\" aria-label=\"concatenate strings with join permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Concatenate strings with join</h2>\n<p>In python, you can concatenate strings with <code>+</code> operation.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">concatenatedString = </span><span class=\"mtk8\">&quot;Programming &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&quot;is &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&quot;fun.&quot;</span></span></code></pre>\n<p>It can also be done with <code>join()</code> method.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">concatenatedString = </span><span class=\"mtk8\">&quot; &quot;</span><span class=\"mtk1\">.join ([</span><span class=\"mtk8\">&quot;Programming&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;is&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;fun.&quot;</span><span class=\"mtk1\">])</span></span></code></pre>\n<p><code>join()</code> concatenates strings faster than <code>+</code> operation because <code>+</code> operators create a new string and then copies the old content at each step. But <code>join()</code> doesn't work that way.</p>\n<h2 id=\"use-generators\" style=\"position:relative;\"><a href=\"#use-generators\" aria-label=\"use generators permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use generators</h2>\n<p>If you have a large amount of data in your list and you need to use one data at a time and for once then use <code>generator</code>s. It will save you time.</p>\n<h2 id=\"it-may-seem-efficient-but-its-not\" style=\"position:relative;\"><a href=\"#it-may-seem-efficient-but-its-not\" aria-label=\"it may seem efficient but its not permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>It may seem efficient, but it's not</h2>\n<p>See the below code:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">L = []</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> element </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> </span><span class=\"mtk10\">set</span><span class=\"mtk1\">(L):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span></code></pre>\n<p>The above code may seem efficient because it used set to delete duplicate data. But the reality is that the code is not efficient. Do not forget that converting a list into set takes time. So this code will work better than the previous:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> element </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> L:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span></code></pre>\n<h2 id=\"do-not-use-dot-operation\" style=\"position:relative;\"><a href=\"#do-not-use-dot-operation\" aria-label=\"do not use dot operation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Do not use dot operation</h2>\n<p>Try to avoid dot operation. See the below programme.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">import</span><span class=\"mtk1\"> math</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">val = math.sqrt(</span><span class=\"mtk7\">60</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>Instead of the above style write code like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> math </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> sqrt</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">val = sqrt(</span><span class=\"mtk7\">60</span><span class=\"mtk1\">)</span></span></code></pre>\n<p>Because when you call a function using <code>.</code> (dot) it first calls <code>__getattribute()__</code> or <code>__getattr()__</code> which then use dictionary operation which costs time. So, try using <code>from module import function</code>.</p>\n<h2 id=\"use-1-for-infinity-loops\" style=\"position:relative;\"><a href=\"#use-1-for-infinity-loops\" aria-label=\"use 1 for infinity loops permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use 1 for infinity loops</h2>\n<p>Use <code>while 1</code> instead of <code>while True</code>. It will reduce some runtime.</p>\n<h2 id=\"try-a-different-approach\" style=\"position:relative;\"><a href=\"#try-a-different-approach\" aria-label=\"try a different approach permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Try a different approach</h2>\n<p>Try new ways to write your code efficiently. See the below code.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> a_condition:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> another_condition:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        do_something</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">else</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">raise</span><span class=\"mtk1\"> exception</span></span></code></pre>\n<p>Instead of the above code you can write:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"python\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> (</span><span class=\"mtk4\">not</span><span class=\"mtk1\"> a_condition) </span><span class=\"mtk4\">or</span><span class=\"mtk1\"> (</span><span class=\"mtk4\">not</span><span class=\"mtk1\"> another_condition):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">raise</span><span class=\"mtk1\"> exception</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">do_something</span></span></code></pre>\n<h2 id=\"use-speed-up-applications\" style=\"position:relative;\"><a href=\"#use-speed-up-applications\" aria-label=\"use speed up applications permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use speed up applications</h2>\n<p>For python's slow speed, some projects have been taken to decrease runtime. Pypy and Numba two of them. In most of the programming contests, you will see pypy if it allows python. These applications will reduce the runtime of your programme.</p>\n<h2 id=\"use-special-libraries-to-process-large-datasets\" style=\"position:relative;\"><a href=\"#use-special-libraries-to-process-large-datasets\" aria-label=\"use special libraries to process large datasets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use special libraries to process large datasets</h2>\n<p>C/C++ is faster than python. So, many packages and modules have been written in C/C++ that you can use in your python programme. <code>Numpy</code>, <code>Scipy</code> and <code>Pandas</code> are three of them and are popular for processing large datasets.</p>\n<h2 id=\"use-the-latest-release-of-python\" style=\"position:relative;\"><a href=\"#use-the-latest-release-of-python\" aria-label=\"use the latest release of python permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Use the latest release of python</h2>\n<p>Python is updated and upgraded regularly, and every release is faster and more optimized. So always use the latest version of python.</p>\n<p>These were some of the tips to decrease the runtime of python code. There are a few more techniques that you can use. Use a search engine to find those and write efficient code!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"October 15, 2020","updated_date":null,"description":"Learn a few ways to speed up your python code.","title":"Speed Up Python Code","tags":["Python","Performance"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/80999ea5cffd2a5ffbfe1622f4b9c068/14b42/speed-up-python-code-1.jpg","srcSet":"/static/80999ea5cffd2a5ffbfe1622f4b9c068/f836f/speed-up-python-code-1.jpg 200w,\n/static/80999ea5cffd2a5ffbfe1622f4b9c068/2244e/speed-up-python-code-1.jpg 400w,\n/static/80999ea5cffd2a5ffbfe1622f4b9c068/14b42/speed-up-python-code-1.jpg 800w,\n/static/80999ea5cffd2a5ffbfe1622f4b9c068/47498/speed-up-python-code-1.jpg 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Md. Tahmid Hossain","github":"tahmid02016","avatar":null}}}},{"node":{"excerpt":"Build a Twitter Bot with NodeJs Hey there! In this blog post, we will build a twitter bot that let us tweet using the command line directly…","fields":{"slug":"/engineering/build-a-twitter-bot-using-nodejs/"},"html":"<h2 id=\"build-a-twitter-bot-with-nodejs\" style=\"position:relative;\"><a href=\"#build-a-twitter-bot-with-nodejs\" aria-label=\"build a twitter bot with nodejs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Build a Twitter Bot with NodeJs</h2>\n<p>Hey there! In this blog post, we will build a twitter bot that let us tweet using the command line directly. </p>\n<blockquote>\n<p><a href=\"https://nodejs.org/en/download/\">Node</a> and <a href=\"https://www.npmjs.com/\">npm</a> (or, yarn) must be installed on your system. </p>\n</blockquote>\n<h2 id=\"lets-start-\" style=\"position:relative;\"><a href=\"#lets-start-\" aria-label=\"lets start  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Let's Start 🎉</h2>\n<p>We will use <strong><a href=\"https://github.com/desmondmorris/node-twitter\">twitter</a></strong> - a client library for the Twitter REST and Streaming APIs. This npm package will make the whole process of building the bot a whole lot easier and faster. </p>\n<h3 id=\"1-apply-for-a-twitter-developer-account\" style=\"position:relative;\"><a href=\"#1-apply-for-a-twitter-developer-account\" aria-label=\"1 apply for a twitter developer account permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 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. Apply for a Twitter Developer Account</h3>\n<p>To be able to access Twitter API, you need a Twitter Developer Account. Apply for it <a href=\"https://developer.twitter.com/en/apply-for-access\">here</a>. Click on <em>Apply for a Developer Account</em>.</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: 33.07692307692307%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA/UlEQVQY03WPyW6DQAyGefCq5z5EH6BLLlGkKuXEpVEO5JKqt1aVWGYoCYQQwLPZU4NyDJ80lrffYwdJkp7q2hpjtNYKrDVKKQ6dtUrpYQA/MRYnAEBzsyP2gwHUWbtG+4uhk6bW+kZha/xgiTXkryASjlwtkXeIARe+8zKr+9+iTo7nH1n9XXRadYd26LsOQPl5Ah6yent/en5ZLF53u3i9Xn/u92EYRlG0XK4+Npvxf6JZcaVs0wMfOa2EzqHh06fQOU6PsH9LjFgWhRAyy0UupBSikDLPsmKC82maHY4Vz7ohRvKPX+p+Cw8x3G0hLm1nsAJiy0uNb2Zn5h9k5Y5fQoRJkwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Twitter Developer Account\"\n        title=\"Twitter Developer Account\"\n        src=\"/static/16a0b5bcb6a6661a39b0bb6f3fd230ec/e5715/twitter.png\"\n        srcset=\"/static/16a0b5bcb6a6661a39b0bb6f3fd230ec/a6d36/twitter.png 650w,\n/static/16a0b5bcb6a6661a39b0bb6f3fd230ec/e5715/twitter.png 768w,\n/static/16a0b5bcb6a6661a39b0bb6f3fd230ec/d8817/twitter.png 1238w\"\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>It will ask you to log in. Select appropriate settings after logging in. It will also generate <strong>keys</strong> and <strong>secret tokens</strong> like Consumer Key, Consumer Secret, Access Token Key, Access Token Secret. Copy and save them somewhere for future use. </p>\n<h3 id=\"2-setup-project\" style=\"position:relative;\"><a href=\"#2-setup-project\" aria-label=\"2 setup project permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Setup Project</h3>\n<p>Make a project folder with any name of your choice. Run <code>npm init</code> to initialize the project. This will generate a <code>package.json</code> file in your directory. Alternatively, you can run <code>npm init -y</code> to setup your project with default settings.</p>\n<blockquote>\n<p><code>package.json</code> holds all the dependencies of a project.</p>\n</blockquote>\n<p>Since our project will be dependent on <strong>twitter</strong> client library, it's time we install this dependency in our project. Run <code>npm install twitter</code> to include this in your <code>package.json</code> .</p>\n<h3 id=\"3-setup-files\" style=\"position:relative;\"><a href=\"#3-setup-files\" aria-label=\"3 setup files permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 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. Setup Files</h3>\n<p>Now we will start with the actual coding part. At the moment, your project folder will have a <code>node_modules</code> folder, a <code>package.json</code> file, and a <code>package-lock.json</code> file. If you have gone with the default options while running <code>npm init</code>, then <code>index.js</code> is the file we will be working upon.</p>\n<p>Open <code>index.js</code>. To be able to use the <strong>twitter</strong> library, which we have installed, you need to include it in <code>index.js</code>. </p>\n<p><code>var Twitter = require('twitter');</code></p>\n<p>Also, remember the <strong>keys</strong> and <strong>tokens</strong> you got from Twitter Developer Portal? It's time we use them. </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=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">client</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Twitter</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">consumer_key:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">CONSUMER_KEY</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">consumer_secret:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">CONSUMER_SECRET</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">access_token_key:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ACCESS_TOKEN_KEY</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">access_token_secret:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">process</span><span class=\"mtk1\">.</span><span class=\"mtk12\">env</span><span class=\"mtk1\">.</span><span class=\"mtk12\">ACCESS_TOKEN_SECRET</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p><strong>Do not add your Consumer or Access Token keys or secrets directly in the <code>index.js</code>.</strong> These should be managed accordingly using <em>environment variables</em>.</p>\n<blockquote>\n<p>We will use <code>dotenv</code> library to manage our environment variables in NodeJS.  Run <code>npm install dotenv</code> and follow <a href=\"https://www.npmjs.com/package/dotenv#usage\">these</a> instructions. Your <code>.env</code> will look something like this.</p>\n</blockquote>\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\">CONSUMER_KEY</span><span class=\"mtk1\">=........................................</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">CONSUMER_SECRET</span><span class=\"mtk1\">=.....................................</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">ACCESS_TOKEN_KEY</span><span class=\"mtk1\">=....................................</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">ACCESS_TOKEN_SECRET</span><span class=\"mtk1\">=.................................</span></span></code></pre>\n<h3 id=\"4-start-coding-\" style=\"position:relative;\"><a href=\"#4-start-coding-\" aria-label=\"4 start coding  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 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. Start Coding 🎯</h3>\n<p>I will use <a href=\"https://github.com/15Dkatz/official_joke_api\">Official Joke API</a> to automatically fetch content for my tweet. You can visit the repository and learn more about the endpoints. But the only <a href=\"https://github.com/15Dkatz/official_joke_api#grab-a-random-joke\">endpoint</a> we will work with is <a href=\"https://official-joke-api.appspot.com/random_joke\">random_joke</a>. Click on this, and you will receive a JSON response with fields id, type, setup, and punchline. The fields we are concerned with are setup and punchline. </p>\n<p>We will use <a href=\"https://github.com/axios/axios\">axios</a> for calling the API endpoint. Run <code>npm install axios</code> and add <code>var axios = require('axios');</code> in <code>index.js</code>.</p>\n<p>Now everything has been laid out. We need to connect the dots. The Official Joke API will return a JSON response. We will grab the required data, i.e., the setup and the punchline from it. And then make use of <a href=\"https://github.com/desmondmorris/node-twitter/tree/master/examples#tweet\">client.post</a> functionality of <strong>twitter</strong> package.</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=\"mtk11\">axios</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;https://official-joke-api.appspot.com/random_joke&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">Response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [</span><span class=\"mtk12\">Response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">setup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">Response</span><span class=\"mtk1\">.</span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">punchline</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}).</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(([</span><span class=\"mtk12\">setup</span><span class=\"mtk1\">, </span><span class=\"mtk12\">punch</span><span class=\"mtk1\">]) </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t</span><span class=\"mtk12\">client</span><span class=\"mtk1\">.</span><span class=\"mtk11\">post</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;statuses/update&#39;</span><span class=\"mtk1\">, {</span><span class=\"mtk12\">status:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">`</span><span class=\"mtk4\">${</span><span class=\"mtk12\">setup</span><span class=\"mtk4\">}</span><span class=\"mtk6\">\\n</span><span class=\"mtk4\">${</span><span class=\"mtk12\">punch</span><span class=\"mtk4\">}</span><span class=\"mtk8\">`</span><span class=\"mtk1\">}, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk1\">, </span><span class=\"mtk12\">tweet</span><span class=\"mtk1\">, </span><span class=\"mtk12\">response</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t</span><span class=\"mtk15\">if</span><span class=\"mtk1\">(!</span><span class=\"mtk12\">error</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t\t</span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">tweet</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t\t}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">\t})</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span></code></pre>\n<p>Now run <code>node index.js</code> on the terminal and see the output.\nIf everything went well, you would see a <em>tweet</em> response, otherwise an <em>error</em> message. The successful message would look something like <a href=\"https://developer.twitter.com/en/docs/twitter-api/v1/tweets/post-and-engage/api-reference/post-statuses-update#example-response\">this</a>.</p>\n<p>At this point, your index.js should look like this.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 45.69230769230769%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABBklEQVQoz42R627DIAyFeZAmGBsMJCHc2iRqs/3p+7/TSPdjUzdVPbLE4fLJ1kGElGIuOQznOl/aYhmklH0v35BAdsaNho3xji0rUF1/sF136k6n/qUEsS/7Pa4f03IN2x7qapdP3u46rcjDr5fyP9jwULaxbkNZ3VybcelM5UZlx3IFN7VB2ghHdd0zbIwmBeYoqRUwKkvKYjNgCa0mrdEwEztQ+NRfjKO/5FLOS12uuV5SyjGmmEqYY8y1GWtZG3PAiA/2hxftYkolL1sqdZ6myXtCRdYDanJjY4wPCnXbIntiq63X7HgImllIAAXQjtgPRxPrHz/1lgRpAoDvPI5I/qTyQl8o80v3xwnZmgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"index.js\"\n        title=\"index.js\"\n        src=\"/static/0758fb1dcb8133462eba5090310a8030/e5715/code.png\"\n        srcset=\"/static/0758fb1dcb8133462eba5090310a8030/a6d36/code.png 650w,\n/static/0758fb1dcb8133462eba5090310a8030/e5715/code.png 768w,\n/static/0758fb1dcb8133462eba5090310a8030/c3fd4/code.png 854w\"\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=\"congratulations-\" style=\"position:relative;\"><a href=\"#congratulations-\" aria-label=\"congratulations  permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Congratulations! 🎊</h3>\n<p>That's it! You have created your first Twitter Bot, which tweets content after directly calling it from an API. You might take a look at the <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/NodeJs/TwitterBot\">repository</a> if you encountered any errors. Here, I have used different APIs to fetch content and tweet. Moreover, I have added a script that will search posts with a particular hashtag and like them. </p>\n<blockquote>\n<p><strong>While pushing your code to GitHub, make sure to add <code>.gitignore</code> file and include <code>node_modules</code> and <code>.env</code> in it.</strong></p>\n</blockquote>\n<h2 id=\"further-reading\" style=\"position:relative;\"><a href=\"#further-reading\" aria-label=\"further reading permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Further Reading</h2>\n<blockquote>\n<p>The world is yours to explore.</p>\n</blockquote>\n<p>And the dev world is based entirely on exploring technologies and frameworks. Play with this <strong>twitter</strong> library and see what interesting stuff can be built with it. Maybe, search tweets with a particular hashtag and like them? Or maybe, retweet tweets of any particular user? You are free to use your imagination and coding skills to explore more and more. If <code>axios</code> and <code>dotenv</code> are new to you, then go ahead and read their documentation. Get hold of the concepts of environment variables. And come up with your own cool Twitter Bot.</p>\n<blockquote>\n<p>Keep in mind Twitter's <a href=\"https://developer.twitter.com/en/developer-terms\">Developer Policy &#x26; Terms</a> and <a href=\"https://twitter.com/en/tos\">Twitter Terms &#x26; Conditions</a>. These should not be violated in whatever project you are building.</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 .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n</style>","frontmatter":{"date":"October 14, 2020","updated_date":null,"description":"Learn how to create a twitter bot using NodeJS that let us tweet using the command line directly","title":"Build A Twitter Bot Using NodeJS","tags":["NodeJs","Twitter","Bot"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/73b57d06f8809fab5ebb6ad89ab328ef/14b42/cover.jpg","srcSet":"/static/73b57d06f8809fab5ebb6ad89ab328ef/f836f/cover.jpg 200w,\n/static/73b57d06f8809fab5ebb6ad89ab328ef/2244e/cover.jpg 400w,\n/static/73b57d06f8809fab5ebb6ad89ab328ef/14b42/cover.jpg 800w,\n/static/73b57d06f8809fab5ebb6ad89ab328ef/47498/cover.jpg 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Vineeta Jain","github":"Ninjavin","avatar":null}}}},{"node":{"excerpt":"Motivation Maps are an effective, intuitive way to understand data in some use-cases. Interactive web maps can help us visualize the data…","fields":{"slug":"/engineering/visualizing-data-using-leaflet-and-netlify/"},"html":"<h2 id=\"motivation\" style=\"position:relative;\"><a href=\"#motivation\" aria-label=\"motivation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Motivation</h2>\n<p>Maps are an effective, intuitive way to understand data in some use-cases. Interactive web maps can help us visualize the data better and derive better insights.</p>\n<p>Different map visualizations can highlight different aspects of a dataset. Heatmaps, Choropleth maps and Clustering maps are frequently used for this purpose.</p>\n<p>In this blog, I shall go over using a powerful JavaScript library to build a web map and deploy it on Netlify.</p>\n<h2 id=\"using-leaflet\" style=\"position:relative;\"><a href=\"#using-leaflet\" aria-label=\"using leaflet permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using Leaflet</h2>\n<p>The Leaflet is a great library for implementing interactive web maps as it provides many UI features, like smooth canvas panning, zooming, mouse events, and all the involved work in animations, which one would otherwise have to implement from scratch.</p>\n<blockquote>\n<p>Leaflet is the leading open-source JavaScript library for mobile-friendly interactive maps. Weighing just about 39 KB of JS, it has all the mapping features most developers ever need.</p>\n<p><em>source: leafletjs.com</em></p>\n</blockquote>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 26.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABgElEQVQY02Po6enhaW1tLQHiViCbf86cOQyHDh1iOHjwIAOQLwAUbmlubs5saWnJW7x4MUNtTR1vc0tTcMPaeIYZ5/wYNt2Ld97xOPX/nmc5x/Z+D2Ng6Orq0u7r6+sAYs3GxsYooObYpqamIKABGUC5wN7e3sLu7u46oMF+1dXV/h0d7ZP6uyfX1J7Q1mjd5xq06V7slS0PEv/veZ595v//acwMHR0d9Z2dnUBzmu2ABixra2urBbpsEZDdBTRoNpCqBBra09/fnwUUn9A/obe7u2F6WO0Bs8DmQy7/V94I+7/lQcL/rffSNjAwMHEyAF2mM2HCBLP29nZdIFsDaIESkNYGWiAJpCcCDfMGukw1MTHBNScn2yUlNcm9pqxZbc9/C66i1Q6n2rd5bdz+KGHzouMxRv///2cAGcgANJABaCADUDPIxaCwY5g4cSJITs/T05NBVlZGXl1dTZ6VlUVARlpaXF5BRsLU2DxQV9lMZcJOX4Y9r5MZ5uyPYgABAN8WuhdrO7L5AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Leaflet Logo\"\n        title=\"Leaflet Logo\"\n        src=\"/static/2f52485085dcefad9f7aa6e60786e779/0a47e/leaflet.png\"\n        srcset=\"/static/2f52485085dcefad9f7aa6e60786e779/0a47e/leaflet.png 600w\"\n        sizes=\"(max-width: 600px) 100vw, 600px\"\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>We can include Leaflet in our application by including the CSS stylesheet and the JS file from the unpkg CDN. Let's start building the application by starting with the following code at the project root. Create a file named <code>index.html</code> and put the following markup in it. The map shall be rendered in <code>div#mapid</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">index</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\">--&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!</span><span class=\"mtk12\">DOCTYPE</span><span class=\"mtk1\"> </span><span class=\"mtk12\">html</span><span class=\"mtk1\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">html</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lang</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;en&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">charset</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;UTF-8&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">meta</span><span class=\"mtk1\"> </span><span class=\"mtk12\">name</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;viewport&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">content</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;width=device-width, initial-scale=1.0&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">MapViz</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">title</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><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://unpkg.com/leaflet/dist/leaflet.css&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk17\">/&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      #mapid </span><span class=\"mtk4\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk12\">fixed</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">width</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100</span><span class=\"mtk1\">%;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">height</span><span class=\"mtk1\">: </span><span class=\"mtk7\">100</span><span class=\"mtk1\">%;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">top</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">left</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=\"mtk4\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">style</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">head</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">div</span><span class=\"mtk1\"> </span><span class=\"mtk12\">id</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;mapid&quot;</span><span class=\"mtk17\">&gt;&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\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">defer</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://unpkg.com/leaflet/dist/leaflet.js&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 class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</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\">html</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>Now, we gather a link to the GeoJSON file for metro stations in Washington D.C., that we shall be visualizing, from the <a href=\"https://docs.mapbox.com/help/glossary/geojson/\">MapBox documentation</a>. It should look similar to the following:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">https://docs.mapbox.com/help/data/stations.geojson</span></code></pre>\n<p>Create a new JavaScript file named <code>script.js</code> in the same directory as the HTML file. Include this file in the web page by adding the following line to it.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"html\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">index</span><span class=\"mtk1\">.</span><span class=\"mtk12\">html</span><span class=\"mtk1\">--&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">defer</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://unpkg.com/leaflet/dist/leaflet.js&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 class=\"mtk1\">    </span><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;script.js&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 class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">body</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span></code></pre>\n<p>In <code>script.js</code>, we can use the Fetch API to make an AJAX request and get the data as a response to a <code>GET</code> request using promises and take a look at what we are dealing with.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// script.js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;https://cors-anywhere.herokuapp.com/https://docs.mapbox.com/help/data/stations.geojson&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">))</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>We can take a look at the data in the Developer Console. We observe that it is a JavaScript object. The various properties associated with the data can be viewed by checking the individual features.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;type&quot;</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;FeatureCollection&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk8\">&quot;features&quot;</span><span class=\"mtk1\">: [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk8\">&quot;geometry&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Point&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;coordinates&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> [-</span><span class=\"mtk7\">76.9750541388</span><span class=\"mtk1\">, </span><span class=\"mtk7\">38.8410857803</span><span class=\"mtk1\">]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      },</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk8\">&quot;type&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Feature&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk8\">&quot;properties&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;description&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Southern Ave&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;marker-symbol&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;rail-metro&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;title&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Southern Ave&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;url&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;http://www.wmata.com/rider_tools/pids/showpid.cfm?station_id=107&quot;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;lines&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> [</span><span class=\"mtk8\">&quot;Green&quot;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk8\">&quot;address&quot;</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;1411 Southern Avenue, Temple Hills, MD 20748&quot;</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>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ]</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Before we begin adding the layers to our map, we need to instantiate a Leaflet <code>map</code> object with the DOM ID of the map container and center it on our point of interest at a specified initial zoom level.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">map</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;mapid&#39;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">setView</span><span class=\"mtk1\">([</span><span class=\"mtk7\">38.8977</span><span class=\"mtk1\">, -</span><span class=\"mtk7\">77.0365</span><span class=\"mtk1\">], </span><span class=\"mtk7\">15</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>As we need a base map (the base layer) for our map, we can use one that is provided by Mapbox. In order to use that, you need a Mapbox API access token that you can create on <a href=\"https://account.mapbox.com/\">their portal</a>.</p>\n<p>The following snippet instantiates a <code>tileLayer</code> object and adds it to our map:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">tileLayer</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}&#39;</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">attribution:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Map data &copy; &lt;a href=&quot;https://www.openstreetmap.org/&quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery © &lt;a href=&quot;https://www.mapbox.com/&quot;&gt;Mapbox&lt;/a&gt;&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">maxZoom:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">18</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;mapbox/streets-v11&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">tileSize:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">512</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">zoomOffset:</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 class=\"mtk12\">accessToken:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;your_mapbox_api_access_token&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>We can use the following snippet to parse the GeoJSON and add it to the map.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Replace the code in <code>script.js</code> with the following, and refresh the web page:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">let</span><span class=\"mtk1\"> </span><span class=\"mtk12\">data</span><span class=\"mtk1\"> = {};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;https://cors-anywhere.herokuapp.com/https://docs.mapbox.com/help/data/stations.geojson&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk12\">map</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;mapid&#39;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">setView</span><span class=\"mtk1\">([</span><span class=\"mtk7\">38.8977</span><span class=\"mtk1\">, -</span><span class=\"mtk7\">77.0365</span><span class=\"mtk1\">], </span><span class=\"mtk7\">15</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">tileLayer</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}&#39;</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">attribution:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;Map data &copy; &lt;a href=&quot;https://www.openstreetmap.org/&quot;&gt;OpenStreetMap&lt;/a&gt; contributors, &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;&gt;CC-BY-SA&lt;/a&gt;, Imagery © &lt;a href=&quot;https://www.mapbox.com/&quot;&gt;Mapbox&lt;/a&gt;&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">maxZoom:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">18</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">id:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;mapbox/streets-v11&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">tileSize:</span><span class=\"mtk1\"> </span><span class=\"mtk7\">512</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">zoomOffset:</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 class=\"mtk12\">accessToken:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;your_mapbox_api_access_token&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">));</span></span></code></pre>\n<p>As the dataset contains <code>Point</code> features, markers will be added at the respective coordinates. Our web page will now look like the following:</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: 77.07692307692308%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAdhKS0j/xAAXEAEAAwAAAAAAAAAAAAAAAAAAEBFB/9oACAEBAAEFApxb/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8Bqv/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AVf/xAAUEAEAAAAAAAAAAAAAAAAAAAAg/9oACAEBAAY/Al//xAAXEAADAQAAAAAAAAAAAAAAAAAAARFR/9oACAEBAAE/IUXRCbiIrlKyn//aAAwDAQACAAMAAAAQ0A//xAAWEQEBAQAAAAAAAAAAAAAAAAAAEUH/2gAIAQMBAT8QjEP/xAAWEQADAAAAAAAAAAAAAAAAAAAQEVH/2gAIAQIBAT8QdD//xAAbEAEBAAMBAQEAAAAAAAAAAAABEQAhMUFRcf/aAAgBAQABPxBDYROX3BAH4p9z1F7u5cWp3ENHW9w2QU+5/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Map with Markers\"\n        title=\"Map with Markers\"\n        src=\"/static/445512bb026a1bf0a9f099240460a15f/212bf/mapInitial.jpg\"\n        srcset=\"/static/445512bb026a1bf0a9f099240460a15f/6aca1/mapInitial.jpg 650w,\n/static/445512bb026a1bf0a9f099240460a15f/212bf/mapInitial.jpg 768w,\n/static/445512bb026a1bf0a9f099240460a15f/70dea/mapInitial.jpg 861w\"\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>We can show tooltips upon clicking on the markers by modifying the code as follows, to include some custom HTML using the properties in the feature, in the popup:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// script.js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk11\">fetch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">dataUrl</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">response</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk12\">response</span><span class=\"mtk1\">.</span><span class=\"mtk11\">json</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">then</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">onEachFeature</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">feature</span><span class=\"mtk1\">, </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">.</span><span class=\"mtk11\">bindPopup</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk8\">&#39;&lt;h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;p&gt;&#39;</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          +  </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">address</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/p&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  })</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  .</span><span class=\"mtk11\">catch</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\"> </span><span class=\"mtk4\">=&gt;</span><span class=\"mtk1\"> </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">err</span><span class=\"mtk1\">));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span></code></pre>\n<p>Uupon clicking any marker, we will now see the following popup:</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: 76.92307692307692%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHYcOSiQ//EABUQAQEAAAAAAAAAAAAAAAAAABBB/9oACAEBAAEFAmH/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwGq/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BV//EABQQAQAAAAAAAAAAAAAAAAAAACD/2gAIAQEABj8CX//EABgQAAMBAQAAAAAAAAAAAAAAAAABESFR/9oACAEBAAE/IUJ5p2CbiIrlK+U//9oADAMBAAIAAwAAABCDD//EABcRAAMBAAAAAAAAAAAAAAAAAAABETH/2gAIAQMBAT8Qh4Qf/8QAFhEAAwAAAAAAAAAAAAAAAAAAEBFR/9oACAECAQE/EHQ//8QAGhAAAgMBAQAAAAAAAAAAAAAAAREAIUExUf/aAAgBAQABPxAgWgjj2AR/BQ2BNh7tR4cx0wgo6X2C5BbZ/9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Map with Popups\"\n        title=\"Map with Popups\"\n        src=\"/static/6e3b1ecd942605fe6d015a7f22b31fff/212bf/mapPopup.jpg\"\n        srcset=\"/static/6e3b1ecd942605fe6d015a7f22b31fff/6aca1/mapPopup.jpg 650w,\n/static/6e3b1ecd942605fe6d015a7f22b31fff/212bf/mapPopup.jpg 768w,\n/static/6e3b1ecd942605fe6d015a7f22b31fff/0b9e0/mapPopup.jpg 864w\"\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>We can also customize the marker icon using the <code>pointToLayer</code> option of the <code>geoJSON</code> constructor as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// scripts.js</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  ...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">geoJSON</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">pointToLayer</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">feature</span><span class=\"mtk1\">, </span><span class=\"mtk12\">coords</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">L</span><span class=\"mtk1\">.</span><span class=\"mtk11\">marker</span><span class=\"mtk1\">(</span><span class=\"mtk12\">coords</span><span class=\"mtk1\">, {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk12\">icon:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">L</span><span class=\"mtk1\">.</span><span class=\"mtk10\">Icon</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">iconSize:</span><span class=\"mtk1\"> [</span><span class=\"mtk7\">30</span><span class=\"mtk1\">, </span><span class=\"mtk7\">30</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">iconAnchor:</span><span class=\"mtk1\"> [</span><span class=\"mtk7\">15</span><span class=\"mtk1\">, </span><span class=\"mtk7\">15</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">popupAnchor:</span><span class=\"mtk1\"> [</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, -</span><span class=\"mtk7\">24</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk12\">iconUrl:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&#39;https://cdn.iconscout.com/icon/free/png-256/metro-subway-underground-train-railway-engine-emoj-symbol-30744.png&#39;</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>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      </span><span class=\"mtk11\">onEachFeature</span><span class=\"mtk12\">:</span><span class=\"mtk1\"> </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">feature</span><span class=\"mtk1\">, </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">layer</span><span class=\"mtk1\">.</span><span class=\"mtk11\">bindPopup</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          </span><span class=\"mtk8\">&#39;&lt;h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">title</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/h4&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;p&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk12\">feature</span><span class=\"mtk1\">.</span><span class=\"mtk12\">properties</span><span class=\"mtk1\">.</span><span class=\"mtk12\">address</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">          + </span><span class=\"mtk8\">&#39;&lt;/p&gt;&#39;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">      }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }).</span><span class=\"mtk11\">addTo</span><span class=\"mtk1\">(</span><span class=\"mtk12\">map</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ...</span></span></code></pre>\n<p>Our updated web page will now look like the following:</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: 77.07692307692308%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwX/xAAWAQEBAQAAAAAAAAAAAAAAAAABAAL/2gAMAwEAAhADEAAAAew83kskb//EABYQAQEBAAAAAAAAAAAAAAAAAAAREP/aAAgBAQABBQLaqv/EABYRAQEBAAAAAAAAAAAAAAAAAAARAf/aAAgBAwEBPwG4r//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/AVf/xAAWEAADAAAAAAAAAAAAAAAAAAAAICH/2gAIAQEABj8CKv8A/8QAGhAAAwEAAwAAAAAAAAAAAAAAAAEhERAxQf/aAAgBAQABPyFYJzwTXRQdG+H/2gAMAwEAAgADAAAAELgP/8QAFhEBAQEAAAAAAAAAAAAAAAAAABFR/9oACAEDAQE/EMEP/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAgEBPxCzGQf/xAAcEAEAAwEBAAMAAAAAAAAAAAABABExIUFRkaH/2gAIAQEAAT8Qsa91s2aEfK3I6C9+pWWlXux6HPb2LFs38n//2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Map with Custom Icon\"\n        title=\"Map with Custom Icon\"\n        src=\"/static/5ccce65251da4bb1a1f35ff984c1e005/212bf/mapIcon.jpg\"\n        srcset=\"/static/5ccce65251da4bb1a1f35ff984c1e005/6aca1/mapIcon.jpg 650w,\n/static/5ccce65251da4bb1a1f35ff984c1e005/212bf/mapIcon.jpg 768w,\n/static/5ccce65251da4bb1a1f35ff984c1e005/b4708/mapIcon.jpg 862w\"\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, we can move on to deploy this web page on Netlify.</p>\n<h2 id=\"deploying-on-netlify\" style=\"position:relative;\"><a href=\"#deploying-on-netlify\" aria-label=\"deploying on netlify permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Deploying on Netlify</h2>\n<p>Netlify is an awesome platform to host your web applications. It also offers many other features such as serverless functions.</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: 27.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsTAAALEwEAmpwYAAABLUlEQVQY02PQ276TQW3/DnXVAzv2aO7d4a2zfTuDUGkuI4+4HAOfnCoG5pVVZQXSmkBsB8SiQGwLxPYweQbTjbv0DbbuvKy7Y+c6vR075xut324iERDKwKeooQRUkAbE1kAsBsSxQGwFxLOAOBuIy4HYA4iXA3EZEEsAsSWD1erdc8w27Ooz3bBrncW63ZutVu488f//fwYeSfk4Pnm1RqCiBiCeCsTzgbgJikOBuAWIM4G4GogjgXgmENcwOC7do+a4ZO8k++V7Ltsv27PTbtH2cEkbNwagYfFABb68cqq5QLoNaijIeyBLMqAGJgFxKVAND9Sl/gwui/YyuCzc6+k+f+9WtwV73ZxWH2LgEBYHGSjIK6siCA0nDqh3QRqVgVgJKi4CxMJQNsgiIQDlLWLLlKj/mwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Netlify Logo\"\n        title=\"Netlify Logo\"\n        src=\"/static/e84c164819279717e4fb312b9fe77c0d/e5715/netlify.png\"\n        srcset=\"/static/e84c164819279717e4fb312b9fe77c0d/a6d36/netlify.png 650w,\n/static/e84c164819279717e4fb312b9fe77c0d/e5715/netlify.png 768w,\n/static/e84c164819279717e4fb312b9fe77c0d/de766/netlify.png 1838w\"\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>Once you have pushed your web page to a Git repository, hosted either on GitHub, GitLab or BitBucket, navigate to <a href=\"https://app.netlify.com\">Netlify</a> and click on the <strong>New Site from Git</strong> button.</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: 49.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGxrXTINcP/xAAcEAABAwUAAAAAAAAAAAAAAAABAgMEABARFDL/2gAIAQEAAQUCEJrGkzSoCSUc2//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABwQAAEDBQAAAAAAAAAAAAAAAAEAApERICEiMf/aAAgBAQAGPwLNZXDK1cRZ/8QAGxABAAICAwAAAAAAAAAAAAAAAQARECFBUfH/2gAIAQEAAT8hrQpObbnv5ri9JcS7Of/aAAwDAQACAAMAAAAQn+//xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPxBH/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8QV//EABoQAQACAwEAAAAAAAAAAAAAAAEAESFBcRD/2gAIAQEAAT8QMCwEl1WuTNAIokrY9uAFFtyvv//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Starting with Netlify\"\n        title=\"Starting with Netlify\"\n        src=\"/static/c559273491c4d34132300434e70915f4/212bf/netlifySigningUp.jpg\"\n        srcset=\"/static/c559273491c4d34132300434e70915f4/6aca1/netlifySigningUp.jpg 650w,\n/static/c559273491c4d34132300434e70915f4/212bf/netlifySigningUp.jpg 768w,\n/static/c559273491c4d34132300434e70915f4/b768e/netlifySigningUp.jpg 1350w\"\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>Next, select your Git provider and your repository:</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: 49.38461538461538%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAUCBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGjvrJKVR//xAAaEAACAgMAAAAAAAAAAAAAAAACAwEEABAU/9oACAEBAAEFAoqqgeZONpCRb//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAAEEAwAAAAAAAAAAAAAAAAEAAhFREiAz/9oACAEBAAY/AhLATa5hS04io0//xAAZEAEBAQADAAAAAAAAAAAAAAABEQAgMfH/2gAIAQEAAT8hLgxFHe8fDhSkcH//2gAMAwEAAgADAAAAEJc//8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EFf/xAAaEAEAAgMBAAAAAAAAAAAAAAABACEQETHR/9oACAEBAAE/ED3gsC13sH9UDgjZC7b7C8M//9k='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Git Provider Selection\"\n        title=\"Git Provider Selection\"\n        src=\"/static/23319b5804aac00e1709fde9795f5885/212bf/gitRepo.jpg\"\n        srcset=\"/static/23319b5804aac00e1709fde9795f5885/6aca1/gitRepo.jpg 650w,\n/static/23319b5804aac00e1709fde9795f5885/212bf/gitRepo.jpg 768w,\n/static/23319b5804aac00e1709fde9795f5885/b768e/gitRepo.jpg 1350w\"\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><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: 49.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAUCBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAGjvrJKVR//xAAaEAACAgMAAAAAAAAAAAAAAAACAwAEARAU/9oACAEBAAEFAhqqwPMmNpCRb//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABsQAQACAgMAAAAAAAAAAAAAAAEAAhFREiAz/9oACAEBAAY/AgaC7nmTNXgax0//xAAaEAEAAwADAAAAAAAAAAAAAAABABARITHx/9oACAEBAAE/IQ4YxR3PHg7hGYoV/9oADAMBAAIAAwAAABCEP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/EIj/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAgEBPxBX/8QAGhABAAMAAwAAAAAAAAAAAAAAAQAhMRFBUf/aAAgBAQABPxAVQLC/dh3RDxA2QvLexwmI7P/Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Git Respository Selection\"\n        title=\"Git Respository Selection\"\n        src=\"/static/d4dbe7837e1b43f9dd5158612b0d6d68/212bf/repoSelection.jpg\"\n        srcset=\"/static/d4dbe7837e1b43f9dd5158612b0d6d68/6aca1/repoSelection.jpg 650w,\n/static/d4dbe7837e1b43f9dd5158612b0d6d68/212bf/repoSelection.jpg 768w,\n/static/d4dbe7837e1b43f9dd5158612b0d6d68/4d731/repoSelection.jpg 1352w\"\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>Go ahead with the defaults, and now your site shall be published on Netlify, and all future pushes should result in a Netlify deployment:</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: 49.23076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAUDBP/EABUBAQEAAAAAAAAAAAAAAAAAAAAB/9oADAMBAAIQAxAAAAHsxrkirY//xAAcEAABAwUAAAAAAAAAAAAAAAAAAQIEAxARFUH/2gAIAQEAAQUCSFSw6A1TXnbf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAHBAAAQMFAAAAAAAAAAAAAAAAAQACIREgM4Gh/9oACAEBAAY/ApBO1DqLJyz/xAAcEAEAAgEFAAAAAAAAAAAAAAABABEhEDFBcYH/2gAIAQEAAT8hIBIMuFxi283O3S4YbT//2gAMAwEAAgADAAAAEL8v/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQMBAT8QiP/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EKr/xAAfEAEAAgEDBQAAAAAAAAAAAAABABExECFRcYGhweH/2gAIAQEAAT8QLWQFWc1cFj63M/dYF9v1L8dLB0n/2Q=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Netlify Deployment\"\n        title=\"Netlify Deployment\"\n        src=\"/static/fc33a74bb6777dce83785da6282226f1/212bf/deployment.jpg\"\n        srcset=\"/static/fc33a74bb6777dce83785da6282226f1/6aca1/deployment.jpg 650w,\n/static/fc33a74bb6777dce83785da6282226f1/212bf/deployment.jpg 768w,\n/static/fc33a74bb6777dce83785da6282226f1/de520/deployment.jpg 1345w\"\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>Nice! Now we have a web map, even though a very basic one, live! Check out the <a href=\"https://leafletjs.com/reference.html\">Leaflet documentation</a> for more!</p>\n<h2 id=\"source-code\" style=\"position:relative;\"><a href=\"#source-code\" aria-label=\"source 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>Source Code</h2>\n<p>Demonstration: <a href=\"https://priceless-poincare-9647e3.netlify.app/\">Priceless Poincare</a></p>\n<p>GitHub: <a href=\"https://github.com/sudiptog81/leaflet-netlify-starter\">leaflet netlify starter</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\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  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"October 14, 2020","updated_date":null,"description":"Let's visualize geospatial data on the web using Leaflet and host it on Netlify!","title":"Visualizing Data using Leaflet and Netlify","tags":["GIS","Serverless","JavaScript"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":2.0618556701030926,"src":"/static/2bf4fa98946c3aaa9aff33c4859f3bda/14b42/map.jpg","srcSet":"/static/2bf4fa98946c3aaa9aff33c4859f3bda/f836f/map.jpg 200w,\n/static/2bf4fa98946c3aaa9aff33c4859f3bda/2244e/map.jpg 400w,\n/static/2bf4fa98946c3aaa9aff33c4859f3bda/14b42/map.jpg 800w,\n/static/2bf4fa98946c3aaa9aff33c4859f3bda/47498/map.jpg 1200w,\n/static/2bf4fa98946c3aaa9aff33c4859f3bda/1abfa/map.jpg 1366w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Sudipto Ghosh","github":"sudiptog81","avatar":null}}}},{"node":{"excerpt":"Introduction The Secure Enclave is a hardware-based key manager that’s isolated from the main processor to provide an extra layer of…","fields":{"slug":"/engineering/secure-enclave-ios-app/"},"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>The Secure Enclave is a hardware-based key manager that’s isolated from the main processor to provide an extra layer of security. Using a secure enclave, we can create the key, securely store the key, and perform operations with the key. Thus makes it difficult for the key to be compromised. </p>\n<p>We usually save data persistently in the app using UserDefaults, Keychain, Core Data or SQLite.\nFor example, To save the session of logged in user, we save username and password. But this process puts our data at high-security risk. So it's always recommended to store sensitive data in an encrypted format. But again, it's a challenge to secure keys used in encryption/decryption.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 395px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 32.151898734177216%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAGABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIE/8QAFgEBAQEAAAAAAAAAAAAAAAAAAgEE/9oADAMBAAIQAxAAAAHUNYsC/wD/xAAZEAEAAgMAAAAAAAAAAAAAAAACABQBBBH/2gAIAQEAAQUCtntsw7OFP//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAEDAQE/Aar/xAAXEQADAQAAAAAAAAAAAAAAAAAAAQIT/9oACAECAQE/Ac5HEn//xAAXEAADAQAAAAAAAAAAAAAAAAAAATIx/9oACAEBAAY/ApZLMZ//xAAaEAACAgMAAAAAAAAAAAAAAAAAARGhITFh/9oACAEBAAE/IVMWnpBm0TSqz//aAAwDAQACAAMAAAAQeC//xAAWEQEBAQAAAAAAAAAAAAAAAAAAARH/2gAIAQMBAT8Q0lP/xAAYEQADAQEAAAAAAAAAAAAAAAAAARFhsf/aAAgBAgEBPxDPok5D/8QAGxABAAICAwAAAAAAAAAAAAAAAQARIUFRcdH/2gAIAQEAAT8QyVPIalFTHSLyAay+J//Z'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Secure Enclave\"\n        title=\"Secure Enclave\"\n        src=\"/static/31be728f50457b650ee4c74aa92f1974/8473b/image2.jpg\"\n        srcset=\"/static/31be728f50457b650ee4c74aa92f1974/8473b/image2.jpg 395w\"\n        sizes=\"(max-width: 395px) 100vw, 395px\"\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 here <strong>Secure Enclave</strong> comes in the role. </p>\n<p>In this blog, we will use Secure Enclave to generate key pair and use those in encryption/decryption of sensitive data further.</p>\n<p>Here I will create a wrapper to generate key pair using Secure Enclave and use them to encrypt/decrypt sensitive data. And also a viewcontroller to show how to use a wrapper to get encrypted and decrypted data.\nYou may implement wrapper's methods as common methods and use wherever needed in the project. But its recommended to use a separate wrapper for handling communication with Secure Enclave.</p>\n<h2 id=\"wrapper\" style=\"position:relative;\"><a href=\"#wrapper\" aria-label=\"wrapper permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Wrapper</h2>\n<p> I have created .h and .m files named as SecEnclaveWrapper as a subclass of NSObject.\nIn .h file I am declaring function for being accessible from other classes like: </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return encrypted value of data using kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM algo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)encryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)data ;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return decryrpted data of encrypted data  using kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM algo</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)decryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *_Nonnull)data ;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Return an initialized instance of the wrapper</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">instancetype</span><span class=\"mtk1\">)init;</span></span></code></pre>\n<p>Then in .m file, define the following methods as : </p>\n<p>The method <code>init</code> initializes and returns the object of this wrapper class. And 'encryptData' and 'decryptData' method return encrypted data and decrypted data of encrypted data, respectively.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">instancetype</span><span class=\"mtk1\">)init {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    self = [super init];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(![self lookupPublicKeyRef] || ![self lookupPrivateKeyRef])</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        [self generatePasscodeKeyPair];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> self;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)encryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)data {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (data && </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        CFDataRef cipher = </span><span class=\"mtk11\">SecKeyCreateEncryptedData</span><span class=\"mtk1\">(publicKeyRef, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)data, </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)cipher;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    } </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</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>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\">*)decryptData:(</span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)data {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(data && </span><span class=\"mtk12\">data</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        CFDataRef plainData = </span><span class=\"mtk11\">SecKeyCreateDecryptedData</span><span class=\"mtk1\">(privateKeyRef, kSecKeyAlgorithmECIESEncryptionStandardX963SHA256AESGCM, (CFDataRef)data, </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\">  (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)plainData;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">else</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The 'lookupPublicKeyRef' method below will lookup keychain for public key &#x26; 'lookupPrivateKeyRef' method search for the private key and return key if found.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (SecKeyRef) lookupPublicKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> sanityCheck = noErr;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *tag;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">id</span><span class=\"mtk1\"> keyClass;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (publicKeyRef != </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk3\">// if already resides in memory, return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    tag = [kPublicKeyName dataUsingEncoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    keyClass = (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClassPublic;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSDictionary</span><span class=\"mtk1\"> *queryDict = @{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClass : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClassKey,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyType : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyTypeEC,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrApplicationTag : tag,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClass : keyClass,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecReturnRef : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">//else look key in keychain and return</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    sanityCheck = </span><span class=\"mtk11\">SecItemCopyMatching</span><span class=\"mtk1\">((__bridge CFDictionaryRef) queryDict, (CFTypeRef *) &publicKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (sanityCheck != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)sanityCheck);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">- (SecKeyRef) lookupPrivateKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef getPrivateKeyRef = newCFDict;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecClass, kSecClassKey);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecAttrKeyClass, kSecAttrKeyClassPrivate);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecAttrLabel, kPrivateKeyName);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionarySetValue</span><span class=\"mtk1\">(getPrivateKeyRef, kSecReturnRef, kCFBooleanTrue);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> status = </span><span class=\"mtk11\">SecItemCopyMatching</span><span class=\"mtk1\">(getPrivateKeyRef, (CFTypeRef *)&privateKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (status == errSecItemNotFound)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">nil</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> (SecKeyRef)privateKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The following methods will actually deal with Secure Enclave to generate a private key and public key.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) generatePasscodeKeyPair</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFErrorRef error = </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    SecAccessControlRef sacObject = </span><span class=\"mtk11\">SecAccessControlCreateWithFlags</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kCFAllocatorDefault,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    kSecAccessControlPrivateKeyUsage,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    &error</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">                                                                    );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (error != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Generating key pair, error: %@</span><span class=\"mtk6\">\\n</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">, error);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> [self generateKeyPairWithAccessControlObject:sacObject];</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\">bool</span><span class=\"mtk1\">) generateKeyPairWithAccessControlObject:(SecAccessControlRef)accessControlRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// create dictionary of private key </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef accessControlDict = newCFDict;;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#if</span><span class=\"mtk4\"> </span><span class=\"mtk1\">!</span><span class=\"mtk11\">TARGET_IPHONE_SIMULATOR</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrAccessControl, accessControlRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#endif</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrIsPermanent, kCFBooleanTrue);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(accessControlDict, kSecAttrLabel, kPrivateKeyName);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk3\">// create dictionary for saving key into keychain</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    CFMutableDictionaryRef generatePairRef = newCFDict;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#if</span><span class=\"mtk4\"> </span><span class=\"mtk1\">!</span><span class=\"mtk11\">TARGET_IPHONE_SIMULATOR</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#endif</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrKeyType, kSecAttrKeyTypeEC);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecAttrKeySizeInBits, (__bridge </span><span class=\"mtk4\">const</span><span class=\"mtk1\"> </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *)([</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithInt:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">]));</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">CFDictionaryAddValue</span><span class=\"mtk1\">(generatePairRef, kSecPrivateKeyAttrs, accessControlDict);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> status = </span><span class=\"mtk11\">SecKeyGeneratePair</span><span class=\"mtk1\">(generatePairRef, &publicKeyRef, &privateKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (status != errSecSuccess){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)status);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">NO</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [self savePublicKeyFromRef:publicKeyRef];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">YES</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The private key is generated and stored in Secure Enclave which cannot be directly used. Whereas public key have to be stored manually in keychain by following method.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">bool</span><span class=\"mtk1\">) savePublicKeyFromRef:(SecKeyRef)publicKeyRef</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{   </span><span class=\"mtk10\">OSStatus</span><span class=\"mtk1\"> sanityCheck = noErr;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *tag;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">id</span><span class=\"mtk1\"> keyClass;</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\">    tag = [kPublicKeyName dataUsingEncoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    keyClass = (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClassPublic;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSDictionary</span><span class=\"mtk1\"> *saveDict = @{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClass : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecClassKey,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyType : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyTypeEC,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrApplicationTag : tag,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeyClass : keyClass,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecValueData : (__bridge </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *)</span><span class=\"mtk11\">SecKeyCopyExternalRepresentation</span><span class=\"mtk1\">(publicKeyRef,</span><span class=\"mtk4\">nil</span><span class=\"mtk1\">),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrKeySizeInBits : [</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithUnsignedInteger:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrEffectiveKeySize : [</span><span class=\"mtk10\">NSNumber</span><span class=\"mtk1\"> numberWithUnsignedInteger:</span><span class=\"mtk7\">256</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanDerive : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanEncrypt : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanDecrypt : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanVerify : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanSign : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanWrap : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanTrue,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kSecAttrCanUnwrap : (__bridge </span><span class=\"mtk4\">id</span><span class=\"mtk1\">) kCFBooleanFalse</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    };</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    sanityCheck = </span><span class=\"mtk11\">SecItemAdd</span><span class=\"mtk1\">((__bridge CFDictionaryRef) saveDict, (CFTypeRef *)&publicKeyRef);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (sanityCheck != errSecSuccess) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;Error trying to retrieve key from server.  sanityCheck: %d&quot;</span><span class=\"mtk1\">, (</span><span class=\"mtk4\">int</span><span class=\"mtk1\">)sanityCheck);</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>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> publicKeyRef;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"demo\" style=\"position:relative;\"><a href=\"#demo\" aria-label=\"demo permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Demo</h2>\n<p>Now I am creating ViewController.h and .m files. In viewDidLoad in .m file, having a string to be stored in UserDefaults. I will encrypt this string by a private key generated above and then store persistently encrypted data for later use.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"objective-c\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">- (</span><span class=\"mtk4\">void</span><span class=\"mtk1\">)viewDidLoad {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    [super viewDidLoad];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strDatatosave = </span><span class=\"mtk8\">@&quot;example data to save&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *bundleIdentifier = [[</span><span class=\"mtk10\">NSBundle</span><span class=\"mtk1\"> mainBundle] bundleIdentifier];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strGroupID = [</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> stringWithFormat:</span><span class=\"mtk8\">@&quot;group.%@&quot;</span><span class=\"mtk1\">,bundleIdentifier];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    SecEnclaveWrapper *keychainItem = [[SecEnclaveWrapper alloc] init];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *encrypted = [keychainItem encryptData:[strDatatosave dataUsingEncoding:NSUTF8StringEncoding]];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strEncrypted = [[</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> alloc] initWithData:encrypted encoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;encrypted string %@&quot;</span><span class=\"mtk1\">,strEncrypted);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSData</span><span class=\"mtk1\"> *decrypted =[keychainItem decryptData:encrypted];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> *strDecrypted = [[</span><span class=\"mtk10\">NSString</span><span class=\"mtk1\"> alloc] initWithData:decrypted encoding:NSUTF8StringEncoding];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk11\">NSLog</span><span class=\"mtk1\">(</span><span class=\"mtk8\">@&quot;decrypted string as real string%@&quot;</span><span class=\"mtk1\">,strDecrypted);</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>In this blog, we learned about the basics of key generation via Secure Enclave and encryption and decryption using keys.\nBy default, key-pairs are generated in the Secure Enclave. The private key is available only at creation time and can not be obtained later as it is saved in Secure Enclave. Operations can be performed with it without exposing it to user code. Only Public Key will be stored and retrieved.</p>\n<p>You can find the complete repository link <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/iOS/SecureEnclave/SecureEnclaveDemo\">here</a></p>\n<p>Thanks for reading the blog. For detailed information and execution example of this blog, please refer to the video below:</p>\n<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/c_1E_NV4NBk\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>\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 .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"October 13, 2020","updated_date":null,"description":"SecureEnclaveDemo is an xcode project containing helper named as SecEnclaveWrapper. You can use this wrapper in your project to encrypt/decrypt sensitive data using Secure Enclave. Let's understand more about in the blog.","title":"Secure Enclave in iOS App","tags":["ios","security","data","encryption","private key","xcode"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/69f1d98b07ca23af682918f3250280ff/14b42/CoverImage.jpg","srcSet":"/static/69f1d98b07ca23af682918f3250280ff/f836f/CoverImage.jpg 200w,\n/static/69f1d98b07ca23af682918f3250280ff/2244e/CoverImage.jpg 400w,\n/static/69f1d98b07ca23af682918f3250280ff/14b42/CoverImage.jpg 800w,\n/static/69f1d98b07ca23af682918f3250280ff/9842e/CoverImage.jpg 900w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Tanvi Jain","github":"tanvijn","avatar":null}}}},{"node":{"excerpt":"What is STL? STL stands for Standard Template Library. If you've used C++ even in small projects, you've likely already used STL - which is…","fields":{"slug":"/engineering/cpp-stl-containers/"},"html":"<h2 id=\"what-is-stl\" style=\"position:relative;\"><a href=\"#what-is-stl\" aria-label=\"what is stl permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is STL?</h2>\n<p>STL stands for Standard Template Library. If you've used C++ even in small projects, you've likely already used STL - which is a great thing! Using STL in C++ makes your code more expressive, simple, and easy to understand. This post will give you an overview of how STL works, some examples, and the basic knowledge you need to get started!</p>\n<h2 id=\"stl-components\" style=\"position:relative;\"><a href=\"#stl-components\" aria-label=\"stl 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>STL Components</h2>\n<p>Loosely speaking, the first components you'd typically understand and use of STL are Containers &#x26; Algorithms. Then there's also Iterators &#x26; Functors, but you should try to take them on one by one, in that order perhaps. This blog will expand a bit on STL Containers.</p>\n<h3 id=\"containers\" style=\"position:relative;\"><a href=\"#containers\" aria-label=\"containers permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Containers</h3>\n<p>Suppose you are at your favorite cinema hall and it's the launch of a big movie. Since it's the launch, there are likely many people waiting in line to buy their tickets. Naturally, you join the queue at the back and wait for your turn. In the computing world, we have a queue too! This is a popular data structure. If you've had a Data Structures class before, you are most likely familiar with some other data structures as well. These are often used, so the STL provides a great implementation of all these data structures, otherwise known as containers.</p>\n<p>Take arrays, for example. Arrays are elements with the same type, stored in contiguous blocks of memory. In C++, you can use arrays as you would in C, like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::string </span><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">10</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">] = </span><span class=\"mtk8\">&quot;Adam&quot;</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>But wait, STL provides a container for arrays too. It's available in the header <code>&#x3C;array></code>. Example usage of it would look like this:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">#include</span><span class=\"mtk4\"> </span><span class=\"mtk8\">&lt;iostream&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">#include</span><span class=\"mtk4\"> </span><span class=\"mtk8\">&lt;string&gt;</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">int</span><span class=\"mtk1\"> </span><span class=\"mtk11\">main</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">std</span><span class=\"mtk1\">::array&lt;</span><span class=\"mtk10\">std</span><span class=\"mtk1\">::string, </span><span class=\"mtk7\">10</span><span class=\"mtk1\">&gt; students;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">] = </span><span class=\"mtk8\">&quot;Adam&#39;s Friend&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    cout &lt;&lt; </span><span class=\"mtk12\">students</span><span class=\"mtk1\">[</span><span class=\"mtk7\">0</span><span class=\"mtk1\">] &lt;&lt; endl;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>So, what's the difference? Why should you use the STL Container class? The performance difference is negligible, but what makes the container classes better is that it is a class. A wrapper class around normal arrays, and offers some advantages like passing by values, bounds checking, etc. As a side note, you'd normally want to use an <code>std::vector</code> instead - which is a dynamically resizable array.</p>\n<h4 id=\"other-examples\" style=\"position:relative;\"><a href=\"#other-examples\" aria-label=\"other examples permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 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 examples</h4>\n<p>Other containers in C++ include:</p>\n<ul>\n<li>\n<p>Sequence containers: (accessibility in a sequential manner)</p>\n<ul>\n<li><code>std::array</code></li>\n<li>\n<p><code>std::vector</code>: Dynamically resizable arrays.\nArrays have a set size, while <code>std::vector</code> doesn't. You can keep adding elements in contigious blocks of memory. For example:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::vector&lt;</span><span class=\"mtk10\">std</span><span class=\"mtk1\">::string&gt; students;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">students</span><span class=\"mtk1\">.</span><span class=\"mtk11\">push_back</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Paul&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">students</span><span class=\"mtk1\">.</span><span class=\"mtk11\">push_back</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Jack&quot;</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>Paul &#x26; Jack are stored in contiguous memory blocks, even though we didn't provide a specific limit at the start - as we do with arrays.</p>\n</li>\n<li>\n<p><code>std::forward_list</code>: Singly linked-list.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">A -&gt; B -&gt; C -&gt; D</span></code></pre>\n<p>This is a simple example of linked-lists. Once you're at a point, let's say \"C\" - you can only go forwards.</p>\n</li>\n<li>\n<p><code>std::list</code>: Doubly linked-list.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">A &lt;-&gt; B &lt;-&gt; C &lt;-&gt; D</span></code></pre>\n<p>Above is a simple example of a doubly linked-list. Unlike Singly linked-lists, if you're at \"C\", you can go either way. To \"B\" or \"D\".</p>\n</li>\n<li><code>std::deque</code>: Double-ended queues - insertion and removal possible at both ends.</li>\n</ul>\n</li>\n<li>\n<p>Container Adaptors: (different interface of accessibility from sequence containers)</p>\n<ul>\n<li><code>std::queue</code>: A standard queue, where removals are done from the front, and insertions are done at the end. The queue is a FIFO structure (First in, First out).</li>\n<li><code>std::priority_queue</code>: A queue in which elements can have a varying level of importance. The ones with the highest importance are at the front, and thus processed first.\nFor example, let's say you're at a barbershop. A person arrived after you. If that person would've made a prior appointment to the shop, he would automatically be placed ahead of you with more \"importance\". Priority queues work similarly.</li>\n<li><code>std::stack</code>:\nSuppose you have a pile of 10 books. If you need a book from middle - of course, like most people, you will pull it right from the middle in one go. Let's think about how computers would take this problem. A computer needs a step-by-step instruction, so the first thing it would do is remove the book from the top. And continue to do that until it reaches the book. To keep books as they were again, it would place books one by one at the top of the pile.\nThus, insertions and removals in a stack are only done at the \"top\". </li>\n</ul>\n</li>\n<li>\n<p>Associative containers: (sorted in a specific order, these containers boast search speeds of O(log N))</p>\n<ul>\n<li><code>std::set</code>: Each element inserted into a set is it's own identifier, meaning that unique elements are entered. Each element acts as it's own \"key\" - which uniquely identifies it. For example, suppose you are a volunteer for entering student information for new students entering into the semester. They are uniquely identified by their roll numbers. Suppose you enter the same student's Roll No (the ID) twice into a set, it will be inserted just once - because a \"set\" can only have unique values.</li>\n<li><code>std::multiset</code>: Like a set, but here the same multiple elements are allowed. Entering the roll no from before twice into an <code>std::multiset</code> will result in it being added twice.</li>\n<li><code>std::map</code>: Take a literal map, for example. When you point to a location on the map, it tells you the details. The \"point\" is the key, and the details of that location are the \"values\". The keys are unique, and values can be anything. An <code>std::map</code> works the same way. Perhaps an example will help understanding more about it:</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">// This maps a student name to his marks. But is this correct?</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::map&lt;</span><span class=\"mtk10\">std</span><span class=\"mtk1\">::string, </span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; mapOfStudentNameToMarks;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// The answer is no. A student&#39;s name isn&#39;t necessarily unique, multiple students with the same name will have a clash this way.</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Thus, the correct way would be:</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk10\">std</span><span class=\"mtk1\">::map&lt;</span><span class=\"mtk4\">int</span><span class=\"mtk1\">, </span><span class=\"mtk4\">int</span><span class=\"mtk1\">&gt; mapOfStudentIDToMarks;</span><span class=\"mtk3\"> // This is correct, because StudentIDs are unique!</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">mapOfStudentIDToMarks</span><span class=\"mtk1\">[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">] = </span><span class=\"mtk7\">100</span><span class=\"mtk1\">;</span><span class=\"mtk3\">   // StudentID 1 -&gt; 100 Marks.</span></span></code></pre>\n<ul>\n<li><code>std::multimap</code>: Can you guess what this might do, based on <code>std::multiset</code>?\nMultimap allows multiple elements to have the same key. So, for example, 10 -> 100 &#x26; 10 -> 150 are both valid for a multimap.</li>\n</ul>\n</li>\n<li>\n<p>Unordered Associative containers: (like associative containers, but implemented as hash-tables. They can be accessed at O(1), i.e., constant time.</p>\n<ul>\n<li><code>std::unordered_set</code></li>\n<li><code>std::unordered_multiset</code></li>\n<li><code>std::unordered_map</code></li>\n<li><code>std::unordered_multimap</code>\n-- </li>\n</ul>\n</li>\n</ul>\n<h3 id=\"stl---what-next\" style=\"position:relative;\"><a href=\"#stl---what-next\" aria-label=\"stl   what next permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>STL - What next?</h3>\n<p>Containers aren't the only part of STL. It is huge! You are encouraged to read up more on STL, as it makes your life easier in every manner! You don't need to reinvent the wheel. Next, you could try looking up the various algorithms contained in the STL. They're present in the header file <code>&#x3C;algorithm></code>. Good luck on your journey!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n</style>","frontmatter":{"date":"October 13, 2020","updated_date":null,"description":"Learn how Standard Template Library works in C++ with interactive examples and what you need to get started","title":"STL Containers & Data Structures in C++","tags":["C++","STL"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/827c613a0a1ac4b2c67db9a2e91101b6/14b42/cover.jpg","srcSet":"/static/827c613a0a1ac4b2c67db9a2e91101b6/f836f/cover.jpg 200w,\n/static/827c613a0a1ac4b2c67db9a2e91101b6/2244e/cover.jpg 400w,\n/static/827c613a0a1ac4b2c67db9a2e91101b6/14b42/cover.jpg 800w,\n/static/827c613a0a1ac4b2c67db9a2e91101b6/47498/cover.jpg 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Aryan Rawlani","github":"aryanrawlani28","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":138,"currentPage":24,"type":"//engineering//","numPages":52,"pinned":"17fa0d7b-34c8-51c4-b047-df5e2bbaeedb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}