{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/engineering/49","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"As my previous blog, I use the python web Crawler library to help crawl the static website. For the Scrapy, there can be customize download…","fields":{"slug":"/engineering/write-a-highly-efficient-python-web-crawler/"},"html":"<p>As my previous blog, I use the python web Crawler library to help crawl the static website. For the Scrapy, there can be customize download middle ware, which can deal with static content in the website like JavaScript.</p>\n<p>However, the Scrapy already helps us with much of the underlying implementation, for example, it uses it own dispatcher and it has pipeline for dealing the parsing word after download.  One drawback for using such library is hard to deal with some strange bugs occurring because they run the paralleled jobs.</p>\n<p>For this tutorial, I want to show the structure of a simple and efficient web crawler.</p>\n<p>First of all, we need a scheduler, who can paralleled the job. Because the most of the time is on the requesting.  I use the  <a href=\"http://www.gevent.org/\">gevent</a> to schedule the jobs. Gevent uses the <a href=\"http://libevent.org/\">libevent</a> as its underlying library, which combines the multithreading and event-based techniques to parallel the job.</p>\n<p>There is the sample code:</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=\"mtk15\">import</span><span class=\"mtk1\"> gevent</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> gevent </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> Greenlet</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> gevent </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> monkey</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">from</span><span class=\"mtk1\"> selenium </span><span class=\"mtk15\">import</span><span class=\"mtk1\"> webdriver</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">monkey.patch_socket()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">class</span><span class=\"mtk1\"> </span><span class=\"mtk10\">WebCrawler</span><span class=\"mtk1\">:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">__init__</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">,</span><span class=\"mtk12\">urls</span><span class=\"mtk1\">=[],</span><span class=\"mtk12\">num_worker</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=\"mtk4\">self</span><span class=\"mtk1\">.url_queue = Queue()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.num_worker = num_worker</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">worker</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">,</span><span class=\"mtk12\">pid</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        driver = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.initializeAnImegaDisabledDriver()  </span><span class=\"mtk3\">#initilize the webdirver</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">#</span><span class=\"mtk4\">TODO</span><span class=\"mtk3\"> catch the exception</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">while</span><span class=\"mtk1\"> </span><span class=\"mtk4\">not</span><span class=\"mtk1\"> </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.url_queue.empty():</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            url = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.url_queue.get()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.driver.get(url)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">            elem = </span><span class=\"mtk4\">self</span><span class=\"mtk1\">.driver.find_elements_by_xpath(</span><span class=\"mtk8\">&quot;//script | //iframe | //img&quot;</span><span class=\"mtk1\">) </span><span class=\"mtk3\"># get such element from webpage</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">def</span><span class=\"mtk1\"> </span><span class=\"mtk11\">run</span><span class=\"mtk1\">(</span><span class=\"mtk12\">self</span><span class=\"mtk1\">):</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        jobs = [gevent.spawn(</span><span class=\"mtk4\">self</span><span class=\"mtk1\">.worker,i) </span><span class=\"mtk15\">for</span><span class=\"mtk1\"> i </span><span class=\"mtk4\">in</span><span class=\"mtk1\"> </span><span class=\"mtk12\">xrange</span><span class=\"mtk1\">(</span><span class=\"mtk4\">self</span><span class=\"mtk1\">.num_worker)]</span></span></code></pre>\n<p>The next part is the headless browser part. I use the phantomjs with <code>--webdriver=4444 --disk-cache=true --ignore-ssl-errors=true --load-images=false --max-disk-cache-size=100000</code>. You can get the detailed option from their documents.</p>\n<p>Phantomjs uses selenium webdriver as front-end to handle the request. However phantomjs is using the webkit and QT as its underlying browser and controller. It has memory leak bugs therefore the phantomjs will consume ton of memory and it only can use one core of your CPU but you can deploy many instances of the phantomjs on different ports. I wrote a daemon process to monitor the memory and its situation but later I realize I can use Perl script to get the status of process and when it exceeds the limits like 1G memory and send kill signal to the process.</p>\n<p>To speed up the crawler, I choose to use static browser to verify the website first because the website is bad written, there might be deadlock occurring so just skip them.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n</style>","frontmatter":{"date":"July 14, 2015","updated_date":null,"description":null,"title":"Write a highly efficient python Web Crawler","tags":["Python","Coding"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/c068d4f41cc4f2a33e3bd2737ca105df/7fbdd/python-web-crawler.webp","srcSet":"/static/c068d4f41cc4f2a33e3bd2737ca105df/61e93/python-web-crawler.webp 200w,\n/static/c068d4f41cc4f2a33e3bd2737ca105df/1f5c5/python-web-crawler.webp 400w,\n/static/c068d4f41cc4f2a33e3bd2737ca105df/7fbdd/python-web-crawler.webp 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Mark Duan","github":null,"avatar":null}}}},{"node":{"excerpt":"The  memcached is one of the most popular open source on-memory key-value caching systems. I will briefly talk about the design of memory…","fields":{"slug":"/engineering/memcach-memory-management/"},"html":"<p>The  <a href=\"https://github.com/memcached\">memcached</a> is one of the most popular open source on-memory key-value caching systems. I will briefly talk about the design of memory management of memcached.</p>\n<h3 id=\"chunk-and-slab\" style=\"position:relative;\"><a href=\"#chunk-and-slab\" aria-label=\"chunk and slab permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Chunk and Slab</h3>\n<p><img src=\"/361a88243c7d3be246f1e738d71cc778/memcached1.webp\" alt=\"memcached-1\"></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=\"mtk3\">/* powers-of-N allocation structures */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">typedef</span><span class=\"mtk1\"> </span><span class=\"mtk4\">struct</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">unsigned</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> size;</span><span class=\"mtk3\">      /* sizes of items */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">unsigned</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> perslab;</span><span class=\"mtk3\">   /* how many items per slab */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *slots;</span><span class=\"mtk3\">           /* list of item ptrs */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">unsigned</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> sl_curr;</span><span class=\"mtk3\">   /* total free items in list */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">unsigned</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> slabs;</span><span class=\"mtk3\">     /* how many slabs were allocated for this class */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> **slab_list;</span><span class=\"mtk3\">       /* array of slab pointers */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">unsigned</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> list_size;</span><span class=\"mtk3\"> /* size of prev array */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">unsigned</span><span class=\"mtk1\"> </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> killing;</span><span class=\"mtk3\">  /* index+1 of dying slab, or zero if none */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">size_t</span><span class=\"mtk1\"> requested;</span><span class=\"mtk3\"> /* The number of requested bytes */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">} </span><span class=\"mtk10\">slabclass_t</span><span class=\"mtk1\">;</span></span></code></pre>\n<p>This is the struct declaration of slabclass_t. Each slab class contains the same size of chunk, but different classes have different chunk sizes. The size is calculated by this algorithm:</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=\"mtk1\">&lt;!--</span><span class=\"mtk15\">while</span><span class=\"mtk1\"> (++i &lt; POWER_LARGEST && size </span></span></code></pre>\n<p>The content value factor is defined when memcached memory is deployed with -f, which can change the size between slab classes. For this loop, the size is multiplied by a specified factor. </p>\n<p><img src=\"/af60c92dc1627ea9224338bbf10df1a8/memcached-2.webp\" alt=\"memcached-2\"></p>\n<p>You can get this information by adding -vvv and you can use the command</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=\"mtk1\">stats slabs under telnet connection ip port</span></span></code></pre>\n<p>Every time when a new memory needs to be allocated. It will scan the slab class to find the most suitable class to store the chunk.</p>\n<h3 id=\"rebalance-and-reassign-slab-memory\" style=\"position:relative;\"><a href=\"#rebalance-and-reassign-slab-memory\" aria-label=\"rebalance and reassign slab memory permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Rebalance and reassign slab memory:</h3>\n<p>From memcached’s wiki:</p>\n<p><strong>Overview</strong>: Memcached 1.4.11. Fixes race conditions and crashes introduced in 1.4.10. Adds the ability to rebalance and reassign slab memory.</p>\n<h4 id=\"slab-reassignment\" style=\"position:relative;\"><a href=\"#slab-reassignment\" aria-label=\"slab reassignment permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Slab Reassignment</h4>\n<p>Long running instances of memcached memory may run into an issue where all available memory has been assigned to a specific slab class (say items of roughly size 100 bytes). Later the application starts storing more of its data into a different slab class (items around 200 bytes). Memcached could not use the 100 byte chunks to satisfy the 200 byte requests, and thus you would be able to store very few 200 byte items.</p>\n<p>1.4.11 introduces the ability to reassign slab pages. This is a <strong>beta</strong> feature and the commands may change for the next few releases, so <strong>please</strong> keep this in mind. When the commands are finalized they will be noted in the release notes</p>\n<h4 id=\"slab-automove\" style=\"position:relative;\"><a href=\"#slab-automove\" aria-label=\"slab automove permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Slab Automove</h4>\n<p>While slab reassign is a manual feature, there is also the start of an automatic memory reassignment algorithm.</p>\n<p>From the source code in <a href=\"https://github.com/memcached/memcached/blob/master/slabs.c#L232\">slabs.c</a> we can see, memcached uses two threads to monitor the slabs class, one is to do maintenance and another one is to do the re-balance the class.</p>\n<p>Memcached defines a global variable <em>struct slab\\</em>rebalance slab_rebal,_ which is used to store the start, end information of slab. s_clsid is the source slab id and d_clsid is the destination slab id. The detailed blog in Chinese <a href=\"http://blog.chinaunix.net/uid-27767798-id-3404133.html\">memcached源码分析—–slab automove和slab rebalance</a> could be helpful.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">struct</span><span class=\"mtk1\"> </span><span class=\"mtk10\">slab_rebalance</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *slab_start;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *slab_end;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">void</span><span class=\"mtk1\"> *slab_pos;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> s_clsid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> d_clsid;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">int</span><span class=\"mtk1\"> busy_items;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">uint8_t</span><span class=\"mtk1\"> done;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h3 id=\"memory-pool\" style=\"position:relative;\"><a href=\"#memory-pool\" aria-label=\"memory pool permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Memory Pool</h3>\n<p>Memcached implements its own memory pool, which is used to avoid system memory allocation and memory fragmentation. That will make your memory efficient and easy to manage. Here is a demo implementation of memory pool. Basically it is a large pre-allocated chunk of memory.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"cpp\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\"> mem_avail) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk4\">NULL</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">    /* mem_current pointer _must_ be aligned!!! */</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (size % CHUNK_ALIGN_BYTES) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    }</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    mem_current = ((</span><span class=\"mtk4\">char</span><span class=\"mtk1\">*)mem_current) + size;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\"> (size </span></span></code></pre>\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 .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"July 07, 2015","updated_date":null,"description":null,"title":"Memcached Memory Management","tags":["Memory Management"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/283a834484b5b25cf8471e04a8e2ff1b/7fbdd/memcached-memory-management.webp","srcSet":"/static/283a834484b5b25cf8471e04a8e2ff1b/61e93/memcached-memory-management.webp 200w,\n/static/283a834484b5b25cf8471e04a8e2ff1b/1f5c5/memcached-memory-management.webp 400w,\n/static/283a834484b5b25cf8471e04a8e2ff1b/7fbdd/memcached-memory-management.webp 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Mark Duan","github":null,"avatar":null}}}},{"node":{"excerpt":"HTML 5 is the latest and greatest web technology, although it has some issues in some browsers which don’t have native support for the new…","fields":{"slug":"/engineering/html5-limitation-in-internet-explorer/"},"html":"<p>HTML 5 is the latest and greatest web technology, although it has some issues in some browsers which don’t have native support for the new HTML5 elements. If you want to support some of the older browsers which may still be in use such as IE8 and lower then you are going to have some trouble using HTML5.</p>\n<p>The problem with IE8 and lower versioned IE browsers is that they were created many years ago while HTML5 is new technology and HTML5 tags were newly invented so legacy browsers do not support them. Microsoft will not release any updates for these browsers because they have released new versions of the IE browser.</p>\n<p>As old IE browsers do not know about these tags then it can’t style them so you will find that in IE8 or lower your websites will be rendered without many styles.</p>\n<h4 id=\"how-to-use-html5-in-ie\" style=\"position:relative;\"><a href=\"#how-to-use-html5-in-ie\" aria-label=\"how to use html5 in ie permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to use HTML5 in IE</h4>\n<p>If you want HTML5s new tags to be supported in IE then you need to add some javascript to create the elements:</p>\n<p>Example:</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=\"mtk1\">  </span><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    document.createElement(&#39;header&#39;);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    document.createElement(&#39;article&#39;);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    document.createElement(&#39;aside&#39;);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    document.createElement(&#39;footer&#39;);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">  </span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">script</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>This is not a very good way, you would need to remember all the tags that you have set and include them on every page of your website. If you add any new tags then you need to add these tags on every page of the website as well. Thankfully Remy Sharp provided a solution for this, Remy Sharp has created a Javascript file which he hosts with google code that will handle this for you.</p>\n<p>add the following at the top of your pages and it will include this code file on your website if the end user is using an IE browser lower than version 9.</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=\"mtk1\">&lt;!--[</span><span class=\"mtk12\">if</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lt</span><span class=\"mtk1\"> </span><span class=\"mtk12\">IE</span><span class=\"mtk1\"> </span><span class=\"mtk7\">9</span><span class=\"mtk1\">]&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">script</span><span class=\"mtk1\"> </span><span class=\"mtk12\">src</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;https://html5shim.googlecode.com/svn/trunk/html5.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\">&lt;![</span><span class=\"mtk12\">endif</span><span class=\"mtk1\">]--&gt;</span></span></code></pre>\n<p>IE also does not support some of the most useful new HTML5 methods that are supported by modern browsers:Window.postMessage()</p>\n<p><strong>Window.postMessage</strong></p>\n<p>allows for sending data messages between two windows/frames across domains. Normally, scripts on different pages are allowed to access each other if and only if the pages that executed them are at the same locations with the same protocol (usually both http) and matching host names. The HTML5 postMessage function provides a great way to communicate securely and with high performance and reliability even cross-domain. Unfortunately, the HTML5 postMessage function does not work in IE</p>\n<p>Let’s take a look at how Window.postMessage works:</p>\n<h4 id=\"syntax\" style=\"position:relative;\"><a href=\"#syntax\" aria-label=\"syntax permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Syntax</h4>\n<p>The below signature is used for postMessage:</p>\n<p><strong>otherWindow.postMessage(message, targetOrigin);</strong></p>\n<p><strong>otherWindow</strong>\nA reference to another window; such a reference may be obtained, for example, using the contentWindow property of an iframe element, the object returned by window.open</p>\n<p><strong>message</strong>\nThis parameter is required for a message to be sent to the other window. The message is serialized using the structured clone algorithm. This means you can pass a broad variety of data objects safely to the destination window without having to serialize them yourself.</p>\n<p><strong>targetOrigin</strong>\nWhen the message is dispatched, the current location of the target document is checked. If it does not match the specified URI, then the message will not be dispatched. This parameter can be useful if you want to be sure of the location of the target document before dispatching the message and you can also specify a literal string “*”  (indicating no preference) or as a URI</p>\n<p>but always provide a specific targetOrigin, not *, if you know where the other window’s document should be located. If you do not set a specific location and use “*” then a malicious site can change the location of the window without your knowledge, and therefore it can intercept the data sent using the postMessage method.</p>\n<p><strong>Example for postMessage</strong></p>\n<p><strong>Sender</strong></p>\n<p>The first part of the process is setting up a “source”.  With the source, we will open a new window (or IFrame), send the new window message (in the our example, we’ll do so every 6 seconds, and create an event listener for any response we receive from the destination window.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">//create popup window</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">domain</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;https://www.example.com&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">myPopup</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk11\">open</span><span class=\"mtk1\">(</span><span class=\"mtk12\">domain</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&#39;/postmessage.html&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk8\">&#39;myWindow&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//periodical message sender</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">setInterval</span><span class=\"mtk1\">(</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(){</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">message</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&#39;Hello!  The time is: &#39;</span><span class=\"mtk1\"> + (</span><span class=\"mtk4\">new</span><span class=\"mtk1\"> </span><span class=\"mtk10\">Date</span><span class=\"mtk1\">().</span><span class=\"mtk11\">getTime</span><span class=\"mtk1\">());</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">myPopup</span><span class=\"mtk1\">.</span><span class=\"mtk11\">postMessage</span><span class=\"mtk1\">(</span><span class=\"mtk12\">message</span><span class=\"mtk1\">,</span><span class=\"mtk12\">domain</span><span class=\"mtk1\">); </span><span class=\"mtk3\">//send the message and target URI</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">},</span><span class=\"mtk7\">6000</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//listen to back</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;message&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk12\">origin</span><span class=\"mtk1\"> !== </span><span class=\"mtk8\">&#39;http://scriptandstyle.com&#39;</span><span class=\"mtk1\">) </span><span class=\"mtk15\">return</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;received response:  &#39;</span><span class=\"mtk1\">,</span><span class=\"mtk12\">event</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=\"mtk4\">false</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>I have used window.addEventListener which doesn’t work with Internet Explorer so use window.attachEvent</p>\n<p><strong>Receiver</strong></p>\n<p>In the destination window we should validate the message origin and if it is not valid then we will not send the message to the sender, otherwise we send a response back to the sender:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">window</span><span class=\"mtk1\">.</span><span class=\"mtk11\">addEventListener</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;message&#39;</span><span class=\"mtk1\">,</span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(</span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk12\">origin</span><span class=\"mtk1\"> !== </span><span class=\"mtk8\">&#39;https://lrblogs.wpengine.com) return</span><span class=\"mtk14\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk12\">source</span><span class=\"mtk1\">.</span><span class=\"mtk11\">postMessage</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&#39;message received:  &#39;</span><span class=\"mtk1\">,</span><span class=\"mtk12\">event</span><span class=\"mtk1\">.</span><span class=\"mtk12\">origin</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">},</span><span class=\"mtk4\">false</span><span class=\"mtk1\">);</span></span></code></pre>\n<p><strong>sessionStorage</strong></p>\n<p>sessionStorage stores data for one session only, this is used in a single transaction it stores the data only for one session and as you close the window the session would be lost and  the data is deleted when the browser is closed.</p>\n<p>HTML5 sessionStorage object are shared in different tabs in the same browser session if you change a sessionStorage attribute’s value in one tab, that change should be reflected within another tab but in IE8 this system will not work properly it does not share sessionStorage objects between frames on a page. This issue has since been fixed in IE11.</p>\n<p><strong>Example:</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">//save a value</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">sessionStorage</span><span class=\"mtk1\">.</span><span class=\"mtk11\">setItem</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;website&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;https://www.example.com&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//retrieve item</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">website</span><span class=\"mtk1\">= </span><span class=\"mtk12\">sessionStorage</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getItem</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;website&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//remove the key</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">sessionStorage</span><span class=\"mtk1\">.</span><span class=\"mtk11\">removeItem</span><span class=\"mtk1\">(“</span><span class=\"mtk12\">website</span><span class=\"mtk1\">”);</span></span></code></pre>\n<p><strong>localStorage</strong></p>\n<p>The localStorage object stores the data like a persistent cookie, with no expiration date. The data will not be deleted when the browser is closed, and will be available when a user returns to the browser.</p>\n<p>IE also supports localStorage from IE8 but it does not support localStorage in IE7 and previous versions.</p>\n<p>localStorage Vs Cookies</p>\n<ol>\n<li>Cookies are small text files stored by browsers allowing for a max of 4KB while with localStorage we can store Mbs of localStorage data.</li>\n<li>Cookies are delivered with every request, which can slow down the delivery of your web pages.</li>\n</ol>\n<p><strong>Example</strong></p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">//save a value</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">localStorage</span><span class=\"mtk1\">.</span><span class=\"mtk11\">setItem</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;Domain&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;https://www.example.com&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//retrieve item</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">website</span><span class=\"mtk1\">= </span><span class=\"mtk12\">localStorage</span><span class=\"mtk1\">.</span><span class=\"mtk11\">getItem</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;website&quot;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//remove the key</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">localStorage</span><span class=\"mtk1\">.</span><span class=\"mtk11\">removeItem</span><span class=\"mtk1\">(“</span><span class=\"mtk12\">website</span><span class=\"mtk1\">”);</span></span></code></pre>\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 .mtk17 { color: #808080; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk14 { color: #F44747; }\n</style>","frontmatter":{"date":"June 30, 2015","updated_date":null,"description":null,"title":"HTML5 Limitation in Internet Explorer","tags":["Java","Maven","Eclipse"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/20127eac7a49d6d333dd2483a84b5c4c/7fbdd/radio-check-buttons-css.webp","srcSet":"/static/20127eac7a49d6d333dd2483a84b5c4c/61e93/radio-check-buttons-css.webp 200w,\n/static/20127eac7a49d6d333dd2483a84b5c4c/1f5c5/radio-check-buttons-css.webp 400w,\n/static/20127eac7a49d6d333dd2483a84b5c4c/7fbdd/radio-check-buttons-css.webp 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Team LoginRadius","github":"LoginRadius","avatar":null}}}},{"node":{"excerpt":"An API is an acronym for Application Programming Interface. API's include various tools, protocols, and routines. API's are used as a way…","fields":{"slug":"/engineering/what-is-an-api/"},"html":"<p>An API is an acronym for Application Programming Interface. API's include various tools, protocols, and routines. API's are used as a way for applications to communicate with various systems.</p>\n<p>But what does this mean? Well let me explain what they are with some examples. I am going to be using various API's for these examples.</p>\n<p><strong>Let's Begin</strong></p>\n<p>Let's start by looking at a favorite website of mine called The Yoda Speak Generator found <a href=\"https://lingojam.com/EnglishtoYoda\">here</a>.</p>\n<p>This website allows users to enter text and get a return of that same text formatted the way Yoda might say it. This is done with an API.</p>\n<p>Yoda Speak: Fun stuff, api's are! Yes, hmmm.</p>\n<p>API’s contain what is called an endpoint to access this API. The endpoint provides the connection to communicate with the API and give it some text to generate into Yoda Speak. The API would then return the generated Yoda Speak to the location of the request.</p>\n<p>Another way to think of an API is to think of it like an egg carton. An egg carton holds the eggs, protects them from damage and allows someone who wants to make breakfast a way to open and close the carton to access the eggs inside. The eggs inside would be the data, and the hand reaching into the carton would be much like the communication using an endpoint from a server.</p>\n<p>Okay, Let's make breakfast.... Just Kidding!</p>\n<p>For those of you who are visual Let's look at some examples of the code. These snippets are in PHP because it is my favorite language. Below is a link to download a small zip file called apidemo.zip.</p>\n<p>Demo Link</p>\n<p>You can host this directory on your localhost or on a website if you choose.</p>\n<p>After you have extracted the zip and have a directory such as localhost/apidemo open a browser and enter <code>http://localhost/apidemo/api.php?request=example&#x26;name=yourname</code> where localhost is your domain.</p>\n<p>To enter this endpoint in an application that makes API calls try Postman. Here is a <a href=\"http://www.getpostman.com/\">link</a> for a chrome extension.</p>\n<p>Try using a GET and a POST method with parameters request=example for the example function in api.php and name=yourname to output a name</p>\n<p>You should now see the output \"Your name is yourname\" in your browser</p>\n<p>explore the files api.php, API.class.php and MyAPI.php to explore how this simple API is taking in the parameters and outputting a name</p>\n<p>Hopefully, I have explained API's so you have a basic understanding of what they are. There are many types of API's, one that you may see often is RESTful API's, these unlike this example must abide by constraints that have been defined by the REST architecture.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"June 23, 2015","updated_date":null,"description":null,"title":"What is an API","tags":["API","Postman"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/a01dd1d7515afffa79ea80811d70b895/403a4/whats-an-api-300x300.webp","srcSet":"/static/a01dd1d7515afffa79ea80811d70b895/61e93/whats-an-api-300x300.webp 200w,\n/static/a01dd1d7515afffa79ea80811d70b895/403a4/whats-an-api-300x300.webp 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Zoie Carnegie","github":null,"avatar":null}}}},{"node":{"excerpt":"Let's face it, at some point you look at a radio or a checkbox button and you're like... this looks like something that starts with an \"s…","fields":{"slug":"/engineering/styling-radio-and-check-buttons-with-css/"},"html":"<p>Let's face it, at some point you look at a radio or a checkbox button and you're like... this looks like something that starts with an \"s\" and ends with a \"hit\". I'm here to stop you from saying that word and go on with your life without worrying about those ugly things.</p>\n<p>We're just going to use code here. No images, just pure scalable user interface using code. Cool, eh? Let's get started.</p>\n<p>Let's create our code structure first.</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=\"mtk1\">&lt;!-- </span><span class=\"mtk12\">Radio</span><span class=\"mtk1\"> --&gt; </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">I&#39;m a radio button</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!-- Checkbox --&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">input</span><span class=\"mtk1\"> </span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span><span class=\"mtk1\">I&#39;m a checkbox</span><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">span</span><span class=\"mtk17\">&gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk17\">&lt;/</span><span class=\"mtk4\">label</span><span class=\"mtk17\">&gt;</span></span></code></pre>\n<p>If it looks ugly, don't be alarmed. That's normal for an untamed code from the wild. All you gotta do now is to tame it with our very best tool, CSS.</p>\n<p>First thing you have to do is to hide the element that generates the hideous button, which is... DUN DUN DUN... the input tag. Don't worry, we can still trigger it even though it's hidden. How? by nesting it inside the label tag.</p>\n<p>Now that the default toggles are gone, we need to create our fake —but amazing— toggles.</p>\n<p><strong>Radio Button</strong></p>\n<p>We can't really customize this toggle that much because it needs other toggles to work properly. Let's just prettify it a bit.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">] {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">relative</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inline-block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">25px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">absolute</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">block</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\">18px</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\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#ccc</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">50%</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=\"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\">box-sizing</span><span class=\"mtk1\">: </span><span class=\"mtk8\">border-box</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transition</span><span class=\"mtk1\">: </span><span class=\"mtk8\">all</span><span class=\"mtk1\"> </span><span class=\"mtk7\">300ms</span><span class=\"mtk1\"> </span><span class=\"mtk8\">ease-in-out</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;radio&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p><img src=\"/d36cc3d6f3b8656bc3c213dd8d697e8b/checked-radio.webp\" alt=\"checked-radio\"></p>\n<p><img src=\"/0d8bd0a9dd2fb37571012a6c7fca93aa/unchecked-radio.webp\" alt=\"unchecked-radio\"></p>\n<p>By now it should like this.  </p>\n<p>Cleaner toggles!</p>\n<p><strong>Checkbox</strong></p>\n<p>This one is fun to customize because it has an on and off feature or a switch. Let's start with a simple toggle. We're going to transform this hideous toggle (screenshot) to this beautiful creature (screenshot).</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">; </span><span class=\"mtk3\">/*hides ugly toggle*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">relative</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inline-block</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">25px</span><span class=\"mtk1\">; </span><span class=\"mtk3\">/*adds spacing on the left*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/*create our new toggle*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;</span><span class=\"mtk6\">\\2713</span><span class=\"mtk8\">&quot;</span><span class=\"mtk1\">; </span><span class=\"mtk3\">/*add a new check mark*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">text-align</span><span class=\"mtk1\">: </span><span class=\"mtk8\">center</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">font-size</span><span class=\"mtk1\">: </span><span class=\"mtk7\">13px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">absolute</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">block</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\">18px</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\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#ccc</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">50%</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=\"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\">box-sizing</span><span class=\"mtk1\">: </span><span class=\"mtk8\">border-box</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transition</span><span class=\"mtk1\">: </span><span class=\"mtk8\">all</span><span class=\"mtk1\"> </span><span class=\"mtk7\">500ms</span><span class=\"mtk1\"> </span><span class=\"mtk8\">ease-in-out</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/*if checked do this*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.spin</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transform</span><span class=\"mtk1\">: </span><span class=\"mtk11\">rotatez</span><span class=\"mtk1\">(</span><span class=\"mtk7\">360deg</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-color</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Oh yes! Beautiful toggle.</p>\n<p><img src=\"/3607cca80217d22bad9c57e44caf3756/checked-check.webp\" alt=\"checked-check\"></p>\n<p><img src=\"/84a77f006447163b34d99200a668ffc1/unchecked-checkbox.webp\" alt=\"unchecked-checkbox\"></p>\n<p><strong>Bonus!</strong></p>\n<p>Have you ever seen those toggles where it slides to the left and right when you click it? Did you know you can do that too using CSS? Let's try it.</p>\n<p>First, we're going to design the default look of an unchecked checkbox. By now you know that we need to hide the default toggle.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] { </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">none</span><span class=\"mtk1\">; }</span></span></code></pre>\n<p>And then add a space on the left of the span using padding. While you're there, add a position relative to because we need to contain the rest of the elements inside the span.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span</span><span class=\"mtk1\"> { </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">relative</span><span class=\"mtk1\">; </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inline-block</span><span class=\"mtk1\">; </span><span class=\"mtk12\">padding</span><span class=\"mtk1\">: </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">35px</span><span class=\"mtk1\">; }</span></span></code></pre>\n<p>Now, let's create our toggles using CSS pseudo element :before and :after. Why? Because generated CSS is easier to handle.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\">, </span><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:after</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">content</span><span class=\"mtk1\">: </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">position</span><span class=\"mtk1\">: </span><span class=\"mtk8\">absolute</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">display</span><span class=\"mtk1\">: </span><span class=\"mtk8\">block</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\">18px</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\">18px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#fff</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">margin-right</span><span class=\"mtk1\">: </span><span class=\"mtk7\">5px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border</span><span class=\"mtk1\">: </span><span class=\"mtk7\">1px</span><span class=\"mtk1\"> </span><span class=\"mtk8\">solid</span><span class=\"mtk1\"> </span><span class=\"mtk8\">#ccc</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=\"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\">box-sizing</span><span class=\"mtk1\">: </span><span class=\"mtk8\">border-box</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">transition</span><span class=\"mtk1\">: </span><span class=\"mtk8\">all</span><span class=\"mtk1\"> </span><span class=\"mtk7\">300ms</span><span class=\"mtk1\"> </span><span class=\"mtk8\">ease-in-out</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>This will generate a box looking element. Since it's targeting both pseudo elements, they will look identical and on top of each other.</p>\n<p>It's time to start prettifying those pseudo elements.</p>\n<p>For :after, since this is the background where the :before toggle slides through. We need to modify the width to look bigger. Add an inset shadow to make it look like it's pushed through and a red background for an \"off\" effect.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:before</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\">30px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">20px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk8\">inset</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">5px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-1px</span><span class=\"mtk1\"> </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.4</span><span class=\"mtk1\">), </span><span class=\"mtk8\">inset</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-2px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-1px</span><span class=\"mtk1\"> </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">255</span><span class=\"mtk1\">, </span><span class=\"mtk7\">255</span><span class=\"mtk1\">, </span><span class=\"mtk7\">255</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.2</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#F22613</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>For :before, we just need to make it look like a circle and lift it off a bit using box-shadow.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">] ~ </span><span class=\"mtk6\">span:after</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">box-shadow</span><span class=\"mtk1\">: </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> </span><span class=\"mtk7\">3px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">4px</span><span class=\"mtk1\"> </span><span class=\"mtk7\">-2px</span><span class=\"mtk1\"> </span><span class=\"mtk11\">rgba</span><span class=\"mtk1\">(</span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0</span><span class=\"mtk1\">, </span><span class=\"mtk7\">0.5</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">border-radius</span><span class=\"mtk1\">: </span><span class=\"mtk7\">50%</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The \"on\" part just needs a little bit of pushing to the side and changing the background to blue or green.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"css\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:before</span><span class=\"mtk1\"> {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">background</span><span class=\"mtk1\">: </span><span class=\"mtk8\">#29d</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk6\">label.slide</span><span class=\"mtk1\"> </span><span class=\"mtk6\">input</span><span class=\"mtk1\">[</span><span class=\"mtk12\">type</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;checkbox&quot;</span><span class=\"mtk1\">]</span><span class=\"mtk6\">:checked</span><span class=\"mtk1\"> ~ </span><span class=\"mtk6\">span:after</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\">13px</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>The CSS is a bit longer here because there's a lot of elements that need to change, but take a chill pill because CSS won't slow your page down.</p>\n<p>And that's it. Your pretty checkbox or radio button toggles.</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 .mtk6 { color: #D7BA7D; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n</style>","frontmatter":{"date":"June 16, 2015","updated_date":null,"description":null,"title":"Styling Radio and Check buttons with CSS","tags":["CSS"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/20127eac7a49d6d333dd2483a84b5c4c/7fbdd/radio-check-buttons-css-1.webp","srcSet":"/static/20127eac7a49d6d333dd2483a84b5c4c/61e93/radio-check-buttons-css-1.webp 200w,\n/static/20127eac7a49d6d333dd2483a84b5c4c/1f5c5/radio-check-buttons-css-1.webp 400w,\n/static/20127eac7a49d6d333dd2483a84b5c4c/7fbdd/radio-check-buttons-css-1.webp 610w","sizes":"(max-width: 610px) 100vw, 610px"}}},"author":{"id":"Team LoginRadius","github":"LoginRadius","avatar":null}}}},{"node":{"excerpt":"Social sharing button offers an easy way to distribute your content to a wider audience. The major social providers allow options to…","fields":{"slug":"/engineering/configuring-social-sharing-buttons/"},"html":"<p>Social sharing button offers an easy way to distribute your content to a wider audience. The major social providers allow options to configure the content that will be shared programmatically. In this guide we explore the options that you can use in order to configure the shared content of your social shares including: Message, URL, Image, and Image Caption/Description.</p>\n<p><strong>Facebook</strong></p>\n<p>Facebook utilizes Open Graph Tags which are meta tags that can be included on your page and are scrapped by Facebook when determining the content that should be shared with a specific button. These tags can be included in the head section of your page. All meta tags should be formatted with a property value of \"og:<tag-name>\", some useful tag names are:</p>\n<ul>\n<li>title- The title of your article.</li>\n<li>type- The media content that is included in the shared article. This is defaulted to \"website\".</li>\n<li>image- The image that will be included in the share.</li>\n<li>url- The canonical URL that will be used to identify the share and aggregate the community shares/likes.</li>\n<li>description- A  brief description that is displayed below the image in the share.</li>\n</ul>\n<p>Example of og meta tags that can be included in your html head tag:</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=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>If you are modifying these tags it can take some time for the changes to translate over to Facebook. You can refer to <a href=\"/social-provider-social-sharing-troubleshooting-resources/\">this blog</a> on troubleshooting, testing, and force updating your configured sharing systems.</p>\n<p><strong>Google</strong></p>\n<p>Google offers multiple ways that you can set the shared content which it intelligently determines the most relevant details to be displayed in the share. This works to varying degrees with the following options available and taking precedence respectively:</p>\n<ul>\n<li>Structured Data Markup- HTML markup detailed on <a href=\"http://schema.org/\">Schema</a>.</li>\n<li>Open Graph Tags- Turn your page into a rich data object, commonly used to customize Facebook sharing details. Information on the markup is available on <a href=\"http://ogp.me/\">OGP</a></li>\n<li>Title or Meta Description- HTML attributes that provide details on the site.</li>\n<li>Google’s best guess- If none of the above are included, Google will crawl your page and try to interpret the most suitable details to include in the share.</li>\n</ul>\n<p>Below is an example of basic structured data markup:</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=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span><span class=\"mtk12\">Your</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Site</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Title</span><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">A</span><span class=\"mtk1\"> </span><span class=\"mtk12\">description</span><span class=\"mtk1\"> </span><span class=\"mtk4\">of</span><span class=\"mtk1\"> </span><span class=\"mtk12\">your</span><span class=\"mtk1\"> </span><span class=\"mtk12\">site</span><span class=\"mtk1\">.</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>Below is an example of using basic meta tags to define the shared content:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p><strong>Twitter</strong></p>\n<p>The best way to customize your Twitter shares is to modify the URL query string parameters that gets triggered when the share icon is clicked. Another way is to customize the <code>&#x3C;a></code> tag by including data-attribute tags as detailed on Twitters <a href=\"https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/overview\">Tweet button creation instructions</a> . If you do not have control over the links or triggers that are being used to activate the Tweet popup you can also set Twitter Card meta tags which handle the Twitter customizations.</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=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>Various providers will utilize some of the above methods with open graph tags being one of the most common methods for controlling the shared content. Other systems will customize this content based off of parameters that are passed into the script or URL that is used to trigger the share interface. Getting these to be correctly configured can be a bit of a trial and error process, you can use the resources detailed in <a href=\"/social-provider-social-sharing-troubleshooting-resources/\">this blog post</a> to help test and verify that you have correctly configured your social sharing content.</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 .mtk4 { color: #569CD6; }\n</style>","frontmatter":{"date":"June 09, 2015","updated_date":null,"description":null,"title":"Configuring Your Social Sharing Buttons","tags":["SocialSharing"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/24799a6bff48ea3ac4e96368c579f88b/403a4/configuring-social-share-buttons-300x300.webp","srcSet":"/static/24799a6bff48ea3ac4e96368c579f88b/61e93/configuring-social-share-buttons-300x300.webp 200w,\n/static/24799a6bff48ea3ac4e96368c579f88b/403a4/configuring-social-share-buttons-300x300.webp 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}}]},"markdownRemark":{"excerpt":"Introduction Ever wondered how apps like Spotify, Netflix, or Slack manage seamless login experiences across devices? Many of them use JWT…","fields":{"slug":"/engineering/how-to-integrate-jwt/"},"html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>Ever wondered how apps like Spotify, Netflix, or Slack manage seamless login experiences across devices? Many of them use JWT, or JSON Web Tokens, a compact, stateless method for securely transmitting user identity and session data across services.</p>\n<p>With JWT token authentication, identity information is embedded in a signed token, allowing you to maintain user sessions without server-side storage. This approach is highly scalable and ideal for modern architectures like SPAs, mobile apps, and microservices.</p>\n<p>In this blog, we’ll walk you through what is JWT, why use it, and how to implement JWT authentication using LoginRadius. </p>\n<p>You’ll learn what JWT is, why it’s effective, and how it works in real-world applications. We'll cover both integration methods (IDX and Direct API), generating your signing key, managing sessions, storing the JWT token securely, and applying best practices throughout.</p>\n<p>Whether you're a developer, product manager, or IAM architect, this guide offers a complete foundation for implementing JWT token authentication into your application stack.</p>\n<h2 id=\"what-is-jwt\" style=\"position:relative;\"><a href=\"#what-is-jwt\" aria-label=\"what is jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is JWT?</h2>\n<p><a href=\"https://www.loginradius.com/blog/engineering/jwt/\">JSON Web Token (JWT)</a> is an open standard (RFC 7519) used to transmit information securely between parties as a JSON object. It’s compact, self-contained, and digitally signed, making it a reliable format for authentication and authorization across modern applications.</p>\n<p>A JWT consists of three parts:</p>\n<ol>\n<li><strong>Header –</strong> Contains metadata like the type of token and signing algorithm (e.g., HS256).</li>\n<li><strong>Payload –</strong> Stores the actual data or “claims,” such as user ID, roles, and token expiry.</li>\n<li><strong>Signature –</strong> A cryptographic hash that ensures the token hasn’t been tampered with.</li>\n</ol>\n<p><em>Example of a token structure:</em></p>\n<p>&#x3C;base64Header>.&#x3C;base64Payload>.&#x3C;signature></p>\n<h2 id=\"why-use-jwt\" style=\"position:relative;\"><a href=\"#why-use-jwt\" aria-label=\"why use jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Use JWT?</h2>\n<ul>\n<li><strong>Stateless Authentication</strong>: No server-side session storage is needed — the token holds all necessary user info. </li>\n<li><strong>Portable</strong>: Works seamlessly across domains, services, and APIs. </li>\n<li><strong>Scalable</strong>: Ideal for microservices, SPAs, mobile apps, and serverless functions. </li>\n<li><strong>Interoperable</strong>: JWTs are supported across many languages and frameworks.</li>\n</ul>\n<h2 id=\"how-jwt-works\" style=\"position:relative;\"><a href=\"#how-jwt-works\" aria-label=\"how jwt works permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How JWT Works?</h2>\n<p><img src=\"/f29edbf2978577390c7ffa02e9bc4dda/lr-JWT-authentication.webp\" alt=\"Flowchart illustrating LoginRadius JWT authentication via Identity Provider (IDP), showing user redirection from login icon to login page, authentication with IDP, JWT token validation, and subsequent redirection to the customer&#x27;s website or error page based on validation results.\"></p>\n<ol>\n<li>A user logs in with credentials. </li>\n<li>Your app (or identity provider like LoginRadius) issues a signed JWT. </li>\n<li>The client stores the token and sends it with each request (usually in the Authorization header). </li>\n<li>The server validates the token’s signature and claims. </li>\n<li>If valid, access is granted — without any session stored on the backend.</li>\n</ol>\n<p>JWT simplifies identity verification, especially when you're building apps that talk to APIs or need to scale without centralized session storage.</p>\n<h2 id=\"jwt-authentication-with-loginradius-overview\" style=\"position:relative;\"><a href=\"#jwt-authentication-with-loginradius-overview\" aria-label=\"jwt authentication with loginradius overview permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>JWT Authentication with LoginRadius: Overview</h2>\n<p>LoginRadius provides robust support for JWT (JSON Web Token) authentication, which allows for flexible and secure access control across different digital platforms. Whether you're building a fully custom identity flow or using a pre-built interface, the platform supports various integration approaches depending on your architecture.</p>\n<p>If you're looking to understand how to implement JWT token authentication effectively, LoginRadius offers two primary implementation models that cater to different levels of customization and control:</p>\n<h3 id=\"1-idx-implementation--jwt-through-a-hosted-login-page\" style=\"position:relative;\"><a href=\"#1-idx-implementation--jwt-through-a-hosted-login-page\" aria-label=\"1 idx implementation  jwt through a hosted login page permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. IDX Implementation – JWT through a Hosted Login Page</h3>\n<p>The IDX-hosted login approach enables secure, standards-compliant, JWT-based authentication without requiring you to build a custom login interface. This is a strategic option for fast, compliant, and user-friendly deployments.</p>\n<ul>\n<li>The Identity Experience Framework (IDX) comes with a fully custom branded hosted login page.</li>\n<li>Once the user logs in and gets enrolled, the user’s JWTs are automatically generated and issued. These tokens can be utilized for managing user sessions and accessing the APIs.</li>\n<li>This approach simplifies deployment without compromising on user experience and security standards.</li>\n</ul>\n<h3 id=\"configuration-steps\" style=\"position:relative;\"><a href=\"#configuration-steps\" aria-label=\"configuration steps permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Configuration Steps:</strong></h3>\n<ol>\n<li>Enable JWT Login</li>\n<li>Go to <a href=\"https://console.loginradius.com/authentication/authentication-configuration\">authentication configuration settings</a> and enable JWT Login in the Admin Console.</li>\n</ol>\n<p><img src=\"/9fb19dd9c88c7916aeebd03ab6e661b7/lr-admin-console.webp\" alt=\"Screenshot of LoginRadius Admin Console showing JWT Custom IDP configuration interface with options for provider name, algorithm (HS256), key entry, clock skew, and expiration time settings.\"></p>\n<ol start=\"2\">\n<li>Specify your signing algorithm and expiry policy, and define your JWT Secret Key.</li>\n<li>Input a secure JWT signing key.</li>\n<li>Specify token expiry duration (e.g., 15–60 minutes)</li>\n<li>Select the desired algorithm —HS256 for symmetric signing (same key signs and verifies)</li>\n<li>RS256 for asymmetric signing, where LoginRadius securely stores the private key used to sign the JWT.</li>\n<li>Your app or backend service uses the public key to validate the token signature.</li>\n<li>LoginRadius provides a JWKS (JSON Web Key Set) endpoint to dynamically fetch and rotate public keys, ensuring trust without key exposure.</li>\n<li>Update IDX Template for Callback</li>\n<li>Modify your IDX login page template to retrieve the JWT post-login. You can access the token via redirect URL parameters or secure JavaScript callbacks.</li>\n</ol>\n<h3 id=\"example-response\" style=\"position:relative;\"><a href=\"#example-response\" aria-label=\"example response permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example Response:</h3>\n<p>{</p>\n<p>  \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR...\",</p>\n<p>  \"expires_in\": 1800</p>\n<p>}</p>\n<p>This integration approach works best for all teams that want effective identity workflows without the complexity of building proprietary login screens, something that is crucial for customer portals, onboarding of mobile applications, and even managing access for business partners.</p>\n<h3 id=\"2-direct-api-implementation--self-managed-login\" style=\"position:relative;\"><a href=\"#2-direct-api-implementation--self-managed-login\" aria-label=\"2 direct api implementation  self managed login permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. Direct API Implementation – Self Managed Login</h3>\n<p>If you’re building a custom login UI or working in a headless environment, LoginRadius lets you generate and handle JWTs directly through its <a href=\"https://www.loginradius.com/docs/api/v2/customer-identity-api/\">Authentication APIs</a>. Here’s how you can programmatically perform token authentication using the classic method:</p>\n<ul>\n<li>For custom front-end applications, LR offers an API to authenticate users and issue JWT tokens.</li>\n<li>In response to the login request, the developers are provided with signed tokens that can be validated on the client’s side or by downstream services.</li>\n<li>This method is best fit for enterprise applications that have complex custom workflows or are designed to be embedded into other applications.</li>\n</ul>\n<h3 id=\"configuration-steps-1\" style=\"position:relative;\"><a href=\"#configuration-steps-1\" aria-label=\"configuration steps 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><strong>Configuration Steps:</strong></h3>\n<h4 id=\"step-1-authenticate-via-api\" style=\"position:relative;\"><a href=\"#step-1-authenticate-via-api\" aria-label=\"step 1 authenticate via api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1: Authenticate via API:</h4>\n<ul>\n<li>\n<p>Send a POST login request to the LR Authentication URL: </p>\n<p>POST /identity/v2/auth/login</p>\n</li>\n</ul>\n<p>Include the user’s credentials (email + password) in the request body.</p>\n<h4 id=\"step-2-get-jwt-in-response\" style=\"position:relative;\"><a href=\"#step-2-get-jwt-in-response\" aria-label=\"step 2 get jwt in response permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2: Get JWT in Response</h4>\n<ul>\n<li>If the user credentials are authentic, then the JWT token will be available in response.</li>\n</ul>\n<p>{</p>\n<p> \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",</p>\n<p> \"expires_in\": 3600</p>\n<p>}</p>\n<h4 id=\"step-3-jwt-decoding-and-validation\" style=\"position:relative;\"><a href=\"#step-3-jwt-decoding-and-validation\" aria-label=\"step 3 jwt decoding and validation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3: JWT Decoding and Validation</h4>\n<ul>\n<li>Use any JWT library (e.g., jsonwebtoken for Node.js or pyjwt for Python) to decode the token.</li>\n<li>Validate the signature using your configured secret key.</li>\n<li>Confirm claims like exp, iat, aud, and iss.</li>\n</ul>\n<h4 id=\"step-4-set-custom-claims-optional\" style=\"position:relative;\"><a href=\"#step-4-set-custom-claims-optional\" aria-label=\"step 4 set custom claims optional permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Set Custom Claims (Optional)</h4>\n<p>With LoginRadius, it is possible to customize the payload to include user roles and/or any additional metadata. You can set custom JWT claims on the Admin Console.</p>\n<p>With this method, you have complete customization over login flows while using LoginRadius to issue signed JWTs for user session management.</p>\n<p><strong>NOTE-</strong> With either method, LoginRadius ensures that JWTs are securely signed, optionally short-lived, and compatible with standard token validation libraries, making integration seamless for everyone.</p>\n<p>To get started with JWT implementation, you can<a href=\"https://www.loginradius.com/docs/single-sign-on/federated-sso/jwt-login/jwt-implementation-guide/\"> read our complete developer documentation</a>. </p>\n<h2 id=\"hosted-login-vs-direct-api\" style=\"position:relative;\"><a href=\"#hosted-login-vs-direct-api\" aria-label=\"hosted login vs direct api permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Hosted Login vs Direct API</h2>\n<p><img src=\"/15ec02ac98d24a9f1f28e5d0f06b9174/IDX-vs-Direct-API-JWT.webp\" alt=\"Illustration showing IDX vs Direct API JWT flow diagram comparing LoginRadius JWT authentication methods via Hosted Login Page (IDX) and Custom Login UI using Direct API, illustrating user login, JWT issuance, and token return process.\"></p>\n<h2 id=\"what-is-session-management-and-how-it-works-with-jwt\" style=\"position:relative;\"><a href=\"#what-is-session-management-and-how-it-works-with-jwt\" aria-label=\"what is session management and how it works with jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is Session Management and How It Works with JWT</h2>\n<p><a href=\"https://www.loginradius.com/blog/identity/user-session-management/\">Session management </a>is how your app keeps track of a user after they log in so they don’t have to prove who they are with every request.</p>\n<p>In traditional apps, sessions are stored on the server using session IDs. Every time a request comes in, the server checks that session ID to verify the user.</p>\n<p>In modern apps, especially SPAs and APIs, JWTs are used to manage sessions without needing server-side storage; this is called stateless session management. The token itself carries the user’s identity, roles, and expiration details. As long as the token is valid, the user stays logged in.</p>\n<p>Good session management ensures:</p>\n<ul>\n<li>Security against session hijacking</li>\n<li>Fast user validation without hitting a database</li>\n<li>Smooth experiences with token refresh strategies</li>\n</ul>\n<h2 id=\"how-loginradius-handles-session-management-with-jwt\" style=\"position:relative;\"><a href=\"#how-loginradius-handles-session-management-with-jwt\" aria-label=\"how loginradius handles session management with jwt permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How LoginRadius Handles Session Management with JWT:</h2>\n<ol>\n<li>\n<p>User Logs In </p>\n<ul>\n<li>LoginRadius returns an access token (JWT) and, optionally, a refresh token.</li>\n</ul>\n</li>\n<li>\n<p>Client Stores the Token </p>\n<ul>\n<li>Access tokens are stored in memory, sessionStorage, or secure cookies. </li>\n<li>They’re sent on every request via the Authorization: Bearer header. </li>\n</ul>\n</li>\n<li>\n<p>Access Token Expiry </p>\n<ul>\n<li>These tokens are short-lived by design (e.g., 15–30 minutes). </li>\n<li>Once expired, the client can use the refresh token to request a new access token. </li>\n</ul>\n</li>\n<li>\n<p>Token Renewal </p>\n<ul>\n<li>LoginRadius validates the refresh token and issues a new JWT, i.e., no user re-authentication is needed. </li>\n<li>Refresh tokens can be revoked at any time.</li>\n</ul>\n</li>\n<li>Logout and Token Revocation Strategy</li>\n</ol>\n<p>When the user logs out, both the access token and refresh token should be cleared from client storage.</p>\n<ul>\n<li>The refresh token can be explicitly revoked via the LoginRadius API, terminating the ability to renew sessions. </li>\n<li>\n<p>However, access tokens are stateless and cannot be revoked mid-lifecycle unless: </p>\n<ul>\n<li>You maintain a blacklist of token IDs (jti claims) and check them on each request. </li>\n<li>You use short-lived access tokens to limit exposure naturally. </li>\n<li>Or, you rotate your JWT signing key, invalidating all previously issued tokens. </li>\n</ul>\n</li>\n</ul>\n<p>Combining these strategies gives you greater control over token misuse and enables a robust, enterprise-grade logout flow. </p>\n<p><a href=\"https://www.loginradius.com/resource/whitepaper/secure-api-using-oauth2\"><img src=\"/e55ae4bbc8ce62e13f03e46e29ebe7cc/api-economy.webp\" alt=\"illustration showing LoginRadius free downloadable resource named API economy is transforming digitization: how to secure it using oauth 2.0.\"></a></p>\n<h2 id=\"how-to-store-jwt-tokens\" style=\"position:relative;\"><a href=\"#how-to-store-jwt-tokens\" aria-label=\"how to store jwt tokens permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to Store JWT Tokens?</h2>\n<p>When you implement JWT-based authentication, the client (browser or mobile app) needs a way to store the access token and, optionally, the refresh token after they are issued by the authentication server. This stored token is then attached to every subsequent request to prove the user's identity.</p>\n<p>Choosing where to store the JWT is a crucial security decision. The most common storage options are:</p>\n<ul>\n<li>localStorage</li>\n<li>sessionStorage</li>\n<li>HTTP-only cookies</li>\n</ul>\n<p>Each option has trade-offs between security, accessibility, and persistence, and the right choice depends on your application's architecture and threat model.</p>\n<h4 id=\"recommended-storage-strategy\" style=\"position:relative;\"><a href=\"#recommended-storage-strategy\" aria-label=\"recommended storage strategy permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Recommended Storage Strategy</h4>\n<ul>\n<li>\n<p>Access Tokens </p>\n<ul>\n<li>For SPAs: store in memory or sessionStorage for short-term access </li>\n<li>If stored in the browser, protect against XSS </li>\n</ul>\n</li>\n<li>\n<p>Refresh Tokens</p>\n<ul>\n<li>Always store the JWT refresh token in HTTP-only secure cookies to prevent JavaScript access. This adds a critical layer of protection against XSS attacks.</li>\n<li>Combine with SameSite=Strict or SameSite=Lax attributes to mitigate CSRF risks and ensure the JWT refresh token is only sent in intended contexts.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"best-practices-for-storing-jwts\" style=\"position:relative;\"><a href=\"#best-practices-for-storing-jwts\" aria-label=\"best practices for storing jwts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Best Practices for Storing JWTs</h2>\n<ol>\n<li>Never store sensitive tokens (like refresh tokens) in localStorage or sessionStorage.</li>\n<li>Use Secure and HttpOnly flags with cookies to prevent JavaScript access and ensure transmission only over HTTPS.</li>\n<li>Set the SameSite=Strict or Lax attribute on cookies to protect against CSRF.</li>\n<li>Use short-lived access tokens and rotate refresh tokens regularly.</li>\n<li>Implement CSP (Content Security Policy) to reduce XSS risk.</li>\n<li>Avoid storing any tokens in frontend code (e.g., hardcoded in JS files).</li>\n</ol>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>JWT authentication with LoginRadius offers a modern, stateless approach to managing sessions across distributed systems. The IDX integration is ideal for rapid deployment, while the Direct API model is best for organizations needing deep customization and integration flexibility.</p>\n<p>With robust token signing, refresh capabilities, and centralized control, LoginRadius provides a future-ready foundation for secure, scalable identity architecture. <a href=\"https://www.loginradius.com/contact-us?utm_source=blog&#x26;utm_medium=web&#x26;utm_campaign=how-to-integrate-jwt\">Contact us</a> to know more about JWT authentication and implementation guide. </p>\n<h2 id=\"faqs\" style=\"position:relative;\"><a href=\"#faqs\" aria-label=\"faqs permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>FAQs</h2>\n<h3 id=\"1-what-is-jwt-authentication-used-for\" style=\"position:relative;\"><a href=\"#1-what-is-jwt-authentication-used-for\" aria-label=\"1 what is jwt authentication used for permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>1. What is JWT authentication used for?</h3>\n<p><strong>A:</strong> JWT authentication securely verifies user identities, enabling stateless session management across web, mobile apps, and microservices without server-side session storage.</p>\n<h3 id=\"2-how-does-loginradius-simplify-jwt-integration\" style=\"position:relative;\"><a href=\"#2-how-does-loginradius-simplify-jwt-integration\" aria-label=\"2 how does loginradius simplify jwt integration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>2. How does LoginRadius simplify JWT integration?</h3>\n<p><strong>A:</strong> LoginRadius simplifies JWT integration by offering hosted <a href=\"https://www.loginradius.com/docs/single-sign-on/federated-sso/jwt-login/jwt-implementation-guide/\">IDX login pages </a>and direct API-based authentication methods, enabling rapid deployment and deep customization.</p>\n<h3 id=\"3-is-jwt-authentication-secure\" style=\"position:relative;\"><a href=\"#3-is-jwt-authentication-secure\" aria-label=\"3 is jwt authentication secure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>3. Is JWT authentication secure?</h3>\n<p><strong>A:</strong> Yes, JWT authentication is secure when implemented with best practices like short-lived tokens, secure storage methods, signature validation, and refresh token rotation.</p>\n<h3 id=\"4-can-jwt-tokens-be-revoked-with-loginradius\" style=\"position:relative;\"><a href=\"#4-can-jwt-tokens-be-revoked-with-loginradius\" aria-label=\"4 can jwt tokens be revoked with loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>4. Can JWT tokens be revoked with LoginRadius?</h3>\n<p><strong>A:</strong> Yes, LoginRadius allows<a href=\"https://www.loginradius.com/docs/api/v2/customer-identity-api/refresh-token/revoke-refresh-token/?q=revoke+jwt\"> revocation of JWT</a> refresh tokens explicitly, and supports strategies like short-lived tokens and key rotation to manage token lifecycles securely.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"April 15, 2025","updated_date":null,"description":"Discover JWT (JSON Web Token) authentication, its advantages, and how to integrate it seamlessly using LoginRadius' hosted IDX and Direct API methods for secure, scalable identity management.","title":"JWT Authentication with LoginRadius: Quick Integration Guide","tags":["JWT","JSON Web Token","Authentication","Authorization"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":0.7782101167315175,"src":"/static/4cedb7829f98208cbc6d5a9aea4e983d/58556/how-to-integrate-jwt.webp","srcSet":"/static/4cedb7829f98208cbc6d5a9aea4e983d/61e93/how-to-integrate-jwt.webp 200w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/1f5c5/how-to-integrate-jwt.webp 400w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/58556/how-to-integrate-jwt.webp 800w,\n/static/4cedb7829f98208cbc6d5a9aea4e983d/1cc9f/how-to-integrate-jwt.webp 896w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Kundan Singh","github":null,"avatar":null}}}},"pageContext":{"limit":6,"skip":288,"currentPage":49,"type":"//engineering//","numPages":53,"pinned":"5c425581-f474-5ae9-abe7-cf5342db2aaa"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}