<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gourav Khunger</title>
    <description>The latest articles on Forem by Gourav Khunger (@gouravkhunger).</description>
    <link>https://forem.com/gouravkhunger</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F506492%2Fc648bd50-a073-45d2-8b57-451d281921de.png</url>
      <title>Forem: Gourav Khunger</title>
      <link>https://forem.com/gouravkhunger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gouravkhunger"/>
    <language>en</language>
    <item>
      <title>That's my first project in golang. It's fully open source, do check out!</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Thu, 05 Jun 2025 08:54:56 +0000</pubDate>
      <link>https://forem.com/gouravkhunger/thats-my-first-project-in-golang-its-fully-open-source-do-check-out-1di0</link>
      <guid>https://forem.com/gouravkhunger/thats-my-first-project-in-golang-its-fully-open-source-do-check-out-1di0</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn" class="crayons-story__hidden-navigation-link"&gt;Showcase Your GitHub Repository’s Users in the README [&amp;lt; 5 Mins]&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/gouravkhunger" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F506492%2Fc648bd50-a073-45d2-8b57-451d281921de.png" alt="gouravkhunger profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/gouravkhunger" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Gourav Khunger
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Gourav Khunger
                
              
              &lt;div id="story-author-preview-content-2565109" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/gouravkhunger" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F506492%2Fc648bd50-a073-45d2-8b57-451d281921de.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Gourav Khunger&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 5 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn" id="article-link-2565109"&gt;
          Showcase Your GitHub Repository’s Users in the README [&amp;lt; 5 Mins]
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/github"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;github&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/go"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;go&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>opensource</category>
      <category>github</category>
      <category>go</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Showcase Your GitHub Repository’s Users in the README [&lt; 5 Mins]</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Thu, 05 Jun 2025 08:52:58 +0000</pubDate>
      <link>https://forem.com/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn</link>
      <guid>https://forem.com/gouravkhunger/showcase-your-github-repositorys-users-in-the-readme-5-mins-16cn</guid>
      <description>&lt;p&gt;If you’ve ever published a library on GitHub, you’ve probably noticed that GitHub shows a nice sidebar section on some repositories — &lt;strong&gt;"Used by X repositories"&lt;/strong&gt; — giving your project social proof and discoverability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhshsui1xn89wfijc8lc.png" class="article-body-image-wrapper"&gt;&lt;img alt="GitHub used by section" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhshsui1xn89wfijc8lc.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, this info is only visible if &lt;strong&gt;100+ repositories&lt;/strong&gt; depend on your project.&lt;/p&gt;

&lt;p&gt;That sucks because I maintain several open source libraries like &lt;a href="https://github.com/gouravkhunger/jekyll-auto-authors" rel="noopener noreferrer"&gt;jekyll-auto-authors&lt;/a&gt; that have dozens of real users and I'd love to showcase that information despite the thresholds.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://dependents.info" rel="noopener noreferrer"&gt;dependents.info&lt;/a&gt; — a simple tool that shows your network dependents right inside your README!&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch a quick demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/icdxdppB6AA"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The idea is simple: &lt;a href="https://dependents.info" rel="noopener noreferrer"&gt;dependents.info&lt;/a&gt; is a GitHub Action written in TypeScript + a Go based API that together generate a SVG image showing which repositories depend on your package.&lt;/p&gt;

&lt;p&gt;Just like &lt;a href="https://contrib.rocks" rel="noopener noreferrer"&gt;contrib.rocks&lt;/a&gt;, but for &lt;strong&gt;network dependents&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The tech stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Action&lt;/strong&gt; in TypeScript: Crawls your repository’s network dependents and sends them to the backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API&lt;/strong&gt; in Go (Fiber): Authenticates using GitHub OIDC to verify requests, stores data, and generates a minimal SVG image with avatars and names of top users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Works for &lt;strong&gt;any public GitHub repository&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Secure: uses GitHub’s built-in &lt;strong&gt;OIDC&lt;/strong&gt; to verify authenticity.&lt;/li&gt;
&lt;li&gt;Shows top 10 dependent repos (sorted by stars).&lt;/li&gt;
&lt;li&gt;Live SVG badge, embeddable in any README.&lt;/li&gt;
&lt;li&gt;Supports a lot of configurations.&lt;/li&gt;
&lt;li&gt;Robust caching and rate-limit friendly.&lt;/li&gt;
&lt;li&gt;Minimal setup: just a few lines in a &lt;code&gt;.yml&lt;/code&gt; GitHub workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add a GitHub Action to your repository:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add this simple workflow file to your repository's &lt;code&gt;.github/workflows&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dependents.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dependents Action&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dependents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gouravkhunger/dependents.info@main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Copy the following code snippet below and replace &lt;code&gt;owner/repo&lt;/code&gt; with your repository's name. paste it wherever you want to embed the image.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://github.com/owner/repo/network/dependents"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://dependents.info/owner/repo/image.svg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;

Made with [dependents.info](https://dependents.info).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As soon as you push these changes, you'll see the image inserted automatically!&lt;/p&gt;
&lt;h2&gt;
  
  
  See It Live
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Website: &lt;a href="https://dependents.info" rel="noopener noreferrer"&gt;https://dependents.info&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GitHub:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gouravkhunger" rel="noopener noreferrer"&gt;
        gouravkhunger
      &lt;/a&gt; / &lt;a href="https://github.com/gouravkhunger/dependents.info" rel="noopener noreferrer"&gt;
        dependents.info
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      easily generate an image of github network dependents to showcase in your project's readme
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;dependents.info&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://dependents.info" rel="nofollow noopener noreferrer"&gt;&lt;br&gt;
  &lt;img alt="dependents.info logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgouravkhunger%2Fdependents.info%2Frefs%2Fheads%2Fmain%2Fwww%2Fpublic%2Fimages%2Flogo.webp" width="125px"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dependents.info/sitemap.xml" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/87e2e445b737c750dbf2ca21a089735a44044a3d4c6a3fb1a8dec24d3a25f786/68747470733a2f2f646570656e64656e74732e696e666f2f676f757261766b68756e6765722f646570656e64656e74732e696e666f2f7573657273" alt="dependents.info users count"&gt;&lt;/a&gt;
&lt;a href="https://dependents.info/gouravkhunger/dependents.info" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fd1b5b65850428f26c05332742382bead1fbf2b88d49334211d9de5c864992f5/68747470733a2f2f646570656e64656e74732e696e666f2f676f757261766b68756e6765722f646570656e64656e74732e696e666f2f6261646765" alt="GitHub Network Dependents Count for gouravkhunger/dependents.info"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;easily generate an image of github network dependents to showcase in your project's &lt;code&gt;readme.md&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;simply use the embed codes, or optionally add a github action for customizations, in your repository.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;demo&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;here's a demo of the generated image for the gem &lt;a href="https://github.com/gouravkhunger/jekyll-auto-authors" rel="noopener noreferrer"&gt;&lt;code&gt;jekyll-auto-authors&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dependents.info/gouravkhunger/jekyll-auto-authors" rel="nofollow noopener noreferrer"&gt;&lt;br&gt;
  &lt;img src="https://camo.githubusercontent.com/1f03344d4c99be3b1b863222499ead3329b5372794599345434c763b426bf75a/68747470733a2f2f646570656e64656e74732e696e666f2f676f757261766b68756e6765722f6a656b796c6c2d6175746f2d617574686f72732f696d616765"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;quickstart&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;embed image&lt;/h3&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;: to customize the frequency of image re-generation, please setup the &lt;a href="https://github.com/gouravkhunger/dependents.info#github-action" rel="noopener noreferrer"&gt;github action&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;copy the following code snippet and &lt;strong&gt;replace &lt;code&gt;owner/repo&lt;/code&gt;&lt;/strong&gt; with your repository's name. paste it wherever you want to embed the image.&lt;/p&gt;

&lt;div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;a&lt;/span&gt; &lt;span class="pl-c1"&gt;href&lt;/span&gt;="&lt;span class="pl-s"&gt;https://dependents.info/owner/repo&lt;/span&gt;"&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;img&lt;/span&gt; &lt;span class="pl-c1"&gt;src&lt;/span&gt;="&lt;span class="pl-s"&gt;https://dependents.info/owner/repo/image&lt;/span&gt;" &lt;span class="pl-kos"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;a&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;if your repository hosts multiple packages each with it's own tracked dependents, use this:&lt;/p&gt;
&lt;div class="highlight highlight-text-html-basic notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;a&lt;/span&gt; &lt;span class="pl-c1"&gt;href&lt;/span&gt;="&lt;span class="pl-s"&gt;https://dependents.info/owner/repo?id=idHere&lt;/span&gt;"&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-ent"&gt;img&lt;/span&gt; &lt;span class="pl-c1"&gt;src&lt;/span&gt;="&lt;span class="pl-s"&gt;https://dependents.info/owner/repo/image?id=idHere&lt;/span&gt;" &lt;span class="pl-kos"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="pl-kos"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="pl-ent"&gt;a&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;by default, the image is generated from the first few dependents. use the &lt;a href="https://github.com/gouravkhunger/dependents.info#github-action" rel="noopener noreferrer"&gt;github action&lt;/a&gt; to control this…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gouravkhunger/dependents.info" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Got ideas or feature requests? Drop them on the repo — contributions and feedback are super welcome.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hope this project helps bring visibility to your packages, no matter how big or small!&lt;/p&gt;

&lt;p&gt;Happy coding :)&lt;/p&gt;

&lt;p&gt;— &lt;a href="https://gourav.sh" rel="noopener noreferrer"&gt;Gourav&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>go</category>
      <category>typescript</category>
    </item>
    <item>
      <title>9 Hand Picked FREE Heroku Alternatives [2023]</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Thu, 06 Jul 2023 10:18:59 +0000</pubDate>
      <link>https://forem.com/genicsblog/9-hand-picked-free-heroku-alternatives-2023-123e</link>
      <guid>https://forem.com/genicsblog/9-hand-picked-free-heroku-alternatives-2023-123e</guid>
      <description>&lt;p&gt;Beginning November 28, 2022, Heroku, one of the most popular go to choice used by developers to host their apps, announced that it would be shutting down its free tier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Listen to the audio version of this article at &lt;a href="https://genicsblog.com/gouravkhunger/9-hand-picked-free-heroku-alternative-hosting-platforms" rel="noopener noreferrer"&gt;genicsblog.com&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Platform-as-a-Service (PaaS) provider's free tier used to provide a generous 550 hours of dyno uptime which could be easily extended to 1000 hours with a verified credit card.&lt;/p&gt;

&lt;p&gt;Even though these dynos shut down after 30 minutes, it could be resolved by various methods to &lt;a href="https://genicsblog.com/gouravkhunger/8-ways-to-keep-your-heroku-app-awake" rel="noopener noreferrer"&gt;keep Heroku apps awake&lt;/a&gt;, thus becoming the easiest way to host software projects for free.&lt;/p&gt;

&lt;p&gt;The free tier shutdown news left many developers in search for alternative hosting platforms that could provide a similar API and website hosting services free of cost. As a result, I have compiled a list of the top 9 free Heroku alternatives to use in 2023.&lt;/p&gt;

&lt;p&gt;If you are interested in watching a video format of this article, check this out:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/XOcrXqvTyOI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;While there are many hosting platforms available in the market, these carefully selected services provide the best options for developers to host their Frontend/Backend applications, APIs, Servers, etc.&lt;/p&gt;

&lt;p&gt;These alternatives offer features similar to Heroku, such as support for multiple programming languages, easy deployment, and scalability. So whether you are a seasoned developer or just getting started, keep reading to discover the top free Heroku alternative hosting platforms:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Deta
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://deta.space" rel="noopener noreferrer"&gt;Deta space&lt;/a&gt; is a relatively new comer to the market but their offerings make them top our list. You can host both static and dynamic content within minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftowldklhxy7jbalaintd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftowldklhxy7jbalaintd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether it be building frontend or backend applications with any technology, Deta has got you covered with their infrastructure they call as the "Personal Cloud".&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No credit card verification required.&lt;/li&gt;
&lt;li&gt;Easy project deployments through their CLI application.&lt;/li&gt;
&lt;li&gt;No limits on the number of builds / deployments.&lt;/li&gt;
&lt;li&gt;Support for any kind of technology/framework to build your application.&lt;/li&gt;
&lt;li&gt;Free hosting for Node.js / Rust / Go / Custom backend apps as well as SvelteKit / Next / Static Apps.&lt;/li&gt;
&lt;li&gt;Free application uptime throughout the month.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;p&gt;The pros far outweigh the cons of Deta making it the best choice for developers to host their projects and applications and move away from Heroku.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying on Deta requires initial project configuration and setup changes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://deta.space/terms#113-hard-and-soft-limits" rel="noopener noreferrer"&gt;Resource usage limits&lt;/a&gt; are generous but may not be sufficient for everyone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. GitHub Pages
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pages.github.com" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; is a free web hosting service provided by GitHub. You can easily create and host static websites served directly from your project's GitHub repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahpfwplzc9qb1gaepng3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahpfwplzc9qb1gaepng3.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It offers a simple and efficient way to serve static websites built with HTML, CSS, and JavaScript.&lt;/p&gt;

&lt;p&gt;It also supports popular website generators such as Jekyll, Hugo, Gatsby, etc. You can also use custom &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt; to create your own publishing pipeline in a matter of minutes.&lt;/p&gt;

&lt;p&gt;GitHub Pages provides support for custom domains, HTTPS encryption, and easy integration with other GitHub features such as Git version control and issue tracking all for free!&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free web hosting for static websites.&lt;/li&gt;
&lt;li&gt;Easy integration with other GitHub features.&lt;/li&gt;
&lt;li&gt;Support for popular static site generators.&lt;/li&gt;
&lt;li&gt;Simple and intuitive user interface for creating and managing websites.&lt;/li&gt;
&lt;li&gt;Ability to collaborate with other developers on the same repository and website.&lt;/li&gt;
&lt;li&gt;Good performance and reliability due to GitHub's infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No support for dynamic websites or web applications.&lt;/li&gt;
&lt;li&gt;No support for server-side scripting or database integration.&lt;/li&gt;
&lt;li&gt;1 GB storage and 100 GB monthly bandwidth soft limit on the free tier.&lt;/li&gt;
&lt;li&gt;Not suitable for websites that require higher levels of security or scalability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This service is perfect for those who want to showcase their side projects, blogs, or portfolios without the need for complex infrastructure or hosting setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Oracle
&lt;/h2&gt;

&lt;p&gt;Oracle Cloud's &lt;a href="https://www.oracle.com/cloud/free/" rel="noopener noreferrer"&gt;free tier&lt;/a&gt; has been a game changer recently. The &lt;a href="https://www.oracle.com/cloud/free/#always-free" rel="noopener noreferrer"&gt;Always Free&lt;/a&gt; services provide unmatched resources for developers to build and deploy their apps, without worrying for usage limits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2qags8fxbn1pgapo0vx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2qags8fxbn1pgapo0vx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reliable services from Oracle.&lt;/li&gt;
&lt;li&gt;Host any kind of applications.&lt;/li&gt;
&lt;li&gt;VMs stay up indefinitely — No fret about downtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Requires credit card verification to begin usage.&lt;/li&gt;
&lt;li&gt;Platform complexity makes it not so easy to use.&lt;/li&gt;
&lt;li&gt;Manual configurations required for deployment.&lt;/li&gt;
&lt;li&gt;Overkill for small / medium projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Cloudflare Pages
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pages.cloudflare.com" rel="noopener noreferrer"&gt;Cloudflare Pages&lt;/a&gt; is a part of the numerous services provided by Cloudflare for building and deploying static websites, APIs, and applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F325jvji6uf5m23c49wmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F325jvji6uf5m23c49wmo.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It provides a simple way for developers to create high-performance websites that are scalable, secure, and easily integrated with other Cloudflare services.&lt;/p&gt;

&lt;p&gt;Whether you are building a personal blog or a complex web application, Cloudflare Pages offers a range of features and benefits that make it a great choice for web development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free web hosting for static and dynamic websites, including unlimited bandwidth and custom domain support.&lt;/li&gt;
&lt;li&gt;Full stack support with serverless functions using Cloudflare Workers.&lt;/li&gt;
&lt;li&gt;Unlimited preview deployments for your projects!&lt;/li&gt;
&lt;li&gt;Support for redirects and headers for files.&lt;/li&gt;
&lt;li&gt;Automatic SSL encryption and security features, including DDoS protection and firewall rules.&lt;/li&gt;
&lt;li&gt;Easy integration with popular Git-based version control systems like GitHub, GitLab, and Bitbucket.&lt;/li&gt;
&lt;li&gt;Support for popular web frameworks like React, Next.js, Vue.js, Angular, etc.&lt;/li&gt;
&lt;li&gt;Fast and reliable global content delivery network (CDN) powered by Cloudflare's infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;500 builds per month hard limit.&lt;/li&gt;
&lt;li&gt;A maximum of 20,000 files per deployment where each file should be less than 25 MiB.&lt;/li&gt;
&lt;li&gt;Complexity for developers who are not familiar with serverless architecture or the Cloudflare ecosystem.&lt;/li&gt;
&lt;li&gt;No built-in database support, although these can be integrated with third-party services.&lt;/li&gt;
&lt;li&gt;Limited support for legacy web technologies or platforms that are not Git-based.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This service is the most suited for those who already use Cloudflare services with their existing websites and are looking to migrate to a different hosting platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Vercel
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; is a cloud-based platform that provides users with the most modern UI/UX to deploy their websites and applications within minutes. It is focused on providing an easy-to-use solution for building and deploying websites and applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidaizzf7ud0ueuat7uu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidaizzf7ud0ueuat7uu5.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has become a popular choice among developers who are looking for a platform that can offer serverless deployment, scalability, and performance. With Vercel, developers can easily deploy their code and enjoy fast loading speeds, excellent scalability, and reliability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Best for Next.js powered projects.&lt;/li&gt;
&lt;li&gt;Easy to use dashboard built for fast deployments.&lt;/li&gt;
&lt;li&gt;Automatic serverless deployment and scaling using its cloud infrastructure and CDN.&lt;/li&gt;
&lt;li&gt;Easy for developers to handle traffic spikes and scaling needs.&lt;/li&gt;
&lt;li&gt;Extensive library of plugins and support for integrations, and add-ons.&lt;/li&gt;
&lt;li&gt;Excellent documentation and community support.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vercel.com/guides/can-vercel-sponsor-my-open-source-project" rel="noopener noreferrer"&gt;Vercel Sponsorships&lt;/a&gt; for open-source projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vercel's free plan has &lt;a href="https://vercel.com/docs/concepts/limits/overview" rel="noopener noreferrer"&gt;various limitations&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Although it supports popular web frameworks like Next.js and Nuxt.js, it is not the best choice if you require more flexibility and control over your stack.&lt;/li&gt;
&lt;li&gt;It is a cloud-based platform, which means that developers do not have complete control over the underlying infrastructure and environment.&lt;/li&gt;
&lt;li&gt;Vercel's recently launched &lt;a href="https://vercel.com/blog/vercel-storage" rel="noopener noreferrer"&gt;serverless storage solutions&lt;/a&gt; are relatively new.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Railway
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://railway.app" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; is like a copy of Heroku but with slight differences. The platform's UX is top notch, and their pricing and restrictions are good enough to make it a viable Heroku alternative.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6yimfit4qat7we2forrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6yimfit4qat7we2forrq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Platform experience is very similar to Heroku with the UI being very modern.&lt;/li&gt;
&lt;li&gt;Deploy any kind of API / website tech stack.&lt;/li&gt;
&lt;li&gt;Great documentation to get started with.&lt;/li&gt;
&lt;li&gt;Easy integration with GitHub to deploy your repository.&lt;/li&gt;
&lt;li&gt;All plans include preview environments for each PR, Multiple custom domains with SSL, deploy from any GitHub repository, etc.&lt;/li&gt;
&lt;li&gt;Built-in database integrations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limited resources without credit card verification. Once verified, it is generous enough to sustain small / medium scale projects for free.&lt;/li&gt;
&lt;li&gt;Even though they bill for resource usages by the minute, it can become expensive quickly if you pass the limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Render
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://render.com" rel="noopener noreferrer"&gt;Render&lt;/a&gt; is a powerful cloud platform designed to simplify the process of building, deploying, and scaling websites and applications. It has gained popularity among developers due to its ease of use, reliability, and robust set of features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04g4ikwt6elqwpv1mmph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04g4ikwt6elqwpv1mmph.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Render offers a generous free tier with ample resources, including free SSL certificates and custom domain support.&lt;/li&gt;
&lt;li&gt;Automatic scaling and zero-downtime deployments, ensuring your website or application can handle traffic spikes and updates without interruption.&lt;/li&gt;
&lt;li&gt;Support for a wide range of programming languages and frameworks like Node, Python, Go, Rust, PHP, Elixir, Docker, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Render deletes Free tier PostgreSQL databases after 90 days from creation, making their database services unusable without paying a fee.&lt;/li&gt;
&lt;li&gt;May become expensive for scaling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Cyclic
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cyclic.sh" rel="noopener noreferrer"&gt;Cyclic&lt;/a&gt; is designed to streamline your DevOps workflows and revolutionize the way you approach continuous integration and deployment. With Cyclic, developers can harness the power of automation to build, test, and deploy their applications effortlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyagxcwbpb3ojkpc7izer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyagxcwbpb3ojkpc7izer.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Apps on Cyclic do not sleep even on the free tier.&lt;/li&gt;
&lt;li&gt;Cyclic's smart caching technology delivers the best performance globally.&lt;/li&gt;
&lt;li&gt;Features its cron jobs technology with 1 second precision triggering.&lt;/li&gt;
&lt;li&gt;Easily scalable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As of now, Cyclic supports JavaScript, TypeScript, and Python runtimes only.&lt;/li&gt;
&lt;li&gt;Good for APIs but not for other types of projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Fly.io
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://fly.io" rel="noopener noreferrer"&gt;Fly.io&lt;/a&gt; is an edge computing platform that empowers developers to optimize their applications for lightning-fast performance and global delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fly.io features a vast network of edge servers strategically placed around the world to bring your applications closer to your users.&lt;/li&gt;
&lt;li&gt;Generous free allowance to run small scale apps.&lt;/li&gt;
&lt;li&gt;Supports many languages and frameworks like Go, Crystal, RedwoodJS, Python, Ruby, Deno, etc.&lt;/li&gt;
&lt;li&gt;Seamless traffic shifting and canary deployments to roll out updates gradually, ensuring a smooth transition while minimizing the risk of errors or downtime.&lt;/li&gt;
&lt;li&gt;In depth &lt;a href="https://fly.io/docs/rails/getting-started/migrate-from-heroku/" rel="noopener noreferrer"&gt;migration from Heroku&lt;/a&gt; guide.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The learning curve to use Fly.io can be steep.&lt;/li&gt;
&lt;li&gt;Better alternatives exist to host small scale apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Notable mentions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; and &lt;a href="https://firebase.google.com" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt; are also great tools to deploy basic frontend apps for free.&lt;/li&gt;
&lt;li&gt;If you need finer control over your stack, &lt;a href="https://aws.amazon.com" rel="noopener noreferrer"&gt;AWS&lt;/a&gt; / &lt;a href="https://cloud.google.com" rel="noopener noreferrer"&gt;GCP&lt;/a&gt; / &lt;a href="https://azure.microsoft.com" rel="noopener noreferrer"&gt;Azure&lt;/a&gt; are the leading cloud services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this comprehensive list of 9 hand picked Heroku alternatives that you should be using in 2023 helps you evaluate your options for deploying your backend APIs and frontend applications.&lt;/p&gt;

&lt;p&gt;Did I miss any great option? Leave a comment below to start a discussion.&lt;/p&gt;

&lt;p&gt;Thank you for reading so far!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>backend</category>
    </item>
    <item>
      <title>Genics Log #2: Sponsorship from Vercel, Theme updates, Organic Growth and more</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Sun, 19 Jun 2022 06:14:19 +0000</pubDate>
      <link>https://forem.com/genicsblog/genics-log-2-sponsorship-from-vercel-theme-updates-organic-growth-and-more-3nfn</link>
      <guid>https://forem.com/genicsblog/genics-log-2-sponsorship-from-vercel-theme-updates-organic-growth-and-more-3nfn</guid>
      <description>&lt;p&gt;Welcome to the second issue in the &lt;a href="https://dev.to/category/genics-log"&gt;Genics log&lt;/a&gt; series! I know this is super late in the month, but I wanted to share some updates on the blog from the past months.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://genicsblog.com/genics-log-2"&gt;Listen to this article at Genics Blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before diving into the latest news at Genics, I would like to introduce myself. I am &lt;a href="https://gouravkhunger.xyz"&gt;Gourav Khunger&lt;/a&gt;, the founder of &lt;a href="https://genicsblog.com"&gt;Genics Blog&lt;/a&gt;. I am a teenager from India who is passionate about software development and &lt;a href="https://dev.to/tag/open-source/"&gt;open source&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://genicsblog.com/genics-log-1"&gt;last article&lt;/a&gt; in this series, we talked about how we went open source and how we managed to grow from 200 visitors/month to 500+ visitors/month, along with sponsorship from &lt;a href="https://beyondwords.io/?utm_source=genicsblog.com&amp;amp;utm_medium=cpc&amp;amp;utm_campaign=advertisement"&gt;BeyondWords&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This log is more inclined towards the core theme infrastructure and how we managed to grow our community to 600+ readers now.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging ENVs with Vercel
&lt;/h2&gt;

&lt;p&gt;This was a crucial step in forming a better infrastructure for building &lt;a href="https://github.com/genicsblog/theme-files"&gt;the theme&lt;/a&gt; and its plugins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Previous setup
&lt;/h3&gt;

&lt;p&gt;From the beginning itself, I planned to create a separate repository for the theme just because it would allow us to use a separate GitHub Pages for &lt;a href="https://staging.genicsblog.com"&gt;staging.genicsblog.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/genicsblog/theme-files/blob/aa7944b1943dbb7206b013dcc1d8102f8c48875e/.github/workflows/setup-staging.yml"&gt;This&lt;/a&gt; was the GitHub Actions file that deployed the theme to staging url. We made sure to block indexing using the &lt;code&gt;robots.txt&lt;/code&gt; file's &lt;code&gt;Disallow: /&lt;/code&gt; directive.&lt;/p&gt;

&lt;p&gt;But here comes the tricky part - the staging was not relevant until we were able to deploy PRs to preview them. Staging environment for approved and merged PRs didn't matter as much as environment for previewing the pending PRs.&lt;/p&gt;

&lt;p&gt;A huge problem was that we couldn't use repository secret variables in GitHub Actions if it ran using &lt;code&gt;pull_request&lt;/code&gt; event but those variables are needed to deploy to gh-pages.&lt;/p&gt;

&lt;p&gt;For that, we had to use &lt;code&gt;pull_request_target&lt;/code&gt; event trigger which allows PR actions to use the repository secrets to access the staging environment.&lt;/p&gt;

&lt;p&gt;But the catch here is, this comes with &lt;strong&gt;security vulnerabilities&lt;/strong&gt; as the PRs are run in the context of the repository base and not the PR base.&lt;/p&gt;

&lt;p&gt;This could mean that user can manipulate the workflow file to misuse the repository secrets!&lt;/p&gt;

&lt;h3&gt;
  
  
  Vulnerability in main repository
&lt;/h3&gt;

&lt;p&gt;The above mentioned issue was actually present in the main repository. I had setup a workflow for PRs using &lt;code&gt;pull_request_target&lt;/code&gt; because I wanted to automerge "correct" changes to drafts by authors.&lt;/p&gt;

&lt;p&gt;YES, this was a big mistake but fortunately, no one exploited this vulnerability using which one could clean up the whole repository in minutes (making a delete commit and managing to automerge it using repo secrets).&lt;/p&gt;

&lt;p&gt;I did have security measures in place:&lt;/p&gt;

&lt;p&gt;An &lt;a href="https://github.com/genicsblog/genicsblog.com/blob/8f8d936e72d886af28ea232d6e90eaa1442c6518/.github/workflows/validate-drafts.yml#L57-L64"&gt;automerge&lt;/a&gt; happened &lt;a href="https://github.com/genicsblog/genicsblog.com/blob/8f8d936e72d886af28ea232d6e90eaa1442c6518/.github/workflows/validate-drafts.yml#L54"&gt;only if&lt;/a&gt; the PR changes article files that are owned by the specific author. The &lt;a href="https://github.com/genicsblog/theme-files/blob/aa7944b1943dbb7206b013dcc1d8102f8c48875e/_scripts/validate-drafts.py"&gt;python script&lt;/a&gt; referenced takes in the list of files changed in the PR and goes through them to verify if the PR author is the actual author of the article files.&lt;/p&gt;

&lt;p&gt;Now, you could argue that a person could change the script in the PR and this check would easily be bypassed. That is the reason that the workflow uses &lt;code&gt;wget&lt;/code&gt; to download the script from the main branch and then run it. It &lt;a href="https://github.com/genicsblog/genicsblog.com/blob/8f8d936e72d886af28ea232d6e90eaa1442c6518/.github/workflows/validate-drafts.yml#L47-L48"&gt;deletes the scripts&lt;/a&gt; in the PR and downloads the correct one before running.&lt;/p&gt;

&lt;p&gt;But again, I was still skeptical of the &lt;code&gt;pull_request_target&lt;/code&gt; event trigger. The docs don't clearly mention it, but I am not sure - If the action runs in context of the PR base, then is it possible that the author change the action script and bypasses the script download and other verification checks?&lt;/p&gt;

&lt;p&gt;This is the reason we now moved to Vercel to off-load all these security issues and still be able to deploy staging ENVs!&lt;/p&gt;

&lt;h3&gt;
  
  
  Sponsorship from Vercel
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://vercel.com/?utm_source=genicsblog&amp;amp;utm_campaign=oss"&gt;Vercel&lt;/a&gt;{:rel="dofollow"} was generous enough to sponsor our &lt;a href="http://github.com/genicsblog/genicsblog.com"&gt;GitHub organization&lt;/a&gt; to be able to deploy organization repositories for free!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Vercel is a platform for frontend frameworks and static sites, built to integrate with your headless content, commerce, or database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This sponsorship now enables us to remove our vulnerable GitHub actions and migrate to Vercel deployments. It was as easy as setting up the installation and build scripts. Vercel automatically deploys all PRs to staging environments!&lt;/p&gt;

&lt;p&gt;Now we can easily preview pull requests and test them visually before moving them to production!&lt;/p&gt;

&lt;h2&gt;
  
  
  Theme updates
&lt;/h2&gt;

&lt;p&gt;We have worked on massive improvements to the theme and its plugins!&lt;/p&gt;

&lt;h3&gt;
  
  
  Paginating author pages (&lt;a href="https://github.com/genicsblog/theme-files/issues/7"&gt;#7&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;This was by far the biggest need for the theme. Author pages &lt;a href="https://genicsblog.com/author/gouravkhunger/"&gt;like this&lt;/a&gt; could get super big without pagination and that affects load times a lot.&lt;/p&gt;

&lt;p&gt;This was a big problem for the Jekyll community as well - there was no plugin to handle multiple authors with ease.&lt;/p&gt;

&lt;p&gt;This lead me to spend time messing with &lt;a href="https://github.com/sverrirs/jekyll-paginate-v2"&gt;jekyll-paginate-v2&lt;/a&gt; and understanding how its pagination works. With some days of effort, I came up with &lt;a href="https://github.com/gouravkhunger/jekyll-auto-authors"&gt;jekyll-auto-authors&lt;/a&gt; which completely simplifies the process of paginating author pages!&lt;/p&gt;

&lt;p&gt;Here's an &lt;a href="https://genicsblog.com/gouravkhunger/adding-multiple-authors-to-a-jekyll-blog-got-easier#2-using-my-plugin-jekyll-auto-authors"&gt;in-depth tutorial&lt;/a&gt; on using the plugin to paginate author pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shortcut commands (&lt;a href="https://github.com/genicsblog/theme-files/issues/10"&gt;#10&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;There are new shortcut commands you can use to perform these actions on the site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening up search bar: &lt;code&gt;command&lt;/code&gt; + &lt;code&gt;K&lt;/code&gt; or &lt;code&gt;Ctrl&lt;/code&gt; + &lt;code&gt;K&lt;/code&gt;. To close it please use the &lt;code&gt;Esc&lt;/code&gt; key.&lt;/li&gt;
&lt;li&gt;Toggling the site theme: &lt;code&gt;command&lt;/code&gt; + &lt;code&gt;shift&lt;/code&gt; + &lt;code&gt;L&lt;/code&gt; or &lt;code&gt;Ctrl&lt;/code&gt; + &lt;code&gt;Shift&lt;/code&gt; + &lt;code&gt;L&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Copy button for code blocks (&lt;a href="https://github.com/genicsblog/theme-files/issues/1"&gt;#1&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Copy buttons on code blocks have been given an overhaul and provide a much nicer user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spam comments
&lt;/h3&gt;

&lt;p&gt;In light of &lt;a href="https://github.com/genicsblog/comments/pull/122"&gt;recent spam abuse&lt;/a&gt; of our commenting system, we have removed the comment system for now. We might use &lt;a href="https://giscus.app"&gt;giscus&lt;/a&gt; in future but there's no plans for it right now.&lt;/p&gt;

&lt;p&gt;Please use our &lt;a href="https://discord.genicsblog.com"&gt;Discord server&lt;/a&gt; for discussions on articles on the site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other updates
&lt;/h3&gt;

&lt;p&gt;Here are some minor but relevant updates we've made to the theme:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More open-graph meta tags (&lt;a href="https://github.com/genicsblog/theme-files/issues/39"&gt;#39&lt;/a&gt;): better for SEO.&lt;/li&gt;
&lt;li&gt;Migration to GA4 (&lt;a href="https://github.com/genicsblog/theme-files/issues/21"&gt;#21&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Selection color for code blocks (&lt;a href="https://github.com/genicsblog/theme-files/issues/28"&gt;#28&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Refactoring series pages (&lt;a href="https://github.com/genicsblog/theme-files/issues/2"&gt;#2&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;For authors: tools like &lt;a href="https://genicsblog.com/tool/frontmatter-generator"&gt;frontmatter generator&lt;/a&gt; (&lt;a href="https://github.com/genicsblog/genicsblog.com/issues/93"&gt;#93&lt;/a&gt;) and &lt;a href="https://genicsblog.com/tool/thumbnail-generator"&gt;thumbnail generator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Licensing for the theme and articles (&lt;a href="https://github.com/genicsblog/genicsblog.com/discussions/136"&gt;#136&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stats
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Open Source
&lt;/h3&gt;

&lt;p&gt;Here are the stats that changed from the last time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/genicsblog/genicsblog.com"&gt;&lt;code&gt;genicsblog.com&lt;/code&gt;&lt;/a&gt; (Main repo with posts and data files): &lt;strong&gt;25 stars&lt;/strong&gt;, &lt;strong&gt;20 forks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/genicsblog/theme-files"&gt;&lt;code&gt;theme-files&lt;/code&gt;&lt;/a&gt; (Basically template files): &lt;strong&gt;7 stars&lt;/strong&gt;, &lt;strong&gt;9 fork&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Analytics
&lt;/h3&gt;

&lt;p&gt;Here are the recent 30-day stats from our Google Analytics:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S5JW6w4i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/46792249/173242642-81e97597-073b-4068-b1ff-3fb0eac8633b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S5JW6w4i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/46792249/173242642-81e97597-073b-4068-b1ff-3fb0eac8633b.png" alt="Genics blog's past 30 days Google Analytics Stats" width="642" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Join our &lt;a href="https://discord.genicsblog.com"&gt;Discord server&lt;/a&gt; to view these public stats every day :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Organic Stats
&lt;/h3&gt;

&lt;p&gt;Almost 40-50% of our monthly traffic is through organic channels!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gEKowZLb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/46792249/173243091-49771902-7e9b-4eed-b37b-a911641ace8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gEKowZLb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/46792249/173243091-49771902-7e9b-4eed-b37b-a911641ace8c.png" alt="Genics blog's past 3 month Google Search Console Stats" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;It's been an absolute rollercoaster ride for us to get to this point! It was from 100 readers a month in December when I decided to open source the blog and start working on a newer and better version of it. And here we are, scaled to 600+ readers within 3 months!&lt;/p&gt;

&lt;p&gt;In the near future, I plan to continue working on the improvements and scale to at least 5k readers per month. Up to that point, we will focus mainly on putting out quality content that people find insightful while focusing on gaining traffic through organic channels mainly.&lt;/p&gt;

&lt;p&gt;After the 5k checkpoint, there will be great things to come ;)&lt;/p&gt;

&lt;p&gt;Looking forward to your feedback and suggestions!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>blog</category>
      <category>news</category>
    </item>
    <item>
      <title>Kotlin: Multi-dimensional Arrays</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Mon, 09 May 2022 16:47:42 +0000</pubDate>
      <link>https://forem.com/genicsblog/kotlin-multi-dimensional-arrays-3hl8</link>
      <guid>https://forem.com/genicsblog/kotlin-multi-dimensional-arrays-3hl8</guid>
      <description>&lt;p&gt;At some point of time, we all have worked with arrays. It is a useful data structure to store multiple values of the same type in a single variable. Complex usage of arrays includes storing data in 2D, 3D, or other multidimensional arrays. This allows us to represent things like matrices, grids, and cubes effectively.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will specifically focus on declaring, initializing and using 2D, 3D, and other multidimensional arrays in the Kotlin programming language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;To understand multi-dimensional arrays and lists in kotlin, you need to have a proper understanding of 1D arrays. I have published an intuitive article about kotlin arrays similar to this one, do &lt;a href="https://genicsblog.com/gouravkhunger/kotlin-multi-dimensional-2d-3d-etc-array-initialization"&gt;read the article&lt;/a&gt; before proceeding.&lt;/p&gt;

&lt;h2&gt;
  
  
  2D Arrays in Kotlin
&lt;/h2&gt;

&lt;p&gt;2D arrays are a convenient way to store grid/board/matrix type of data.&lt;/p&gt;

&lt;p&gt;If we dig deep into Kotlin Standard Library, the function &lt;code&gt;arrayOf()&lt;/code&gt; is actually returning &lt;code&gt;Array&amp;lt;T&amp;gt;&lt;/code&gt; where &lt;code&gt;T&lt;/code&gt; is the type of the elements in the array. This effectively means that if we pass in &lt;code&gt;T&lt;/code&gt; we get out an array &lt;code&gt;Array&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means if we pass in &lt;code&gt;arrayOf()&lt;/code&gt; into the &lt;code&gt;arrayOf()&lt;/code&gt; function, we effectively get out &lt;code&gt;Array&amp;lt;Array&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; and that is exactly the representation of 2D Arrays!&lt;/p&gt;

&lt;h3&gt;
  
  
  2D Arrays with pre-defined data
&lt;/h3&gt;

&lt;p&gt;Let's see how to make 2D arrays with predefined values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;array&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a 2D Kotlin array which is a collection of 1D Kotlin arrays. Here's a representation of the array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;General Form:
[[1 2 3], [4,5,6], [7,8,9]]

As a matrix:
1 2 3
4 5 6
7 8 9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, these arrays are not type-safe. You can add another data type to the array without any issue. To make it type-safe, we need to declare the type of the array during initialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;array&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt; &lt;span class="c1"&gt;// Declaring the type gives error if data types are mixed&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"this string will give error"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;arrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2D arrays with dynamic size
&lt;/h3&gt;

&lt;p&gt;To create 2D lists where we don't have a fixed known size, we use &lt;code&gt;mutableListOf&amp;lt;MutableList&amp;lt;T&amp;gt;&amp;gt;()&lt;/code&gt; declaration where &lt;code&gt;T&lt;/code&gt; is the data type we expect the inner lists to hold. We don't pass any initial value because the array will be populated using some logic later.&lt;/p&gt;

&lt;p&gt;Let's look at it in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;list&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MutableList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// The elements within the inner lists can be anything, the numbers below are just an example.&lt;/span&gt;

&lt;span class="c1"&gt;// `repeat()` takes in a number and iterates from 0 to number-1&lt;/span&gt;
&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// `row` is a new row in the array&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableListOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

    &lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// `col` is a new column in the row, ranges from 0 to 3&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Append the row to the array, can also use the `add()` function&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// for each list in the list, print its element in matrix form&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sublist&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sublist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$j "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// new line after each row&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/*
You can also access particular elements like:
list[0][0] -&amp;gt; First element of the first row
or
list.get(0).get(0) -&amp;gt; Same as above
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code outputs the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 1 2 3 
0 1 2 3 
0 1 2 3 
0 1 2 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And hence we can create dynamic lists in kotlin as per our needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  N-Dimensional Arrays in Kotlin
&lt;/h2&gt;

&lt;p&gt;Using the approaches discussed above, it wouldn't be hard to create 3D, 4D or even more dimensional arrays.&lt;/p&gt;

&lt;p&gt;If the dataset you have is known, you can use the &lt;code&gt;arrayOf()&lt;/code&gt; function, or to have variable array data, you can go ahead with &lt;code&gt;mutableListOf()&lt;/code&gt; functions to create the arrays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial you learned about the arrays and mutable lists in kotlin using &lt;code&gt;arrayOf()&lt;/code&gt; and &lt;code&gt;mutableListOf()&lt;/code&gt; functions.&lt;/p&gt;

&lt;p&gt;These functions help you to create arrays and lists of any data type in Kotlin, to store values and perform actions based on that data.&lt;/p&gt;

&lt;p&gt;I hope you find this tutorial useful. Share it with your friends who are beginning with kotlin!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
      <category>codenewbie</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to Create a Pull Request in GitHub *Correctly*</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Wed, 06 Apr 2022 07:50:23 +0000</pubDate>
      <link>https://forem.com/genicsblog/how-to-create-a-pull-request-in-github-correctly-20np</link>
      <guid>https://forem.com/genicsblog/how-to-create-a-pull-request-in-github-correctly-20np</guid>
      <description>&lt;p&gt;A major aspect of open source is the ability to create and maintain a community of developers who collaborate on building software together. Collaboration is a key component of open source development!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read this article at &lt;a href="https://genicsblog.com/gouravkhunger/how-to-create-a-pull-request-in-github-correctly" rel="noopener noreferrer"&gt;genicsblog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://git-scm.com" rel="noopener noreferrer"&gt;Git&lt;/a&gt; and &lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; are popular open source collaboration tools. Git helps you keep track of changes to your code, and GitHub helps you share your code with others. In this article we will teach you how to create a pull request in GitHub in the correct way.&lt;/p&gt;

&lt;p&gt;We will use this &lt;a href="https://github.com/gouravkhunger/PRs-demo" rel="noopener noreferrer"&gt;demo repository&lt;/a&gt; to demonstrate the process on collaboration. Feel free to play with it and see how it works. Follow along the tutorial below.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Fork the Repository
&lt;/h2&gt;

&lt;p&gt;Forking a repository means you are creating a copy of the repository to your own GitHub account. This makes a clone of the repository that you can work on.&lt;/p&gt;

&lt;p&gt;Any changes to your fork will not affect the original repository! Thus, it is kind of a playground area for you to experiment with code/files.&lt;/p&gt;

&lt;p&gt;To fork a repository, simply press the &lt;strong&gt;Fork button&lt;/strong&gt; on the top right corner of the repository page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F161415696-9e0772ed-60a6-4f5d-98d5-3976217fdc1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F161415696-9e0772ed-60a6-4f5d-98d5-3976217fdc1a.png" alt="Fork button on GitHub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This creates a new repository in your account.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Clone the Repository
&lt;/h2&gt;

&lt;p&gt;Cloning a repository means you are downloading the repository to your computer. This creates a folder that you will work on.&lt;/p&gt;

&lt;p&gt;Run this command in your terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/&amp;lt;your-username&amp;gt;/PRs-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will clone the repository to a folder names &lt;code&gt;PRs-demo&lt;/code&gt; which you can &lt;code&gt;cd&lt;/code&gt; into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;PRs-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Create a New Branch
&lt;/h2&gt;

&lt;p&gt;Branching is a way to work on a different version of files in a project with Git version control. Creating a new branch is effective when you are working on a new feature or bug fix. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It helps to keep changes organised and clean.&lt;/li&gt;
&lt;li&gt;It separates changes from working code in main branch. In case of broken code, you can easily revert to the main branch.&lt;/li&gt;
&lt;li&gt;This also helps your fork's main branch clean once your PRs are merged (more on this later).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run this command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;new-branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;&amp;lt;new-branch-name&amp;gt;&lt;/code&gt; is the name of the new branch. It can be anything like: &lt;code&gt;bug-fix&lt;/code&gt;, &lt;code&gt;feature-1&lt;/code&gt;, &lt;code&gt;feature-2&lt;/code&gt;, etc. For simplicity purpose you can keep it &lt;code&gt;learning-about-prs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-b&lt;/code&gt; flag is used to create a new branch, and &lt;code&gt;checkout&lt;/code&gt; asks Git to switch to that new branch we created.&lt;/p&gt;

&lt;p&gt;To verify that you have correctly switched to the new branch, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should output something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* learning-about-prs
  main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;*&lt;/code&gt; verifies that you are currently on that branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Make Changes
&lt;/h2&gt;

&lt;p&gt;Now you can make Changes to the files in the project. Here, we just have a &lt;code&gt;README.md&lt;/code&gt; file. You can edit it and add this sentence to the end of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; This line was added by &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;&amp;lt;Your Name Here&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://github.com/&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;your-username&amp;gt;&lt;/span&gt;).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to replace &lt;code&gt;&amp;lt;Your Name Here&amp;gt;&lt;/code&gt; with your name and &lt;code&gt;&amp;lt;your-username&amp;gt;&lt;/code&gt; with your GitHub username!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Commit your changes
&lt;/h2&gt;

&lt;p&gt;Committing your changes is crucial to save the current state of your project.&lt;/p&gt;

&lt;p&gt;You can check the current state of your project by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells us which files have changes that are not committed yet. The output would be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On branch learning-about-prs
Changes not staged for commit:
  (use "git add &amp;lt;file&amp;gt;..." to update what will be committed)
  (use "git restore &amp;lt;file&amp;gt;..." to discard changes in working directory)
    modified:   README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can prepare the README.md file to be committed. Files that have finalised changes and are ready to be committed are moved to the staging area. Git only commited files that are staged, which provides us even more flexibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adds all the changed files to the staging area. Optionally you can handpick files to be added.&lt;/p&gt;

&lt;p&gt;Now, you can make a commit by running this command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;Commit Message&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;-m&lt;/code&gt; flag lets us add a message to our commit. This message is helpful for other people viewing change history of the project. Replace &lt;code&gt;&amp;lt;Commit Message&amp;gt;&lt;/code&gt; with a short summary of the changes you made. For example: "Added a new line to the README.md file".&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Push changes to your fork
&lt;/h2&gt;

&lt;p&gt;Now that you have committed the file locally, you need to send this file over to your fork present on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: GitHub doesn't automatically know about your commits made locally. You need to push the commits yourself.&lt;/p&gt;

&lt;p&gt;Since you have made changes to &lt;code&gt;learning-about-prs&lt;/code&gt;, you can push them to GitHub with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin learning-about-prs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are asking git to &lt;code&gt;push&lt;/code&gt; our changes to the branch &lt;code&gt;learning-about-prs&lt;/code&gt; on the &lt;code&gt;origin&lt;/code&gt; present on GitHub (your fork).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-u&lt;/code&gt; sets the upstream for current branch so that you don't have to type &lt;code&gt;origin learning-about-prs&lt;/code&gt; everytime. From the next time, even if you type &lt;code&gt;git push&lt;/code&gt; it will push to &lt;code&gt;learning-about-prs&lt;/code&gt; branch on GitHub.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Additional Note:
&lt;/h3&gt;

&lt;p&gt;Here, &lt;code&gt;origin&lt;/code&gt; is linked to your fork. You can verify it by running this command in your terminal:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This should show the &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt; links which point to your fork.&lt;br&gt;
If you change these links by using &lt;code&gt;git remote rm origin&lt;/code&gt; and &lt;code&gt;git remote add origin &amp;lt;new-link&amp;gt;&lt;/code&gt;, the commits will be sent to new remote then!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  7. Make the PR
&lt;/h2&gt;

&lt;p&gt;Once you push your changes to GitHub, open the fork on GitHub. You will be able to see a a notification regarding the new commits to &lt;code&gt;learning-about-prs&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F161416102-4e803e63-f22c-4125-a5dd-38ee7c07bbc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F161416102-4e803e63-f22c-4125-a5dd-38ee7c07bbc3.png" alt="Branch had recent pushes, Compare and pull request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press the &lt;code&gt;Compare and pull request&lt;/code&gt; button and you will be presented with an interface to create a pull request.&lt;/p&gt;

&lt;p&gt;Enter appropriate &lt;strong&gt;Title&lt;/strong&gt; and &lt;strong&gt;Comment&lt;/strong&gt; to our PR. This helps the reviewers know what changes you are making to the repository.&lt;/p&gt;

&lt;p&gt;Once you are done with adding the metadata to the PR, go ahead and press the "&lt;strong&gt;Create Pull Request&lt;/strong&gt;" button.&lt;/p&gt;

&lt;p&gt;Congratulations 🥳&lt;/p&gt;

&lt;p&gt;You've successfully made a Pull Request to a repository on GitHub!&lt;/p&gt;

&lt;p&gt;Using these steps you can create a Pull Request to any repository on GitHub!&lt;/p&gt;

&lt;h2&gt;
  
  
  (Optional) Useful Information
&lt;/h2&gt;

&lt;h3&gt;
  
  
  I forgot to make some required changes but made a PR, do I have to make a new one now?
&lt;/h3&gt;

&lt;p&gt;Absolutely no! GitHub is smart enough to handle this. &lt;strong&gt;You can't create more than one PR from a single branch&lt;/strong&gt;. This means that you can add more commits to the current branch and as soon as you push them, they will automatically go to the existing PR.&lt;/p&gt;

&lt;p&gt;Just add as many commits you want, to the branch and use &lt;code&gt;git push&lt;/code&gt;. That will send the commits to the existing PR, avoiding the need to create a new one from scratch!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do we create a new branch in the first place?
&lt;/h3&gt;

&lt;p&gt;There are quite a few reasons to it. The main one being it maintains a separation of concerns. One can work on differnt number of features at the same time without affecting existing working code.&lt;/p&gt;

&lt;p&gt;This also helps teams to assign different features to different people and collaborate on different parts of projects in realtime.&lt;/p&gt;

&lt;p&gt;Another reason is, once the reviewers approve and merge your changes, it adds a new commit to the original repository.&lt;/p&gt;

&lt;p&gt;Now your fork would get left behind because it doesn't automatically pull new changes from the original source.&lt;/p&gt;

&lt;p&gt;GitHub provides us with &lt;strong&gt;Fetch upstream&lt;/strong&gt; button to keep our fork in sync with the remote repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F161415987-2c9160b0-9f14-4ee6-b569-16c900b26950.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F161415987-2c9160b0-9f14-4ee6-b569-16c900b26950.png" alt="Fetch upstream button on GitHub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pressing &lt;strong&gt;Fetch and merge&lt;/strong&gt; gets changes from original repository to our fork allowing us to keep the fork up to date.&lt;/p&gt;

&lt;p&gt;If we had made changes directly to the main branch, it could cause merge conflicts as our fork would have different commits than original repository.&lt;/p&gt;

&lt;p&gt;Also, this could pollute the new PRs with old commits if the main branch of fork isn't kept up to date with original repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a good place to start with open source?
&lt;/h3&gt;

&lt;p&gt;Genics Blog is an &lt;a href="https://github.com/genicsblog" rel="noopener noreferrer"&gt;open source&lt;/a&gt; developer publication where we do a lot of open source work. We are a high school student run organisation. Join our &lt;a href="https://discord.genicsblog.com" rel="noopener noreferrer"&gt;community on Discord&lt;/a&gt; to learn about opportunities from experienced developers and get involved!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Resources
&lt;/h2&gt;

&lt;p&gt;Check out this video where I use the steps taught here to create a PR to the &lt;a href="https://github.com/genicsblog/theme-files" rel="noopener noreferrer"&gt;&lt;code&gt;theme-files&lt;/code&gt;&lt;/a&gt; repository for &lt;a href="https://genicsblog.com" rel="noopener noreferrer"&gt;Genics Blog&lt;/a&gt; on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/wHxlA0p1AbM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Watch at 1.25x speed for better experience :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This was a long but to the point Guide to create Pull Requests on GitHub which can help you to contribute to open source projects on GitHub.&lt;/p&gt;

&lt;p&gt;If you find this guide helpful, or have any related questions feel free to comment or &lt;a href="https://discord.genicsblog.com" rel="noopener noreferrer"&gt;join our discord&lt;/a&gt; to get help.&lt;/p&gt;

&lt;p&gt;Share this article with people who are new to open source world!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Genics Log #1: Sponsorship from BeyondWords, Open Source, Organic Stats and more</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Fri, 11 Feb 2022 09:13:38 +0000</pubDate>
      <link>https://forem.com/genicsblog/genics-log-1-sponsorship-from-beyondwords-open-source-organic-stats-and-more-2ack</link>
      <guid>https://forem.com/genicsblog/genics-log-1-sponsorship-from-beyondwords-open-source-organic-stats-and-more-2ack</guid>
      <description>&lt;p&gt;Hello there, I hope you are doing well!&lt;/p&gt;

&lt;p&gt;This is the first article in the &lt;a href="https://genicsblog.com/category/genics-log" rel="noopener noreferrer"&gt;Genics log&lt;/a&gt; series where we will be documenting our monthly progress on the blog and report what's been brewing up in the past months.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://genicsblog.com/genics-log-1" rel="noopener noreferrer"&gt;Read this article at Genics Blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before diving into the latest news at Genics, I would like to introduce myself. I am &lt;a href="https://genicsblog.com/contributor/gouravkhunger" rel="noopener noreferrer"&gt;Gourav Khunger&lt;/a&gt;, the founder of &lt;a href="https://genicsblog.com" rel="noopener noreferrer"&gt;Genics Blog&lt;/a&gt;. I am a teenager from India who is passionate about software development and &lt;a href="https://genicsblog.com/tag/open-source/" rel="noopener noreferrer"&gt;open source&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Genics Blog went &lt;a href="https://github.com/genicsblog" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; at this New Year, which means we started accepting community contributions for the blog.&lt;/p&gt;

&lt;p&gt;Within a month itself, we have reached huge milestones! Here's a gist of some stats from the past month:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Core team&lt;/strong&gt; members increased from &lt;strong&gt;1 to 5 members&lt;/strong&gt;!&lt;/li&gt;
&lt;li&gt;A total of &lt;strong&gt;15 articles&lt;/strong&gt; were posted in January!&lt;/li&gt;
&lt;li&gt;A total of &lt;strong&gt;40 members&lt;/strong&gt; joined the &lt;a href="https://discord.genicsblog.com" rel="noopener noreferrer"&gt;Genics Blog discord server&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Rose from &lt;strong&gt;200 monthly visitors to 500+&lt;/strong&gt;!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it all started
&lt;/h2&gt;

&lt;p&gt;I always wanted to create a community of skilled developers who create quality content around topics!&lt;/p&gt;

&lt;p&gt;As the new year began, I grabbed the opportunity to open source my &lt;a href="https://blog.gouravkhunger.xyz" rel="noopener noreferrer"&gt;existing blog&lt;/a&gt; and build a community around the existing content.&lt;/p&gt;

&lt;p&gt;And since we chose the open source way, we quickly rose from 200 visitors/month to 500+ visitors/month!&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Source Setup
&lt;/h2&gt;

&lt;p&gt;We use &lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; for our open source projects. Everything we build around Genics is open source because we want to be as transparent as we can!&lt;/p&gt;

&lt;p&gt;For this blog, we used &lt;a href="https://jekyllrb.com" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt; to generate the website and render all the content. The beauty of Jekyll is we can use any design template, while writing the articles in markdown format. It renders the complete site with an easy build command!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pages.github.com" rel="noopener noreferrer"&gt;GitHub Pages&lt;/a&gt; works really well for hosting the website, because jekyll generates static html pages which work seamlessly with GitHub Pages.&lt;/p&gt;

&lt;p&gt;There's a lot more to share on how the site and management works. I'd love to write articles on how we build and operate our systems completely for &lt;strong&gt;FREE&lt;/strong&gt;, so keep an eye out on the &lt;a href="https://docs.genicsblog.com/developer" rel="noopener noreferrer"&gt;developer documentation&lt;/a&gt; and future posts on Genics blog!&lt;/p&gt;

&lt;h2&gt;
  
  
  Announcing BeyondWords.io Sponsorship
&lt;/h2&gt;

&lt;p&gt;Just a few days ago we got sponsored by &lt;a href="https://beyondwords.io/?utm_source=genicsblog.com&amp;amp;utm_medium=cpc&amp;amp;utm_campaign=advertisement" rel="noopener noreferrer"&gt;BeyondWords.io&lt;/a&gt;!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;BeyondWords is an AI voice and audio publishing platform that brings frictionless audio to writers, newsrooms, and businesses!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is a platform that allows anyone to publish their written scripts in audio format to the world. In my opinion, the best part about is its text to speech AI conversion modules are far better than those of Google and Amazon as the audio it generates seems to be near human voice!&lt;/p&gt;

&lt;p&gt;Genics Blog got sponsored by &lt;a href="https://beyondwords.io" rel="noopener noreferrer"&gt;BeyondWords&lt;/a&gt; where they generously offered us free services to convert our articles to audio formats! You can try out the audio functionality right at the top of this post!&lt;/p&gt;

&lt;h2&gt;
  
  
  Stats
&lt;/h2&gt;

&lt;p&gt;We have grown manifolds just because of the fact that we went open source!&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Source
&lt;/h3&gt;

&lt;p&gt;Here are the stats for the repositories under &lt;a href="//https:/github.com/genicsblog"&gt;Genics Blog&lt;/a&gt; organization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/genicsblog/genicsblog.com" rel="noopener noreferrer"&gt;&lt;code&gt;genicsblog.com&lt;/code&gt;&lt;/a&gt; (Main repo with posts and data files): &lt;strong&gt;21 stars&lt;/strong&gt;, &lt;strong&gt;14 forks&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/genicsblog/theme-files" rel="noopener noreferrer"&gt;&lt;code&gt;theme-files&lt;/code&gt;&lt;/a&gt; (Basically template files): &lt;strong&gt;2 stars&lt;/strong&gt;, &lt;strong&gt;1 fork&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/genicsblog/docs" rel="noopener noreferrer"&gt;&lt;code&gt;docs&lt;/code&gt;&lt;/a&gt; (&lt;a href="https://docs.genicsblog.com" rel="noopener noreferrer"&gt;Documentation website&lt;/a&gt;): &lt;strong&gt;3 stars&lt;/strong&gt;, &lt;strong&gt;2 forks&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/genicsblog/genics-bot" rel="noopener noreferrer"&gt;&lt;code&gt;genics-bot&lt;/code&gt;&lt;/a&gt; (Bot for the &lt;a href="https://discord.genicsblog.com" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt;): &lt;strong&gt;5 star&lt;/strong&gt;, &lt;strong&gt;1 fork&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Google Analytics
&lt;/h3&gt;

&lt;p&gt;Images speak louder than words!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F153484864-a8bf7f54-03aa-4f30-95d8-7f94e2e94949.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F153484864-a8bf7f54-03aa-4f30-95d8-7f94e2e94949.png" alt="Genics blog's past 30 days Google Analytics Stats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Organic Stats
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F153484772-c2a0a786-0826-4771-85a8-c70f55dcb719.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F153484772-c2a0a786-0826-4771-85a8-c70f55dcb719.png" alt="Genics blog's past 30 days Google Search Console Stats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Plans
&lt;/h2&gt;

&lt;p&gt;We are looking forward to producing a lot of quality content in the future, as well as working on improving the platform.&lt;/p&gt;

&lt;p&gt;Here are a few examples of some things we'd work on in the near future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building certain tools to aid the writing process for authors at Genics Blog.&lt;/li&gt;
&lt;li&gt;Adding table of content to the posts.&lt;/li&gt;
&lt;li&gt;Social previews for anchor tags in posts.&lt;/li&gt;
&lt;li&gt;Copy buttons for code blocks.&lt;/li&gt;
&lt;li&gt;Adding some cool webmention functionality to our articles, so as to highlight who shares our articles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And a lot more!&lt;/p&gt;

&lt;p&gt;You can check out the issues page on &lt;a href="https://github.com/genicsblog/theme-files/issues" rel="noopener noreferrer"&gt;&lt;code&gt;theme-files&lt;/code&gt;&lt;/a&gt; repo to see what's on the roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;I'm really glad to be sharing this info with you!&lt;/p&gt;

&lt;p&gt;Did you know we have a discord bot that sends notifications on our analytics and stats everyday 👀. I bet you, hardly anyone would do that :P&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F153487310-2dcd5854-4de9-47fa-a679-09a917d8564f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46792249%2F153487310-2dcd5854-4de9-47fa-a679-09a917d8564f.png" alt="Genics Blog's Discord Community Bot logging stats from Google Analytics everyday"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do join us there to get notified of new posts and updates on Genics Blog.&lt;/p&gt;

&lt;p&gt;If you find what we are doing as high school students fascinating, consider joining us and be a part of Genics Blog! &lt;a href="https://genicsblog.com/contribute" rel="noopener noreferrer"&gt;Here&lt;/a&gt; are the ways you could contribute to it.&lt;/p&gt;

&lt;p&gt;Looking forward to seeing you engage with the active community on our &lt;a href="https://discord.genicsblog.com" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt; :)&lt;/p&gt;

</description>
      <category>news</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Next generation Hello World program</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Tue, 01 Feb 2022 11:14:20 +0000</pubDate>
      <link>https://forem.com/gouravkhunger/next-generation-hello-world-program-41oe</link>
      <guid>https://forem.com/gouravkhunger/next-generation-hello-world-program-41oe</guid>
      <description>&lt;p&gt;While learning a programming language, I am pretty sure you started with the basic "Hello World!" program :)&lt;/p&gt;

&lt;p&gt;But once you advance in a particular programming language, the Hello World code would start seeming to be boring.&lt;/p&gt;

&lt;p&gt;But here's an interesting challenge for you! My friend and I have created a challenge out of the basic Hello World code so you could stretch your coding muscles and judge how well you know about the language you specialize in!&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://genicsblog.com/next-generation-hello-world-program"&gt;this article&lt;/a&gt; to learn about the challenge and also how to solve the given problem.&lt;/p&gt;

&lt;p&gt;Though it might feel it is for advanced coders, everything is explained in a beginner-friendly way so it's worth checking out!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>challenge</category>
      <category>helloworld</category>
    </item>
    <item>
      <title>My first article at freeCodeCamp 🎉</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Wed, 17 Nov 2021 11:29:01 +0000</pubDate>
      <link>https://forem.com/gouravkhunger/my-first-article-at-freecodecamp-4o0f</link>
      <guid>https://forem.com/gouravkhunger/my-first-article-at-freecodecamp-4o0f</guid>
      <description>&lt;p&gt;Recently I wrote my first ever article for freeCodeCamp. It is an in-depth tutorial on adding swipe animation to an Android view. &lt;/p&gt;

&lt;p&gt;Check it out here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/add-swipe-animations-to-a-card-view-in-android-app/"&gt;https://www.freecodecamp.org/news/add-swipe-animations-to-a-card-view-in-android-app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do you think about the article? Let me know in the discussion below 😃&lt;/p&gt;




&lt;p&gt;I usually publish my articles at &lt;a href="https://genicsblog.com"&gt;genicsblog.com&lt;/a&gt; and share them here, if you wanna opt in for my newsletter you can do that on my blog and follow to get notified about new content 😄&lt;/p&gt;

</description>
      <category>android</category>
      <category>animation</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How to Support Multiple Fonts in an Android App</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Sat, 06 Nov 2021 19:15:31 +0000</pubDate>
      <link>https://forem.com/gouravkhunger/how-to-support-multiple-font-options-in-an-android-app-1j5e</link>
      <guid>https://forem.com/gouravkhunger/how-to-support-multiple-font-options-in-an-android-app-1j5e</guid>
      <description>&lt;p&gt;You would hardly see any Android app that allows its users to be able to choose from a set of fonts to be used for the whole app, based on the user's preference. The major reason being it is hard to implement!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you bother?
&lt;/h2&gt;

&lt;p&gt;Accessibility is a major aspect that every app developer should focus on. Imagine an app with an amazing utility but one that is barely usable. You don't want to loose your user base!&lt;/p&gt;

&lt;p&gt;I used to neglect this, but here's why I am writing this post.&lt;/p&gt;

&lt;p&gt;If you follow me on any social media, or here on my blog, you know that &lt;a href="https://genicsblog.com/introducing-jekyllex-android-app" rel="noopener noreferrer"&gt;I built JekyllEx&lt;/a&gt; to be able to manage Jekyll blogs from my Android device.&lt;/p&gt;

&lt;p&gt;Recently, I &lt;a href="https://github.com/jekyllex/jekyllex-android/issues/2" rel="noopener noreferrer"&gt;a person reached out&lt;/a&gt; to discuss about their chronic headaches that are triggered by font and colours that don't go well on their eyes and it would be great if I allowed some settings to be able to customise it based on user preferences. &lt;/p&gt;

&lt;p&gt;I quickly went to have a look at what the Android accessibility guidelines had to say.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/guide/topics/ui/accessibility" rel="noopener noreferrer"&gt;https://developer.android.com/guide/topics/ui/accessibility&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But to my surprise- I DIDN'T FIND ANYTHING. If you take a look at those guidelines, you'll find Google actually emphasizes developers a lot to take measures and make their app accessible for all kind of users. But such a common problem hasn't been addressed. Believe me, there are many a people with varied levels of such reading problems. &lt;/p&gt;

&lt;p&gt;And I usually don't enable such settings in apps, but I thought it would be a great challenge to overcome, because mostly, all the solutions that already exist are inefficient: most stack overflow answers ask to traverse the &lt;code&gt;ViewGroup&lt;/code&gt;'s children and apply custom typeface as they find Text.&lt;/p&gt;

&lt;p&gt;I had some other thoughts and it was obvious I would be making an Android library that somehow resolves this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;In broad aspects, an Android app is just a set of &lt;code&gt;View&lt;/code&gt;(s), held together by &lt;code&gt;ViewGroup&lt;/code&gt;(s), that perform certain actions when loaded, clicked, etc. All that together makes the functional app.&lt;/p&gt;

&lt;p&gt;But here's the catch- each view has its own &lt;code&gt;Context&lt;/code&gt;, that gives access to the current state of the view, and that makes it harder to think about how to implement the multiple-font feature, as each view needs separate handling to update its font.&lt;/p&gt;

&lt;p&gt;Here is a typical example of how to update the font of a single &lt;code&gt;TextView&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;typeface&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ResourcesCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_code_pro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// get font from res/font/ directory&lt;/span&gt;
&lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;helloWorld&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;typeface&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;typeface&lt;/span&gt; &lt;span class="c1"&gt;// apply the font to the text view&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636027952199%2FbY0CrvEb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636027952199%2FbY0CrvEb8.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have 20+ text views, or rather a RecyclerView(as in &lt;a href="https://jekyllex.xyz" rel="noopener noreferrer"&gt;JekyllEx&lt;/a&gt;), in which each of the items has a significantly large number of &lt;code&gt;TextView&lt;/code&gt;(s).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636028456465%2Ffi0vdUzhZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636028456465%2Ffi0vdUzhZ.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, &lt;a href="https://github.com/jekyllex/jekyllex-android/blob/main/app/src/main/res/layout/other_repository_item.xml" rel="noopener noreferrer"&gt;each RecyclerView item&lt;/a&gt; actually has 8 TextViews! Imagine updating the font manually for each view, one-by-one. It would be really inconvenient!&lt;/p&gt;

&lt;p&gt;I had a look to some stack overflow questions and as told earlier, most of them were old and in-efficient.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;From the very beginning I knew I would store the default font in a &lt;code&gt;SharedPreference&lt;/code&gt;. For those who don't know about it, it is Android's way to allow apps to store simple key-value paired data that the app can use without write access to the disk. For most of the cases, it suffices to use &lt;code&gt;SharedPreference&lt;/code&gt; instead of writing to disk and it was super handy in this case.&lt;/p&gt;

&lt;p&gt;I would store the resource id, an integer identifier that is given to all types of resources in any app, in &lt;code&gt;SharedPreference&lt;/code&gt;, and retrieve that value to apply the font when the view is inflated (rendered on screen).&lt;/p&gt;

&lt;p&gt;This was the most efficient way I could come up with, because &lt;code&gt;SharedPreference&lt;/code&gt; is really optimised. The values are cached and retrieving multiple values within a short time doesn't affect performance much.&lt;/p&gt;

&lt;p&gt;There exists another way, by changing the &lt;code&gt;themes.xml&lt;/code&gt; values at runtime and applying font directly from the styles itself, but it requires minimum API level 23 (Android 6.0). So it wouldn''t be backward compatible and make the app crash on lower Android versions. I didn't want to do so.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;Here's the library that I built:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gouravkhunger" rel="noopener noreferrer"&gt;
        gouravkhunger
      &lt;/a&gt; / &lt;a href="https://github.com/gouravkhunger/Fontize" rel="noopener noreferrer"&gt;
        Fontize
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fontize is an Android library that enables multi-font selection functionality to beautify your app.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Fontize Android Library&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://android-arsenal.com/api?level=23" rel="nofollow noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://camo.githubusercontent.com/e7ce1768000fb61d452bcb69f56f0bc11b44424b6ab860e1927294fd6d71a158/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4150492d32332532422d627269676874677265656e2e7376673f7374796c653d666c6174" alt="Fontize Android Library Licence"&gt;&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://jitpack.io/#GouravKhunger/Fontize" rel="nofollow noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://camo.githubusercontent.com/220be0e6dfff3264aff6a0e61236e0574fa9bdf5cd23b2791566be4f31789010/68747470733a2f2f6a69747061636b2e696f2f762f476f757261764b68756e6765722f466f6e74697a652e737667" alt="Fontize Android Library Licence"&gt;&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/gouravkhunger/Fontize/blob/main/LICENSE" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://camo.githubusercontent.com/46b4ecde82f22639ed0e7ec17fbd36cf6933902ffd8ce5d410771129d5113863/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f676f757261766b68756e6765722f466f6e74697a65" alt="Fontize Android Library Licence"&gt;&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/gouravkhunger/Fontize/stargazers" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://camo.githubusercontent.com/cdacd89150d079f8915205f8194680b1a3ea5de11e6d5e5794ffc2e42f652c51/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f676f757261766b68756e6765722f466f6e74697a65" alt="Fontize Android Library Stars"&gt;&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/gouravkhunger/Fontize/fork" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://camo.githubusercontent.com/569b7a92e820230d31c37bece2f2ed48b75c24bd06b7f12e25c45dd9231a9280/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f676f757261766b68756e6765722f466f6e74697a65" alt="Fontize Android Library Forks"&gt;&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/gouravkhunger/Fontize/issues" rel="noopener noreferrer"&gt;&lt;br&gt;
    &lt;img src="https://camo.githubusercontent.com/94325c5c262715f6fece484e0a23445a130bbc3f01888826343d7e9509fd9d4d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f676f757261766b68756e6765722f466f6e74697a65" alt="Fontize Android Library Issues"&gt;&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;div&gt;
    Built with ❤︎ by
        &lt;a href="https://github.com/gouravkhunger" rel="noopener noreferrer"&gt;Gourav Khunger&lt;/a&gt;
    
&lt;/div&gt;



&lt;p&gt;Fontize is an Android library, written in kotlin, that enables your android app have multiple fonts for your &lt;code&gt;TextView&lt;/code&gt;s
and switch  between them in a jiffy!&lt;/p&gt;
&lt;p&gt;A quick demo:&lt;/p&gt;
&lt;div&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/gouravkhunger/Fontize/main/media/demo.gif"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fgouravkhunger%2FFontize%2Fmain%2Fmedia%2Fdemo.gif" alt="Fontize Android Library Demo GIF" height="500"&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Adding Fontize to your project&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Include jitpack in your root &lt;code&gt;build.gradle&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="highlight highlight-source-groovy-gradle notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-en"&gt;allprojects&lt;/span&gt; {
    repositories {
        &lt;span class="pl-k"&gt;..&lt;/span&gt;.
        maven { url &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;https://jitpack.io&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; }
    }
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;And add it's dependency to your app level &lt;code&gt;build.gradle&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight highlight-source-groovy-gradle notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-en"&gt;dependencies&lt;/span&gt; {
    implementation &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;com.github.gouravkhunger:Fontize:1.0.1&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Sync the project and you'll have imported Fontize successfully.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Start using Fontize&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Make sure you have all your fonts in the &lt;code&gt;res/font/&lt;/code&gt; directory. Support for font files in the &lt;code&gt;assets&lt;/code&gt; folder will ship soon!&lt;/p&gt;
&lt;p&gt;Rename all the &lt;code&gt;TextView&lt;/code&gt;s or &lt;code&gt;AppCompatTextView&lt;/code&gt;s in your project to &lt;code&gt;com.github.gouravkhunger.fontize.FontizeTextView&lt;/code&gt; - You don't have to change anything else, and the view would still perform the same :)&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class="highlight highlight-text-xml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&amp;lt;&lt;span class="pl-ent"&gt;TextView&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gouravkhunger/Fontize" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Once you add &lt;a href="https://github.com/gouravkhunger/Fontize" rel="noopener noreferrer"&gt;fontize&lt;/a&gt; to your project, you need to follow certain steps mentioned in the repositorie's README and your project will migrate to use intelligent &lt;code&gt;Fontize&lt;/code&gt; views that can work united and can change fonts in a snap.&lt;/p&gt;

&lt;p&gt;Here's a demo of what you can Achieve with Fontize:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636224247599%2Fd04oZY7Pf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1636224247599%2Fd04oZY7Pf.gif" alt="Fontize Android library demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To set the default font for the app, you just have to add this line of code just below &lt;code&gt;onCreate()&lt;/code&gt; function in your app's launcher activity (the one that is triggered when app icon is clicked) only once:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="nc"&gt;Fontize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setDefaultFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exo_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// replace with the font you desire&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Internally, this function creates a &lt;code&gt;SharedPreference&lt;/code&gt; value if it doesn't already exist:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;setDefaultFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;sharedPref&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PreferenceManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDefaultSharedPreferences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fontId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sharedPref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fontFamily"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ResourcesCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ID_NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fontId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;ResourcesCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ID_NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sharedPref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;putInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fontFamily"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To update the font for the entire app, you just need to run this code and Fontize will handle it automatically for you:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="nc"&gt;Fontize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;updateFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zen_old_mincho&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// updates fontFamily throughout app&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here's the interesting part, this function just updates the &lt;code&gt;fontFamily&lt;/code&gt; value stored in &lt;code&gt;SharedPreference&lt;/code&gt; for the app:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;updateFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;sharedPref&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PreferenceManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDefaultSharedPreferences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sharedPref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;putInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fontFamily"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The actual work happens in the view classes. Let's take the example of &lt;code&gt;FontizeTextView&lt;/code&gt;, or any similar class. It just extends the parent View and applies the font by picking its value from &lt;code&gt;SharedPreference&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FontizeTextView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AttributeSet&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatTextView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;prefs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PreferenceManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDefaultSharedPreferences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;fontId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fontFamily"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ResourcesCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ID_NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fontId&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="nc"&gt;ResourcesCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ID_NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;typeface&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ResourcesCompat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fontId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;typeface&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;typeface&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;All this code does is, to override the default view to apply the font family as soon as it inflates. Similar classes for views that support texts within them, like workarounds for &lt;code&gt;MenuItem&lt;/code&gt;(s) and &lt;code&gt;Toolbar&lt;/code&gt;(s),  will be shipped soon.&lt;/p&gt;

&lt;p&gt;If you need to look at a live project that uses Fontize in production- &lt;a href="https://github.com/jekyllex/jekyllex-android" rel="noopener noreferrer"&gt;checkout JekyllEx app on GitHub&lt;/a&gt;. It doesn't use the initial version that was published on Jitpack, but it uses a custom fork as per its needs and requirements, but Fontize will soon evolve and be able to do a lot more than just &lt;code&gt;TextViews&lt;/code&gt; 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Believe me or not, starting this project, to finishing the base version with a working &lt;code&gt;FontizeTextView&lt;/code&gt;, to publishing it on jitpack- all just finished within 2 hours! &lt;a href="https://github.com/gouravkhunger/Fontize" rel="noopener noreferrer"&gt;Fontize&lt;/a&gt; deserves a star for that effort 😎.&lt;/p&gt;

&lt;p&gt;I hope you learnt something new out of this post. If you want to keep reading quality Android development content, consider joining my newsletter @ &lt;a href="https://genicsblog.com" rel="noopener noreferrer"&gt;Genics Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Do comment and let me know what topic should I pick to publish an article next week. All kinds of feedbacks are appreciated :)&lt;/p&gt;

&lt;p&gt;Thanks and happy coding!&lt;/p&gt;

</description>
      <category>android</category>
      <category>a11y</category>
      <category>library</category>
    </item>
    <item>
      <title>Trying out Next.js for the first time 🤯</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Mon, 27 Sep 2021 10:56:47 +0000</pubDate>
      <link>https://forem.com/gouravkhunger/trying-out-next-js-for-the-first-time-3k6g</link>
      <guid>https://forem.com/gouravkhunger/trying-out-next-js-for-the-first-time-3k6g</guid>
      <description>&lt;p&gt;You read the title right! I tried something other than Android this time :P&lt;/p&gt;

&lt;p&gt;I have always been wanting to learn web development. If you know my background, you probably know I first learned HTML, CSS, and really basic Javascript at first. If not, consider reading &lt;a href="https://genicsblog.com/3-years-of-blogging"&gt;this article&lt;/a&gt; to know more about my journey:&lt;/p&gt;

&lt;p&gt;But just learning that wasn't enough to make better websites. Technically we can make functional websites with them. But &lt;strong&gt;it isn't intuitive&lt;/strong&gt;. Using just HTML and CSS to make a good-looking website is a headache because files become too long to manage. At least that was the case for me :(&lt;/p&gt;

&lt;p&gt;Sure, you can use tools like Tailwind CSS, but neither was I aware of such tools nor did I knew there are frameworks like React, Angular, Vue, etc. which can make the process of building websites easy.&lt;/p&gt;

&lt;p&gt;It was obvious that I left web dev back then and that was when I turned to Android. I have been doing Android dev for more than 2 years now. And I recently realized - &lt;strong&gt;staying in a single domain while the tech world progresses will slow your progress&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I am not saying you should learn everything that comes out each day. But having a gist of other things won't be harming you. I have tried both things- sticking to a single tech and also trying different things. And I bet you, trying new things teaches more than repeating what you know again and again!&lt;/p&gt;

&lt;p&gt;For a long time, I wanted to try out web dev again, more because websites work on any device, and just knowing Android was limiting me to the devices I can make apps for.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://hashnode.com/bootcamp"&gt;Hashnode Bootcamp&lt;/a&gt;'s Day 5 task was a perfect moment I could try a new thing and write about it. And here I am writing about using Next.js for two really basic things I needed to work on. Here are the projects:&lt;/p&gt;

&lt;h2&gt;
  
  
  Birthday Wish Generator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://hbdwish.ml"&gt;Check it out&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repo: &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gouravkhunger"&gt;
        gouravkhunger
      &lt;/a&gt; / &lt;a href="https://github.com/gouravkhunger/nextjs-birthday-wish"&gt;
        nextjs-birthday-wish
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is a minimal Next.js app where you can create birthday wishes and share the link to anyone :)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Happy Birthday Wisher&lt;/h1&gt;
&lt;p&gt;Check out the &lt;a href="https://hbdwish.ml" rel="nofollow"&gt;Live Website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is a simple &lt;a href="https://nextjs.org/" rel="nofollow"&gt;Next.js&lt;/a&gt; project where you can generate a birthday wish for someone.&lt;/p&gt;
&lt;p&gt;Just enter their name, press Go and share them the generated link :)&lt;/p&gt;
&lt;p&gt;Don't forget to ⭐️ this repository!&lt;/p&gt;
&lt;h2&gt;
Images&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/46792249/136275729-454a4475-18fc-4b41-af98-dbf781778b9e.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jqLxMrMM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/46792249/136275729-454a4475-18fc-4b41-af98-dbf781778b9e.png" alt="Happy Birthday Wisher Home Page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Local Setup&lt;/h2&gt;
&lt;p&gt;First, clone this repository:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/gouravkhunger/nextjs-birthday-wisher&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Install the dependencies:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Then, run the development server:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="nofollow"&gt;http://localhost:3000&lt;/a&gt; with your browser to see the result.&lt;/p&gt;
&lt;p&gt;You can start editing the page by modifying &lt;code&gt;pages/index.js&lt;/code&gt;. The page auto-updates as you edit the file.&lt;/p&gt;
&lt;h2&gt;
Contributing&lt;/h2&gt;
&lt;p&gt;In order to make a hassle-free environment, please make sure to read the &lt;a href="https://github.com/gouravkhunger/nextjs-birthday-wishCONTRIBUTING.md"&gt;Contribution Guidelines&lt;/a&gt; and follow all the steps mentioned there
Are we missing any of your favorite features, which you think you can add to it❓ Feel free to do so. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;All contributions are welcome.&lt;/p&gt;
&lt;h2&gt;
Learn More&lt;/h2&gt;
&lt;p&gt;To learn more about Next.js, take…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gouravkhunger/nextjs-birthday-wish"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;One of my friend's birthdays is near and I wanted to do something special for them. And looking at the Next.js, I quickly thought to make a simple page with some confetti popping in the background, and their name on the front.&lt;/p&gt;

&lt;p&gt;I quickly made the project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app nextjs-birthday-wish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But this thought struck my mind: Since I am gonna deploy it to Vercel anyway, I can make a home page where anyone can enter the name of the person they want to send a wish, and then copy the generated link to be sent.&lt;/p&gt;

&lt;p&gt;Also, I could make it open source just to increase the number of reports on my profile so that I can flex on the count.&lt;/p&gt;

&lt;p&gt;I quickly created two pages, along with their CSS modules. Here are the screenshots:&lt;/p&gt;
&lt;h3&gt;
  
  
  Home Page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VxtNB5zu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632674975999/NHbFfU1vZ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VxtNB5zu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632674975999/NHbFfU1vZ.jpeg" alt="one.jpeg" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Birthday Wish
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zw6R35cL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632675120489/1uZ_YLvsn.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zw6R35cL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632675120489/1uZ_YLvsn.jpeg" alt="two.jpeg" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I completed the project in 3 hours, took so long because I had to test 7 different confetti libraries that work with Next.js 😂. Finally used &lt;code&gt;[confetti-js](https://www.npmjs.com/package/confetti-js)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I also spent some time on CSS and the routing stuff- because I don't know CSS that well, but I am improving day by day. The CSS design of this blog is done by me!&lt;/p&gt;

&lt;p&gt;But I think I did a pretty decent job. And it was fun trying next js for the first time, it's a great framework on top of React, so if you are learning Next.js you are learning concepts of React too. So it is a win-win case.&lt;/p&gt;
&lt;h2&gt;
  
  
  S̶t̶r̶i̶k̶e̶d̶ ̶T̶e̶x̶t̶ ̶G̶e̶n̶e̶r̶a̶t̶o̶r̶
&lt;/h2&gt;

&lt;p&gt;(The title for this section is generated with this tool 😂)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://strikeit.ml/"&gt;Check out the project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gouravkhunger"&gt;
        gouravkhunger
      &lt;/a&gt; / &lt;a href="https://github.com/gouravkhunger/nextjs-strikeit"&gt;
        nextjs-strikeit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A simple site to get a striked through version of text.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
StrikeIt&lt;/h1&gt;
&lt;p&gt;Check out the &lt;a href="https://strikeit.ml" rel="nofollow"&gt;Live Website&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is a simple &lt;a href="https://nextjs.org/" rel="nofollow"&gt;Next.js&lt;/a&gt; site to quickly get the striked through version of text copied to your keyboard.&lt;/p&gt;
&lt;p&gt;Don't forget to ⭐️ this repository!&lt;/p&gt;
&lt;h2&gt;
Images&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/gouravkhunger/nextjs-strikeit/main/media/one.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gQajuHK6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/gouravkhunger/nextjs-strikeit/main/media/one.png" alt="StrikeIt Home Page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/gouravkhunger/nextjs-strikeit/main/media/two.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0_S2llFA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/gouravkhunger/nextjs-strikeit/main/media/two.png" alt="Striked Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Local Setup&lt;/h2&gt;
&lt;p&gt;First, clone this repository:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;git clone https://github.com/gouravkhunger/nextjs-strikeit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;cd&lt;/code&gt; into the folder and then, run the development server:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; download dependencies&lt;/span&gt;
npm i
npm run dev
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or&lt;/span&gt;
yarn dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="nofollow"&gt;http://localhost:3000&lt;/a&gt; with your browser to see the result.&lt;/p&gt;
&lt;p&gt;You can start editing the page by modifying &lt;code&gt;pages/index.js&lt;/code&gt;. The page auto-updates as you edit the file.&lt;/p&gt;
&lt;h2&gt;
Learn More&lt;/h2&gt;
&lt;p&gt;To learn more about Next.js, take a look at the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/docs" rel="nofollow"&gt;Next.js Documentation&lt;/a&gt; - learn about Next.js features and API.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/learn" rel="nofollow"&gt;Learn Next.js&lt;/a&gt; - an interactive Next.js tutorial.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can check out &lt;a href="https://github.com/vercel/next.js/"&gt;the Next.js GitHub repository&lt;/a&gt; - your feedback and contributions are welcome!&lt;/p&gt;
&lt;h2&gt;
Credits&lt;/h2&gt;
&lt;div&gt;Icons made by &lt;a href="https://www.flaticon.com/authors/surang" title="surang" rel="nofollow"&gt;surang&lt;/a&gt; from &lt;a href="https://www.flaticon.com/" title="Flaticon" rel="nofollow"&gt;www.flaticon.com&lt;/a&gt;
&lt;/div&gt;

&lt;h2&gt;
License&lt;/h2&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;MIT License
Copyright (c) 2021 Gourav Khunger&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gouravkhunger/nextjs-strikeit"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Here are the images:&lt;/p&gt;

&lt;h3&gt;
  
  
  Home Page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KgO-A7Qb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632674734678/ik7IJW6Yt.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KgO-A7Qb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632674734678/ik7IJW6Yt.jpeg" alt="one.jpeg" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Preview of striked text
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KTJD9_tc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632674743501/Wvr_3Y_om.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KTJD9_tc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632674743501/Wvr_3Y_om.jpeg" alt="two.jpeg" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I needed this generator because I use Google Calendar to stay focused and plan the work I have for a day. &lt;/p&gt;

&lt;p&gt;I don't clutter my day with huge time boxes because that doesn't work for me and I need the flexibility to carry out my tasks.&lt;/p&gt;

&lt;p&gt;What I do is: I copy a template of three events for each day the day before it, and put the things I need to carry out in their respective category.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bzAdelb5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632672045301/bk9x2KLPn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bzAdelb5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632672045301/bk9x2KLPn.png" alt="image.png" width="800" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works well for me. But actually, the text in google calendar events cannot be striked through once it is completed- as you can do for tasks rather than events.&lt;/p&gt;

&lt;p&gt;I could have used many of the text formatting tools available online to cut my text and strike to check them off. But I generally forget random website names and the same would be the case with many 😂. Also, most free tools have ads and trackers, which isn't convenient.&lt;/p&gt;

&lt;p&gt;So, why not try to build this thing with Next.js? The thought of increasing repo count on GitHub profile still came 😜.&lt;/p&gt;

&lt;p&gt;I again quickly made a new Next.js  project, deleted the unnecessary blurb that comes by default then copied from the last project added the text box.&lt;/p&gt;

&lt;p&gt;This time I faced a new difficulty- to display the striked text preview in a paragraph below the input box. I could set an event listener when the input box's text changed, but didn't know what to do to get a reference of the paragraph below it, as we can't do the traditional &lt;code&gt;document.getElementById()&lt;/code&gt; in Next.js apps.&lt;/p&gt;

&lt;p&gt;With some research, I learned we can use &lt;code&gt;useRef&lt;/code&gt; to maintain a ref of elements, and it worked! I learned how &lt;a href="https://stackoverflow.com/a/53836006/9819031"&gt;this snippet&lt;/a&gt; gives you striked version of the text and then implemented it when input occurs.&lt;/p&gt;

&lt;p&gt;I learned how easy it is to copy something to the device clipboard using Next.js. This piece of snippet does the work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This will be copied!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It took me ~4 hours for this project because I wanted to make it responsive and I was struggling with the input box width for different screens, at the end made it work well with some hit and trial 😆&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Words
&lt;/h1&gt;

&lt;p&gt;I hope you liked the article, consider commenting to let me know what you think!&lt;/p&gt;

&lt;p&gt;It was my first experience with Next.js and I must admit it was really good. Though I got many errors and go to learn a lot in the meantime, it was worth it!&lt;/p&gt;

&lt;p&gt;Do check out the projects on GitHub and star them. And since you are going to star them, why not follow me there too? 😆&lt;/p&gt;

&lt;p&gt;I post resourceful content on this blog, consider subscribing to the newsletter by filling the form at the top of the article to get notified of the new content that I keep posting. Alternatively, &lt;a href="https://hashnode.com/@gouravkhunger/joinme"&gt;join Hashnode&lt;/a&gt; and &lt;a href="https://hashnode.com/@gouravkhunger"&gt;follow me&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://genicsblog.com/contact"&gt;Let's get in touch&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally posted on &lt;a href="https://genicsblog.com"&gt;genicsblog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>projects</category>
    </item>
    <item>
      <title>Integrate Authentication to your Android App with Auth0</title>
      <dc:creator>Gourav Khunger</dc:creator>
      <pubDate>Mon, 27 Sep 2021 10:40:51 +0000</pubDate>
      <link>https://forem.com/byteslash/integrate-authentication-to-your-android-app-with-auth0-2hcf</link>
      <guid>https://forem.com/byteslash/integrate-authentication-to-your-android-app-with-auth0-2hcf</guid>
      <description>&lt;p&gt;&lt;a href="https://auth0.com"&gt;Auth0&lt;/a&gt; is an amazing tool to easily integrate user authentication in any kind of app you are building. It has a great set of tools to enable auth in your app in a few really quick steps.&lt;/p&gt;

&lt;p&gt;Today, we are going to look into how to integrate Auth0 into your Android App! First, we'll set up the local project for integrating Auth0, and then we'll set up the app on the Auth0 dashboard.&lt;/p&gt;

&lt;p&gt;Check out this video to learn what we are going to build in this tutorial:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/obk3q1AaH6I"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The code for this basic app that we are going to build is present here on GitHub, star it and follow me :)&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/gouravkhunger"&gt;
        gouravkhunger
      &lt;/a&gt; / &lt;a href="https://github.com/gouravkhunger/auth0-demo-android"&gt;
        auth0-demo-android
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demo implementation of Auth0 Authentication for Android
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Demo Implementation of Auth0&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://genicsblog.com/authentication-in-android-app-with-auth0" rel="nofollow"&gt;Read the article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Demo implementation of Auth0 Authentication for Android.&lt;/p&gt;
&lt;h2&gt;
License&lt;/h2&gt;
&lt;p&gt;This project is &lt;a href="https://github.com/gouravkhunger/auth0-demo-android/blob/main/LICENSE"&gt;&lt;code&gt;MIT&lt;/code&gt;&lt;/a&gt; Licensed.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;MIT License
Copyright (c) 2021 Gourav Khunger

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/gouravkhunger/auth0-demo-android"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  Android app setup
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Initialize the project
&lt;/h2&gt;

&lt;p&gt;First, create a new Android Studio Project.  If you are just checking out Auth0, you can follow the steps mentioned in one of my previous articles on &lt;a href="https://genicsblog.com/how-to-create-your-first-android-app-using-android-studio"&gt;how to make a basic project using Android Studio&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also use any existing project!&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up view binding
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is it?
&lt;/h3&gt;

&lt;p&gt;View binding is a new way of referencing views from XML layouts inside your java/kotlin classes. View Binding creates a Binding class for each XML layout resource which you can use to refer views without the hassle of using &lt;code&gt;findViewById()&lt;/code&gt; or using the deprecated kotlin synthetics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable View Binding
&lt;/h3&gt;

&lt;p&gt;If you are reading this post in the future, chances are that view binding is supported right into new projects using Android Studio.&lt;/p&gt;

&lt;p&gt;If not, you can go into the App level &lt;code&gt;build.gradle&lt;/code&gt; file and add this piece of code anywhere inside the &lt;code&gt;android&lt;/code&gt; scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="n"&gt;buildFeatures&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;viewBinding&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This image will give you a gist of where to add it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZQWHPvaw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632594546418/IWp7Zd5Ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZQWHPvaw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632594546418/IWp7Zd5Ju.png" alt="image.png" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrate Auth0
&lt;/h2&gt;

&lt;p&gt;To integrate Auth0 into our project, we need to do the following things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Auth0 dependencies
&lt;/h3&gt;

&lt;p&gt;In your app level &lt;code&gt;build.gradle&lt;/code&gt; dependencies section, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="k"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... other dependencies&lt;/span&gt;

  &lt;span class="c1"&gt;// Auth0 Android SDK&lt;/span&gt;
  &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'com.auth0.android:auth0:2.4.0'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C9uWhwXb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632596987895/ChRu2ueYY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C9uWhwXb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632596987895/ChRu2ueYY.png" alt="image.png" width="800" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add manifest placeholders
&lt;/h3&gt;

&lt;p&gt;You need to add one more simple line of code to the app level &lt;code&gt;build.gradle&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight gradle"&gt;&lt;code&gt;&lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;defaultConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// ...&lt;/span&gt;

        &lt;span class="c1"&gt;// Add this&lt;/span&gt;
        &lt;span class="n"&gt;manifestPlaceholders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nl"&gt;auth0Domain:&lt;/span&gt; &lt;span class="s2"&gt;"@string/com_auth0_domain"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;auth0Scheme:&lt;/span&gt; &lt;span class="s2"&gt;"demo"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates an &lt;code&gt;intent-filter&lt;/code&gt; which is used by the library to open your app back once the login is done by the user. If this is not done you have to define an &lt;code&gt;intent-filter&lt;/code&gt; on your own. This method is easier than handling that.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The &lt;code&gt;@string/com_auth0_domain&lt;/code&gt; is actually a string resource, you need to declare it in your &lt;code&gt;strings.xml&lt;/code&gt; as follows:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;string&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"com_auth0_domain"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Your domain here&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hKeMsew9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632597709645/Q0e7v73bC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hKeMsew9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632597709645/Q0e7v73bC.png" alt="image.png" width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't worry if you don't have a domain like this yet, scroll below to find the auth0 dashboard setup, or you can skip this for now and come back to it later!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Press Sync Now on the notification bar to complete the finalize the above things&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2gyYDpe6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632597868902/ZQFHTYOs_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2gyYDpe6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632597868902/ZQFHTYOs_.png" alt="image.png" width="800" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Internet Permissions to Manifest
&lt;/h3&gt;

&lt;p&gt;You would need to add the internet permission to the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file to allow network access, else the app may crash during login process.&lt;/p&gt;

&lt;p&gt;Add this line in your &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file as shown in the image below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.INTERNET"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--57tAOJGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632598305357/oBXJKdYTY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--57tAOJGk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632598305357/oBXJKdYTY.png" alt="image.png" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Make a basic UI
&lt;/h2&gt;

&lt;p&gt;Open the &lt;code&gt;res/layout/activity_main.xml&lt;/code&gt; file and replace the content with this layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;LinearLayout&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:android=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res/android"&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:app=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/apk/res-auto"&lt;/span&gt;
    &lt;span class="na"&gt;xmlns:tools=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.android.com/tools"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
    &lt;span class="na"&gt;android:orientation=&lt;/span&gt;&lt;span class="s"&gt;"vertical"&lt;/span&gt;
    &lt;span class="na"&gt;android:gravity=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;
    &lt;span class="na"&gt;tools:context=&lt;/span&gt;&lt;span class="s"&gt;".MainActivity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/nameTv"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_margin=&lt;/span&gt;&lt;span class="s"&gt;"10dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:textSize=&lt;/span&gt;&lt;span class="s"&gt;"30sp"&lt;/span&gt;
        &lt;span class="na"&gt;android:textColor=&lt;/span&gt;&lt;span class="s"&gt;"#000000"&lt;/span&gt;
        &lt;span class="na"&gt;android:text=&lt;/span&gt;&lt;span class="s"&gt;"@string/john_doe"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;TextView&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/emailTv"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_marginBottom=&lt;/span&gt;&lt;span class="s"&gt;"28dp"&lt;/span&gt;
        &lt;span class="na"&gt;android:textSize=&lt;/span&gt;&lt;span class="s"&gt;"18sp"&lt;/span&gt;
        &lt;span class="na"&gt;android:text=&lt;/span&gt;&lt;span class="s"&gt;"@string/email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Button&lt;/span&gt;
        &lt;span class="na"&gt;android:text=&lt;/span&gt;&lt;span class="s"&gt;"@string/login"&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/loginBtn"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_marginTop=&lt;/span&gt;&lt;span class="s"&gt;"20dp"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Button&lt;/span&gt;
        &lt;span class="na"&gt;android:text=&lt;/span&gt;&lt;span class="s"&gt;"@string/logout"&lt;/span&gt;
        &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/logoutBtn"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"wrap_content"&lt;/span&gt;
        &lt;span class="na"&gt;android:layout_marginTop=&lt;/span&gt;&lt;span class="s"&gt;"10dp"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/LinearLayout&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a simple layout that has the name and email text on top and two buttons to log-in and log-out. You'll have to create string resources for dummy name and email placeholder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_uL1TgWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632600993177/-UK3Y3RsZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_uL1TgWZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632600993177/-UK3Y3RsZ.png" alt="Screenshot_1632600899.png" width="800" height="1600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding the &lt;code&gt;MainActivity&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Initialize View Binding
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;lateinit var&lt;/code&gt; for the view binding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ActivityMainBinding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inflate the binding the the &lt;code&gt;onCreate()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ActivityMainBinding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layoutInflater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, set the root element of the binding as the content view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what the &lt;code&gt;MainActivity.kt&lt;/code&gt; file looks like after doing the above changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// package name&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.github.gouravkhunger.auth0demo&lt;/span&gt;

&lt;span class="c1"&gt;// imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;ActivityMainBinding&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;binding&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ActivityMainBinding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inflate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layoutInflater&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;setContentView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initialize Auth0
&lt;/h3&gt;

&lt;p&gt;First, you'll need to create an instance of the Auth0 class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Imports&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// other vars ...&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;lateinit&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Auth0&lt;/span&gt;

    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// ...&lt;/span&gt;

        &lt;span class="c1"&gt;// Set up the account object with the Auth0 application details&lt;/span&gt;
        &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Auth0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"xljNBT32DCsVDN7sYDM1qEHMD2mA1fVp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"auth0-demo-android.us.auth0.com"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This is the client id and domain of my sample app, replace it with yours to make it work.&lt;/em&gt; To get these parameters for your app, skip ahead to the setting up auth0 section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Log-in
&lt;/h3&gt;

&lt;p&gt;Now, proceed to set the &lt;code&gt;onClickListener&lt;/code&gt; on the button. This will be triggered whenever the button will be clicked.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainActivity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AppCompatActivity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Bundle&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;savedInstanceState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loginBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOnClickListener&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;WebAuthProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withScheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"openid profile email"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c1"&gt;// Launch the authentication passing the callback where the results will be received&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Credentials&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// Called when there is an authentication failure&lt;/span&gt;
                    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// Something went wrong!&lt;/span&gt;
                        &lt;span class="nc"&gt;Toast&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Login Error: \n${error.message}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_LONG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="c1"&gt;// Called when authentication completed successfully&lt;/span&gt;
                    &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// Get the access token from the credentials object.&lt;/span&gt;
                        &lt;span class="c1"&gt;// This can be used to call APIs&lt;/span&gt;
                        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;accessToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accessToken&lt;/span&gt;
                        &lt;span class="nf"&gt;showUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, once a user presses this button, the login process will start and they'll be asked to log in with their E-mail id. &lt;/p&gt;

&lt;p&gt;You can use any scheme name, here I used &lt;code&gt;demo&lt;/code&gt;. But I recommend not to use &lt;code&gt;https&lt;/code&gt; because it might conflict with the intent-filters internally. I got this error while building &lt;a href="https://genicsblog.com/introducing-jekyllex-android-app"&gt;JekyllEx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once the login is successful, we can get the access token which can be used to retrieve the user profile. Let's make a function to get the user profile from the token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;showUserProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationAPIClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// With the access token, call `userInfo` and get the profile from Auth0.&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;userInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Something went wrong!&lt;/span&gt;
                &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"Error getting profile \n${error.message}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_LONG&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// We have the user's profile!&lt;/span&gt;
                &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nameTv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
                &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emailTv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;
                &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"Login Successful!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_SHORT&lt;/span&gt;
                &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Log-out
&lt;/h3&gt;

&lt;p&gt;Now, let's make a function that enables logging out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;WebAuthProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withScheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="err"&gt;: &lt;/span&gt;&lt;span class="nc"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;?,&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;?)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// The user has been logged out!&lt;/span&gt;
                    &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"Successfully logged out!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_SHORT&lt;/span&gt;
                    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nameTv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;john_doe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emailTv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="nd"&gt;@MainActivity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;"Couldn't Logout!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="nc"&gt;Toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LENGTH_SHORT&lt;/span&gt;
                    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, our app is ready to handle log-in and logout. You can also &lt;a href="https://github.com/gouravkhunger/auth0-demo-android/blob/main/app/src/main/java/com/github/gouravkhunger/auth0demo/MainActivity.kt"&gt;checkout the content&lt;/a&gt; of the &lt;code&gt;MainActivity.kt&lt;/code&gt; file on the repo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up Auth0
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Make an account
&lt;/h2&gt;

&lt;p&gt;First, let's do the setup needed at the auth0 dashboard. &lt;/p&gt;

&lt;p&gt;Go to the official &lt;a href="https://auth0.com/"&gt;Auth0&lt;/a&gt; site and press signup on the navigation bar. After making an account, you would be taken to the dashboard where you can create a tenant. Here, the tenant is what auth0 calls a project. A project can have a number of applications in it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All the applications in a single-tenant have the same user database and storage.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up the tenant
&lt;/h2&gt;

&lt;p&gt;Create a new tenant. You can choose any domain name for your tenant, here I am choosing &lt;code&gt;auth0-demo-android&lt;/code&gt;. For now, this will be a subdomain, but you can customize it to your custom domain by upgrading your free plan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kB_etYLr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632595285718/pzRUUPZSOX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kB_etYLr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632595285718/pzRUUPZSOX.png" alt="Screenshot 2021-09-26 at 12.10.19 AM.png" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a new app
&lt;/h2&gt;

&lt;p&gt;Go to the applications section and press create a new app. Since we are building an Android app, choose the native field and hit create.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o5HoxUW---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632595589796/u_K9yatlS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5HoxUW---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632595589796/u_K9yatlS.png" alt="Screenshot 2021-09-26 at 12.15.19 AM.png" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we are going to develop an app that will use this tenant, tag it in the &lt;code&gt;development&lt;/code&gt; phase.&lt;/p&gt;

&lt;p&gt;After creating your app, go to the app settings&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--POqMrZyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632648478901/D6LpFj98V.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--POqMrZyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632648478901/D6LpFj98V.png" alt="image.png" width="706" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to the Application URIs section, there add callback URLs for login and logout. These are required to let Auth0 know what apps are authorized to perform these actions as these strings contain identifiers for our app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;demo://&amp;lt;tenant-domain&amp;gt;.us.auth0.com/android/PACKAGE_NAME/callback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Replace the package name and tenant domain with that of your own app. If you have set a scheme other than &lt;code&gt;demo&lt;/code&gt;, change it here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nxa5gUx3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632648617407/DJhXTcFJH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nxa5gUx3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632648617407/DJhXTcFJH.png" alt="image.png" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZT_JmchO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632648626448/y2zKRWq53.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZT_JmchO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1632648626448/y2zKRWq53.png" alt="image.png" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After adding them, scroll all the way to the bottom and save the changes.&lt;/p&gt;

&lt;p&gt;Now you can go ahead and replace the Client IDs and such things in the code, wherever necessary.&lt;/p&gt;

&lt;h1&gt;
  
  
  Congratulations 🥳
&lt;/h1&gt;

&lt;p&gt;You have successfully added Auth0 to your Android app. Trust me, though this post was long, it is actually really easy if you try it on your own.&lt;/p&gt;

&lt;p&gt;If you stayed along till this far, I am really thankful to you! Please comment on your experience with Auth0 and this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://genicsblog.com/contact"&gt;Let's connect&lt;/a&gt; with each other :)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://genicsblog.com"&gt;genicsblog.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>android</category>
      <category>authentication</category>
      <category>auth0</category>
    </item>
  </channel>
</rss>
