<?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: OkkarMin</title>
    <description>The latest articles on Forem by OkkarMin (@okkarmin).</description>
    <link>https://forem.com/okkarmin</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%2F630949%2Fb5b039c0-0236-4887-b2d4-99cd56c92758.png</url>
      <title>Forem: OkkarMin</title>
      <link>https://forem.com/okkarmin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/okkarmin"/>
    <language>en</language>
    <item>
      <title>Your own bit.ly for a grand total of $0</title>
      <dc:creator>OkkarMin</dc:creator>
      <pubDate>Sun, 20 Jun 2021 03:00:24 +0000</pubDate>
      <link>https://forem.com/okkarmin/your-own-bit-ly-for-a-grand-total-of-0-5hmi</link>
      <guid>https://forem.com/okkarmin/your-own-bit-ly-for-a-grand-total-of-0-5hmi</guid>
      <description>&lt;h2&gt;
  
  
  Sob story
&lt;/h2&gt;

&lt;p&gt;I have always wanted to have my very own url shortner because of the following reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Link will be easy to remember, for own self and for others&lt;/li&gt;
&lt;li&gt;Just plain cool. Imagine this, &lt;code&gt;https://{your-name}.ml/{whatever-you-want}&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;.ml&lt;/code&gt; becuase it is free! &lt;code&gt;.tk&lt;/code&gt; is also free. If you have some spare cash lying around, you can buy your own&lt;br&gt;
&lt;code&gt;.com&lt;/code&gt; or &lt;code&gt;.whaterver&lt;/code&gt; domain you like&lt;/p&gt;

&lt;p&gt;Okay sob story is done, let's get right down to it and here is &lt;a href="https://github.com/OkkarMin/url-shortner-app" rel="noopener noreferrer"&gt;final repository&lt;/a&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://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/OkkarMin" rel="noopener noreferrer"&gt;
        OkkarMin
      &lt;/a&gt; / &lt;a href="https://github.com/OkkarMin/url-shortner-app" rel="noopener noreferrer"&gt;
        url-shortner-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Repository for url-shortner-app post, read the post on http://okkarm.in/blog/your-own-url-shortner or https://dev.to/okkarmin/your-own-bit-ly-for-a-grand-total-of-0-5hmi
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;NextJS + ChakraUI&lt;/li&gt;
&lt;li&gt;Firebase Firestore for data storage&lt;/li&gt;
&lt;li&gt;Vercel for hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Process
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;'Purchase' domain&lt;/li&gt;
&lt;li&gt;Set up Firebase&lt;/li&gt;
&lt;li&gt;Create NextJS app&lt;/li&gt;
&lt;li&gt;Host app on vercel&lt;/li&gt;
&lt;li&gt;Add domain to vercel&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. 'Purchase' domain
&lt;/h2&gt;

&lt;p&gt;We are going to obtain free domain from &lt;a href="https://freenom.com" rel="noopener noreferrer"&gt;freenom&lt;/a&gt;. Head over there, register for an account and&lt;br&gt;
type in your desired domain in the &lt;code&gt;Find a new FREE domain&lt;/code&gt;. Really anything you like but best is to keep it short.&lt;br&gt;
I wanted &lt;code&gt;okkar.ml&lt;/code&gt; but it was taken, so I got myself &lt;code&gt;okkar.tk&lt;/code&gt; instead.&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%2F7tx1tei76d1v08l0j1br.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%2F7tx1tei76d1v08l0j1br.png" alt="Explaining how to get freenom free domain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose 12 months when asked to select the duration, you can also 'release' the domain free domain back if you happen to&lt;br&gt;
buy yourself a domain. Okay we are done with this step&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Set up Firebase
&lt;/h2&gt;

&lt;p&gt;You can use any database you are comfortable with. The shape of the data is simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"linkedin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"full_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://linkedin.com/in/okarmin/"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When user, navigate to &lt;code&gt;https://okkar.tk/linkedin&lt;/code&gt; they are going to get redirected to the full url, which is&lt;br&gt;
&lt;code&gt;http://linkedin.com/in/okarmin/&lt;/code&gt;. In general, when user visit &lt;code&gt;https://okkar.tk/[slug]&lt;/code&gt; we are going to look up for&lt;br&gt;
corresponding &lt;code&gt;full_url&lt;/code&gt; and redirect the user to it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to Firebase console&lt;/li&gt;
&lt;li&gt;Add project, any name you like, I will be using &lt;code&gt;url-shortner-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Default for rest of the options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now it should take about a minute to create the project. Once ready, click on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Continue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Firestore Database&lt;/code&gt; on the left&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Create database&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Start in test mode&lt;/code&gt;, &lt;a href="https://medium.com/@gaute.meek/firestore-and-security-1d77812715c1" rel="noopener noreferrer"&gt;this article&lt;/a&gt; will do a better job than me to discuss about securing Firestore&lt;/li&gt;
&lt;li&gt;Choose location that is nearest to your country, &lt;code&gt;asia-southeast2&lt;/code&gt; for Singapore. &lt;a href="https://firebase.google.com/docs/firestore/locations" rel="noopener noreferrer"&gt;See all Cloud Firestore locations here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have created Firestore, let's now add a document to it, click on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Start collection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;urls&lt;/code&gt; for Collection ID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Auto ID&lt;/code&gt; for Document ID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slug&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt; &lt;code&gt;github&lt;/code&gt; then &lt;code&gt;Add field&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;full_url&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;{your github link}&lt;/code&gt; then &lt;code&gt;Save&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&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%2F9x1zhj8ql918dhthoz5y.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%2F9x1zhj8ql918dhthoz5y.png" alt="Firebase Cloud Firestore state after adding one url"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add more document if you want to have more urls and remember to use same datashape of &lt;code&gt;{slug, full_url}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We now need to add new web project and get configuration values from Firebase&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on setting icon beside &lt;code&gt;Project Over&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Add app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Choose web, &lt;code&gt;&amp;lt;/&amp;gt;&lt;/code&gt; logo&lt;/li&gt;
&lt;li&gt;Give it any nickname you like, I will be using &lt;code&gt;url-shortner-app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Register&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Firebase should now give you the configurations like below
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;storageBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messagingSenderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;measurementId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&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;Keep this tab open, we will be using the config in the next step.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Create NextJS app
&lt;/h2&gt;

&lt;p&gt;We will use &lt;a href="https://github.com/vercel/next.js/tree/canary/examples/with-chakra-ui-typescript" rel="noopener noreferrer"&gt;with-chakra-ui-typescript&lt;/a&gt; starter from NextJS.&lt;br&gt;
Also npm install Firebase module to allow us to connect with Firestore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app &lt;span class="nt"&gt;--example&lt;/span&gt; with-chakra-ui-typescript url-shortner-app
&lt;span class="nb"&gt;cd &lt;/span&gt;url-shortner-app
npm &lt;span class="nb"&gt;install &lt;/span&gt;firebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can delete the &lt;code&gt;src/components&lt;/code&gt; and &lt;code&gt;pages/index.tsx&lt;/code&gt; we will not be using them.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Page for redirecting to &lt;code&gt;full_url&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;pages/[slug].tsx&lt;/code&gt; and put the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GetServerSideProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase/app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase/firestore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Slug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getServerSideProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetServerSideProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ value }&lt;/span&gt;&lt;span class="dl"&gt;"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;full_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;querySnapShot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;urls&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slug&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;==&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;querySnapShot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;full_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="na"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;full_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Slug&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We import the required modules and files&lt;/li&gt;
&lt;li&gt;Notice the &lt;code&gt;return null&lt;/code&gt;, we don't have to return any UI component as we are will be redirecting the users&lt;/li&gt;
&lt;li&gt;On page visit, &lt;code&gt;getServerSideProps&lt;/code&gt; will help us determine whether there is an entry in Firestore that has
&lt;code&gt;{slug, full_url}&lt;/code&gt; pair or not, if there is, redirect user to &lt;code&gt;full_url&lt;/code&gt;, otherwise redirect user to &lt;code&gt;/&lt;/code&gt; where 404 error
page will be shown&lt;/li&gt;
&lt;li&gt;We are only making use of 3 config options for Firebase, &lt;code&gt;apiKey, authDomain, projectID&lt;/code&gt; out of
full configuration options that we obatined from step 2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this stage, you can &lt;code&gt;npm run dev&lt;/code&gt; to test your app locally but for us we are sure that it will work :) so we don't test&lt;br&gt;
and let us directly host on vercel and your folder structure should look 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;url-shortner-app/
┣━━📁 src
┃ ┣━━📁 pages
┃ ┃ ┣━━ [slug].tsx
┃ ┃ ┣━━ _app.tsx
┃ ┃ ┗━━ _document.tsx
┃ ┗━━ theme.tsx
┣━━ .gitignore
┣━━ README.md
┣━━ next-env.d.ts
┣━━ package-lock.json
┣━━ package.json
┗━━ tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Host app on vercel
&lt;/h3&gt;

&lt;p&gt;Vercel made it extremely easy to host NextJS apps. After all, Vercel is behind NextJS. Before we can host on vercel, create new&lt;br&gt;
repository on github and push your codes to github.&lt;/p&gt;

&lt;p&gt;Now we can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login to Vercel using GitHub&lt;/li&gt;
&lt;li&gt;&lt;code&gt;New Project&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Import&lt;/code&gt; the repository that you just created and pushed&lt;/li&gt;
&lt;li&gt;Use default options and &lt;code&gt;Deploy&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After it has successfully deployed, we need to link the domain we obtained from freenom with Vercel. Click on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Domains&lt;/code&gt;, in &lt;code&gt;https://vercel.com/dashboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Add&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Select the project that was just deployed and &lt;code&gt;Continue&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Type in your domain, &lt;code&gt;okkar.tk&lt;/code&gt; for me and &lt;code&gt;Add&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should see this and take note of &lt;code&gt;Type&lt;/code&gt; and &lt;code&gt;Value&lt;/code&gt; shown:&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%2Fpnv35g4ndf7k56ug5i66.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%2Fpnv35g4ndf7k56ug5i66.png" alt="Showing the state after you have added domain to Vercel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now need to go back to freenom:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Services&lt;/code&gt; -&amp;gt; &lt;code&gt;My Domains&lt;/code&gt; -&amp;gt; &lt;code&gt;Manage Domain&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Manage Freenom DNS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Put the &lt;code&gt;Type&lt;/code&gt; and &lt;code&gt;Value&lt;/code&gt; you saw from Vercel here&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Save Changes&lt;/code&gt;&lt;/li&gt;
&lt;/ul&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%2F56jw2vtjv1zu6z7r8nvb.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%2F56jw2vtjv1zu6z7r8nvb.png" alt="Showing how A record look like on Freenom DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Give it sometime for the DNS configuration to propagate and after some time you should be able to see &lt;code&gt;Valid Configuration&lt;/code&gt;&lt;br&gt;
on Vercel. Vercel magically gave us SSL certificate as well which allows our domain to have &lt;code&gt;https&lt;/code&gt; protocol.&lt;/p&gt;

&lt;p&gt;That's it! We now have a functioning app that allows you to pass your &lt;code&gt;slug&lt;/code&gt; and redirect to &lt;code&gt;full_url&lt;/code&gt;, in my case since&lt;br&gt;
I bought domain, &lt;code&gt;https://okkarm.in/linkedin&lt;/code&gt; will be redirected to &lt;code&gt;http://linkedin.com/in/okarmin/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;Right now we are adding new urls from Firebase console, you could try to extend what we have by adding an authenticated&lt;br&gt;
page that allows you to add new urls from the app itself &lt;code&gt;https://domain.ml/addNewUrl&lt;/code&gt;. Since we use &lt;code&gt;with-chakra-ui-typescript&lt;/code&gt; starter,&lt;br&gt;
you can now use UI components to quickly build fairly nice looking pages.&lt;/p&gt;

&lt;p&gt;You could also add in Firebase analytics to keep track of how many visitors per shortened url. Tons of ways you can add on top&lt;br&gt;
of this project.&lt;/p&gt;

&lt;p&gt;With that, we end here for today, for more content like this, please hit the subscribe button and ofcourse smash that notificaiton&lt;br&gt;
bell.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>beginners</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
