<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Hrithwik Bharadwaj]]></title><description><![CDATA[Hrithwik Bharadwaj is a Full Stack Developer and a Violinist from Mysore.]]></description><link>https://blog.hrithwik.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 16:33:00 GMT</lastBuildDate><atom:link href="https://blog.hrithwik.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[You don't have to remember Linux commands anymore]]></title><description><![CDATA[Linux Commands are like GTA Cheatcodes. People with great memory remember them by heart and weaker ones write them down.
I am a hybrid, I used to remember most of the linux commands and GTA Cheatcodes but I don't have them byheart anymore
Here is why...]]></description><link>https://blog.hrithwik.dev/you-dont-have-to-remember-linux-commands-anymore</link><guid isPermaLink="true">https://blog.hrithwik.dev/you-dont-have-to-remember-linux-commands-anymore</guid><category><![CDATA[npm]]></category><category><![CDATA[AI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Sun, 28 Jul 2024 06:16:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/oZMUrWFHOB4/upload/96f65334485be0fade4a36b9c6b1afec.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Linux Commands are like GTA Cheatcodes. People with great memory remember them by heart and weaker ones write them down.</p>
<p>I am a hybrid, I used to remember most of the linux commands and GTA Cheatcodes but I don't have them byheart anymore</p>
<p>Here is why</p>
<h2 id="heading-introducing-askcmdhttpswwwnpmjscompackageaskcmd">Introducing <a target="_blank" href="https://www.npmjs.com/package/askcmd">askcmd</a></h2>
<p><a target="_blank" href="https://www.npmjs.com/package/askcmd">askcmd</a> is a command line tool which takes natural language as input and outputs commands specific to your OS.</p>
<ol>
<li><p><code>npm i askcmd -g</code></p>
</li>
<li><p>Go to <a target="_blank" href="https://console.groq.com">Groq.com</a> and get an API KEY</p>
</li>
<li><p><code>askcmd -s &lt;APIKEY&gt;</code></p>
</li>
<li><p>Start getting commands for anything like <code>askcmd show me the last 5 commitids with the message</code></p>
</li>
<li><p>Forget Linux Commands like you have forgotten routes after GPS arrived.</p>
</li>
</ol>
<p>It's <a target="_blank" href="https://github.com/hrithwikbharadwaj/askcmd">open source</a>. Would appreciate it if you <a target="_blank" href="https://github.com/hrithwikbharadwaj/askcmd">star it.</a></p>
]]></content:encoded></item><item><title><![CDATA[Why I built my own node-schedule alternative]]></title><description><![CDATA[Like on YouTube where you can schedule your videos at a specific date and time
I had a similar requirement a few months back for an LMS product. I had to publish reports of students at the end of the term. (A specific date and time)
When I googled ho...]]></description><link>https://blog.hrithwik.dev/why-i-built-my-own-node-schedule-alternative</link><guid isPermaLink="true">https://blog.hrithwik.dev/why-i-built-my-own-node-schedule-alternative</guid><category><![CDATA[npm]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Tue, 14 Nov 2023 04:57:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699940501345/d37ebc65-d2b4-4576-b7a6-6e5d90789ddf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Like on YouTube where you can schedule your videos at a specific date and time</p>
<p>I had a similar requirement a few months back for an LMS product. I had to publish reports of students at the end of the term. (A specific date and time)</p>
<p>When I googled how to schedule date-based jobs,</p>
<p>I found this package called <a target="_blank" href="https://www.npmjs.com/package/node-schedule">node-schedule</a>.</p>
<p>(Why not just use event bridge? - <a class="post-section-overview" href="#heading-why-not-use-a-managed-service-like-event-bridge">My Answer</a>)</p>
<p>Node Schedule was super easy to use, You just pass it a <strong>name</strong>, <strong>callback</strong> and the <strong>date</strong> on which the callback function should be executed.</p>
<p>But it had 2 major and 1 minor problem</p>
<ul>
<li><p><strong>Jobs weren't persistent</strong> (If I restarted my express app, the jobs were gone)</p>
</li>
<li><p><strong>Jobs weren't Atomic</strong> - If the same job was scheduled on multiple machines, then it would execute them on every machine leading to duplicate data, so you could only vertically scale your machines where jobs are running. Also cancelling the job on every machine was not possible.</p>
</li>
<li><p><strong>No Inbuilt Retry Mechanism</strong>, if a job failed, I had to catch it and then reschedule the job.</p>
</li>
</ul>
<p>To fix these things, I had previously built a class on top of <strong>node-schedule</strong> in my code base that made sure the jobs were atomic and had the rescheduling ability.</p>
<p>A similar requirement popped up in a different project recently and I decided to bundle this into a new package and that's how building <a target="_blank" href="https://www.npmjs.com/package/job-stash">job-stash</a> began.</p>
<h2 id="heading-introducing-job-stash-alternative-to-node-schedule-and-agenda">Introducing Job Stash - Alternative to Node Schedule and Agenda</h2>
<p><a target="_blank" href="https://www.npmjs.com/package/job-stash">Job Stash</a> is an npm package to schedule tasks which takes a <strong>callback function</strong> and the <strong>date</strong> on which the function has to be executed.</p>
<ul>
<li><p><strong>Persists task metadata in DB</strong> - Reschedule all the jobs using this on your app restart.</p>
</li>
<li><p><strong>Abstracts DB Implementation</strong> - Give it a Mongo DB Address(URI) and it forms a new connection. Give it a MongoDBClient and it reuses the connection.</p>
</li>
<li><p><strong>It's Atomic</strong> - If you have multiple machines running, only one of them will execute your callback function.</p>
</li>
<li><p><strong>Has an Inbuilt Retry Mechanism</strong> - if something goes wrong while executing the job, they are retried after a retry window(customisable).</p>
</li>
<li><p>Unpacked size less than 30KB.</p>
</li>
</ul>
<p>For persistence storage I am using MongoDB here since our app already used MongoDB and the idea was I could reuse the same connection.</p>
<h2 id="heading-tutorial-on-how-to-schedule-jobs-in-nodejs-using-job-stash">Tutorial on How to Schedule Jobs in Node.js using Job Stash</h2>
<h3 id="heading-step-1-install-it-on-your-project">Step 1 - Install it on your project</h3>
<pre><code class="lang-javascript">npm i job-stash
</code></pre>
<h3 id="heading-step-2-initialise-the-scheduler">Step 2- Initialise the Scheduler</h3>
<p>The scheduler has to be initialised with db credentials and other <a target="_blank" href="https://www.npmjs.com/package/job-stash#options">options</a></p>
<p>I am here reusing the db connection from Mongoose and setting <code>useLock</code> to true.</p>
<p>Making <code>useLock</code> to true ensures that if you are running a service on multiple machines, the job is executed only in one of them.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Scheduler } <span class="hljs-keyword">from</span> <span class="hljs-string">'job-stash'</span>;

<span class="hljs-keyword">await</span> Scheduler.init({ <span class="hljs-attr">mongo</span>: mongoose.connection.db }, { <span class="hljs-attr">useLock</span>: <span class="hljs-literal">true</span> });

<span class="hljs-comment">/* 
If you don't already have a mongodb connection running
use the below snippet.

await Scheduler.init(
  {
    db: {
      address: mongoConnectionString,
      collection: 'jobs',
      name: 'evaluation_service',
    },
  },
  { useLock: true }
);
*/</span>
</code></pre>
<p>Let's talk about the callback function that decides what to do when the job is executed.</p>
<p>I have a common function that decides which function to call / what to do based on a field called operation.</p>
<p>Example:</p>
<p>If my operation is equal to <code>publishReport</code> I want to call a <code>publishReport()</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decideCallback</span>(<span class="hljs-params">job</span>) </span>{
  <span class="hljs-keyword">const</span> { jobId, operation, activityType } = job;
  <span class="hljs-keyword">if</span> (operation === <span class="hljs-string">"publishReport"</span>) {
    <span class="hljs-keyword">await</span> publishReport(jobId);
  }
  <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operation === <span class="hljs-string">"gradeZero"</span> &amp;&amp; activityType === <span class="hljs-string">"quiz"</span>) {
    <span class="hljs-keyword">await</span> gradeZero(jobId);
    <span class="hljs-keyword">await</span> createQuizReport(jobId);
  }
  <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (operation === <span class="hljs-string">"gradeZero"</span>) {
    <span class="hljs-keyword">await</span> gradeZero(jobId);
  }
}
</code></pre>
<p>If you notice, the <code>decideCallback</code> function has access to a job object which includes jobId and other metadata that you store.</p>
<p>The Scheduler binds the job data inside any callback you pass to it when scheduling or rescheduling jobs.</p>
<h3 id="heading-step-3-reschedule-jobs-from-disk-to-memory-on-app-start">Step 3 - Reschedule Jobs From Disk to Memory on App Start</h3>
<p>I will now use the <code>decideCallback</code> function to reschedule all my tasks on the restart of my express app after initialising the scheduler class.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> Scheduler.init({ <span class="hljs-attr">mongo</span>: mongoose.connection.db }, { <span class="hljs-attr">useLock</span>: <span class="hljs-literal">true</span> });
<span class="hljs-keyword">await</span> Scheduler.rescheduleJobs(decideCallback)
</code></pre>
<p>the <code>Scheduler.rescheduleJobs</code> will internally fetch all the active jobs and will pass all the job data inside the <strong>decideCallback</strong> function.</p>
<p>You can use the same <strong>decideCallback</strong> function to schedule a new job too.</p>
<h3 id="heading-how-to-schedule-a-new-job">How to Schedule A New Job</h3>
<p>It's a little weird to cover rescheduling before scheduling a new job, but if you look at how you use this package in your app, You initialise it, you Reschedule all the current jobs from Disk to Memory and then based on the API Request / Event you schedule a new job.</p>
<p>Here is how you schedule a new job</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// decideCallback has access to jobId, dateToRunOn and metadata if any.</span>
<span class="hljs-comment">// the Scheduler binds this data when scheduling or rescheduling jobs.</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decideCallback</span>(<span class="hljs-params">job</span>) </span>{
  <span class="hljs-keyword">const</span> { jobId, dateToRunOn, operation } = job;
  <span class="hljs-keyword">if</span> (operation === <span class="hljs-string">"publishReport"</span>) {
    <span class="hljs-keyword">await</span> publishReport(jobId, dateToRunOn);
  }
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">scheduleJob</span>(<span class="hljs-params">jobId, dateToRun, metadata</span>) </span>{
  <span class="hljs-keyword">await</span> Scheduler.scheduleJob(decideCallback, dateToRunOn, jobId, metadata);
}

scheduleJob(
  jobId: <span class="hljs-string">'123'</span>,
  <span class="hljs-attr">dateToRunOn</span>: <span class="hljs-string">'2023-11-13T07:44:06.191Z'</span>,
  { <span class="hljs-attr">operation</span>: <span class="hljs-string">'publishReport'</span> },
);
</code></pre>
<p>When the callback function is executed(In our case <code>decideCallback</code>), it calls the function with the <code>jobId</code>, <code>dateToRunOn</code> and all the other <code>metadata</code> that means the <code>jobId</code>, <code>dateToRunOn</code> and all the other <code>metadata</code> are accessible inside decideCallback through the first argument.</p>
<p>The <code>Scheduler.scheduleJob</code> function expects a <code>callback</code>, <code>dateToRunOn</code>, <code>jobId</code> and <code>metadata</code>.</p>
<p><code>metadata</code> and <code>jobId</code> are optional</p>
<ol>
<li><p><code>metadata</code> - This is any information you want to save in the database or use to choose which function or API to call when the job runs.</p>
<p> In our case, I am storing a field called <code>operation</code> that will help me decide which function to call when the job is executed.</p>
</li>
<li><p><code>jobId</code> - If you don't pass a <code>jobId</code> then the package creates a unique UUID.</p>
<p> The <code>Scheduler.scheduleJob</code> returns a job object with a method called get <code>getJobId</code></p>
<p> You can use that to store a jobId that can be further used to cancel a job.</p>
<p> Here is how you cancel a job</p>
</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> Scheduler.cancelJob(jobId);
</code></pre>
<h3 id="heading-how-to-update-a-job">How to Update a Job</h3>
<p>Maybe you want to change the date of execution or add some new metadata to a job.</p>
<p>There is an inbuilt method that lets you update a job.</p>
<p>It accepts the same things as a <code>Scheduler.scheduleJob</code> but the only difference is that it cancels the current running job and reschedules a new one.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> Scheduler.updateJob(jobId, callback, dateToRunOn, metadata)
</code></pre>
<h3 id="heading-why-not-use-a-managed-service-like-event-bridge">Why not use a Managed Service like Event Bridge?</h3>
<p>It's not like I don't want to use Event Bridge. In fact, I use it for a couple of cron-style APIs that have to be run on specific intervals like recalculating analytics for all the links every 10 minutes for <a target="_blank" href="https://tapthe.link">tapthe.link</a> etc.</p>
<p>I also agree that managed services are great.</p>
<p>However, the use case for scheduling reports was a little different in my case.</p>
<p>Here are my requirements</p>
<ul>
<li><p>The Reports of students are usually published by the end of the term - meaning long-lived jobs.</p>
</li>
<li><p>Wanted to be accurate within 5 minutes of max delay.</p>
</li>
<li><p>I won't have more than 5000 active jobs at a given time</p>
</li>
</ul>
<p>I just didn't want to poll my DB every 2-5 minutes through a cron expression because I know that there won't be any new job the majority of the time.</p>
<p>The job should be like an event.</p>
<p>an event occurred -&gt; timestamp was hit -&gt; Job has to be executed.</p>
<p>That's why I liked the idea of using a date-based scheduler instead of polling the DB. There is an internal clock in the app that knows when to execute a job.</p>
<h2 id="heading-current-limitations-of-job-stash">Current Limitations of Job Stash</h2>
<ul>
<li><p>It <strong>requires your tech stack to be MongoDB</strong>. If you don't use MongoDB as your primary database, it doesn't make sense to introduce another DB just to support a scheduler. If you plan to make your scheduler service separate then it's still okay to have mongoDB. (Even the Free plan is more than enough)</p>
</li>
<li><p><strong>Doesn't Support Cron Job yet</strong> - It's not that hard enabling this, I just haven't worked on this yet.</p>
<p>  For now, all my cron-related things just work on Event Bridge. There is a hacky way of making interval-based things work in the current setup too, you just have to schedule a new job whenever the current job is executed but yeah , I haven't built it. will build it soon or you can build and contribute too.</p>
</li>
</ul>
<h2 id="heading-why-does-job-stash-even-exist">Why does Job Stash even exist?</h2>
<p>While there exists a plethora of packages and ways to schedule jobs. The Hackernews Community loves using <strong>systemd</strong> but that involves a lot of boilerplate code and research.</p>
<p>it's just pain.</p>
<blockquote>
<p>Job Stash exists for developers who have a Node.js codebase with MongoDB as their database and want to get a scheduler up and running within 5 minutes.</p>
</blockquote>
<p>Job Stash exists for developers</p>
<ol>
<li><p>Who have a Node.js codebase</p>
</li>
<li><p>Who have MongoDB as their database</p>
</li>
<li><p>Who like their machines to be scaled horizontally and want only one of them to execute that job</p>
</li>
<li><p>Who wants easy rescheduling of jobs on restart</p>
</li>
<li><p>Who schedules a medium scale of 50K-100K jobs</p>
</li>
<li><p>Who wants to schedule a job on a specific date and time instead of polling the database every X minutes.</p>
</li>
</ol>
<p>Do let me know what you think in the comment section.</p>
<p>Shout out to <a target="_blank" href="https://www.linkedin.com/in/prajwalp264/">Prajwal</a> who reviewed the code and motivated me into building this.</p>
]]></content:encoded></item><item><title><![CDATA[One Year Journey as a Software Developer]]></title><description><![CDATA[Here is how I wrote this blog post.
I remembered things I contributed last year.
made them into points and started expanding on how anyone can implement/learn that.
Then realised the blog post is getting long :)
Anyways, Hey everyone, I am Hrithwik, ...]]></description><link>https://blog.hrithwik.dev/one-year-journey-as-a-software-developer</link><guid isPermaLink="true">https://blog.hrithwik.dev/one-year-journey-as-a-software-developer</guid><category><![CDATA[backend]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[#DevRetro2022]]></category><category><![CDATA[#DevRetro2022 #hashnode]]></category><category><![CDATA[MongoDB]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Fri, 06 Jan 2023 19:11:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1673032154210/90460b67-723f-41ee-b5ce-8c4ae1b4e685.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here is how I wrote this blog post.</p>
<p>I remembered things I contributed last year.</p>
<p>made them into points and started expanding on how anyone can implement/learn that.</p>
<p>Then realised the blog post is getting long :)</p>
<p>Anyways, Hey everyone, I am Hrithwik, I am a Software Developer From Bangalore working at an <a target="_blank" href="https://u-next.com/">Indian EdTech Company</a>.</p>
<p>I started my journey as a Software Developer professionally last year and these are some of the things I learnt last year.</p>
<p>If you are someone who is going to work with MongoDB and Javascript, This blog post can help you learn a thing or two, just skim through the Table of Contents and choose any heading and you will learn something.</p>
<h2 id="heading-learnt-to-use-debugger-in-vscode">Learnt to use Debugger in VSCode</h2>
<p>For a guy who used to write a lot of console logs</p>
<p>Learning to use a debugger, was the first coolest thing I learnt.</p>
<p>Initially, I had set up ts-node and had done a bunch of things to set up a debugger in every project I worked on VSCode.</p>
<p>Then discovered that there is an easier way to run a debugger in VSCode.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673030142163/27c33c22-cf6d-4ec4-8c69-848d9ea9adc8.gif" alt class="image--center mx-auto" /></p>
<p>That's it :)</p>
<h2 id="heading-working-with-typescript">Working with Typescript</h2>
<p>I was a developer who started coding backend with python(flask) and then got introduced to Node.js with javascript</p>
<p>While I thought this is good, I then discovered Typescript.</p>
<p>Typescript is javascript but with types, it's pretty easy to get started with the basics, but once you start writing code, you realise how much more is there to learn.</p>
<p>Here is what I did</p>
<ul>
<li><p>Learnt some basics like data types and interfaces to contribute to the codebase in my first week.</p>
</li>
<li><p>Started using some advanced concepts like Generics and keyof in the coming weeks</p>
</li>
<li><p>Then got busy with shipping more instead of wasting time with types. (haha jk. I actively use TS and explore different open source repos like excalidraw, zod etc to get better)</p>
</li>
</ul>
<p>The amount of run time errors typescript can save you from is enormous.</p>
<blockquote>
<p>But do note that once the codebase get's huge, your type server starts acting weird, You might not get type recommendations immediately, basically, the IDE experience becomes slower, I manually restart the server most of the time to get the type get reflected immediately</p>
</blockquote>
<h2 id="heading-github-2-branch-strategy">GitHub 2 Branch Strategy</h2>
<p>Well, I knew how to use GitHub and some basic commands, but learnt a new thing called GitHub 2 branch strategy.</p>
<p>Initially, when I joined my first company, the approach was like this, I used to create a branch from develop and push all my changes to develop. Then every X weeks once, all the code from develop used to go to main.</p>
<p>Life was simple when we did this, but this has a major flaw. At one point your master branch will have all the code which is in develop and some code which is in develop is not usually stable.</p>
<p>So our Architect came up with a new strategy which we follow to raise PRs.</p>
<p>The idea is simple, we have 2 Branches, <strong>Develop</strong> and <strong>Main</strong>.</p>
<p><strong>Main has verified non-buggy code.</strong></p>
<p><strong>Develop</strong> has new features which are yet to be tested fully.</p>
<p>You take a branch from <strong>Main</strong> and create a <strong>Feature branch</strong>, Push all the code to your <strong>feature branch</strong> and raise a PR to <strong>develop</strong>. If it has no merge conflicts, good :)</p>
<p>If it does have merge conflicts, you don't take a pull from <strong>develop</strong> to your feature branch but</p>
<ul>
<li><p>You create a branch from <strong>develop</strong></p>
</li>
<li><p>Name it like <strong>dev/{featureBranchName}</strong></p>
</li>
<li><p>You merge your feature branch to the new develop branch</p>
</li>
<li><p>You will get merge conflicts, resolve them and raise a PR to develop and delete the source branch(dev/{featureBranchName})</p>
</li>
</ul>
<p>Then test the feature thoroughly in develop and then raise a PR to <strong>main</strong>, If you get merge conflicts, take a pull from main and resolve them.</p>
<blockquote>
<p>The idea is simple, Your feature branch should only have the code which you have written and the code which is in <strong>main</strong>.</p>
</blockquote>
<h2 id="heading-atomic-updates-using-transactions-in-mongo">Atomic Updates using Transactions in Mongo</h2>
<p>I will have an entire section on MongoDB Learnings but wanted to share about this before I started sharing other things</p>
<p>When I was working on personal projects, I had never thought about transactions or Atomic Updates. I had just read the theory in my engineering and never thought about it in the NoSQL context.</p>
<p>Although update and findAndModify Queries are Document Level Atomic, they by default aren't collection level atomic.</p>
<blockquote>
<p><strong>What's an Atomic Update ?</strong></p>
<p>Let's say you have an API which is changing the data in two different collections, If the update in one collection fails, the other one should not be stored as well.</p>
</blockquote>
<p>For Atomic Updates to happen through different collections we have to use transactions.</p>
<p>How do we make this work in Mongoose?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> cls = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cls-hooked'</span>);
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>);

<span class="hljs-keyword">const</span> ns = cls.createNamespace(<span class="hljs-string">'session'</span>); <span class="hljs-comment">// any name works</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initialiseTransaction</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> session = <span class="hljs-keyword">await</span> mongoose.startSession();
  session.startTransaction();
  ns.set(<span class="hljs-string">'MONGOOSE_SESSION'</span>, session);
  <span class="hljs-keyword">return</span> session;
}
</code></pre>
<p>The initialiseTransaction Function will create a session object. You can run this while starting the app and use something like <a target="_blank" href="https://www.npmjs.com/package/cls-hooked">cls-hooked</a> , which is local-storage for nodejs to share this session object to any part of your app and have several util functions like this</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getSession</span>(<span class="hljs-params"></span>)</span>{
    <span class="hljs-keyword">const</span> session = ns.get(<span class="hljs-string">'MONGOOSE_SESSION'</span>);
    <span class="hljs-keyword">return</span> session;
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">commitTransaction</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> session = ns.get(<span class="hljs-string">'MONGOOSE_SESSION'</span>);
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> session.commitTransaction();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Transaction successful!'</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.log(err);
  }
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">abortTransaction</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> session = ns.get(<span class="hljs-string">'MONGOOSE_SESSION'</span>);
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> session.abortTransaction();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.log(err);
  }
}
</code></pre>
<p>here is how you use transactions in your queries</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> result1 = <span class="hljs-keyword">await</span> Collection1.findOneAndUpdate(filter, updateData, {
  <span class="hljs-attr">session</span>: getSession(),
});
<span class="hljs-comment">// updates collection 1</span>
<span class="hljs-keyword">const</span> result2 = <span class="hljs-keyword">await</span> Collection2.findOneAndUpdate(filter, updateData2, {
  <span class="hljs-attr">session</span>: getSession(),
});
<span class="hljs-comment">// updates something in collection 2</span>
<span class="hljs-keyword">await</span> Collection3.deleteMany(filter).session(getSession());
<span class="hljs-comment">// deletes something in collection 3</span>
<span class="hljs-keyword">await</span> commitTransaction();
<span class="hljs-comment">/* commits all the values to the DB if it reaches here, if there is an 
error , you can call the abortTransaction function in your global
error handler 
*/</span>
</code></pre>
<p>For every query you use a .session() or pass it as an option and then at last you commit the data.</p>
<p>Although transactions might make the API response a little slower than usual, having a transaction manager for all your DB calls guarantees that your writes to different collections are Atomic.</p>
<p>Folks at MongoDB always recommend you to keep related data at one collection since at a document level, things are atomic by default, but what happens most of the times is , you don't have a choice but to keep your data at different collection, that's when transactions can help you</p>
<h2 id="heading-built-a-scheduler-feature-which-can-schedule-tasks-on-a-particular-datetime">Built a scheduler feature which can schedule tasks on a particular DateTime</h2>
<p>There was this requirement in the product which I am building where we had to publish a report for students on a particular day.</p>
<p>This can be anywhere from 3 weeks - 4 months.</p>
<p>The simplest approach I thought initially was to create an API which polls the DB every minute using a CRON expression. This API could have been called via AWS EventBridge.</p>
<p>But for my use case,</p>
<ul>
<li><p>The Reports are usually published after 1 month or in the semester's end (5th month)</p>
</li>
<li><p>We won't have more than 300 JOBS per batch(every 6 months)</p>
</li>
</ul>
<p>so calling the API every minute doesn't make sense.</p>
<p>Although there are many ways of building a Scheduler,</p>
<p>My idea was simple, why not schedule a different job for every task(report-publish) instead of polling the DB every min.</p>
<p>I was searching for something which can just plug into the express server and something which is not complex.</p>
<p>I started looking for packages which support date-based scheduling and found <strong>node-schedule</strong>. This can run a task on a specific date.</p>
<p>It's this easy to schedule a job</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> schedule = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node-schedule'</span>);
<span class="hljs-keyword">const</span> date = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
date.setMinutes(date.getMinutes() + <span class="hljs-number">2</span>);
<span class="hljs-comment">// runs after 2 minutes after this script is exucuted</span>

<span class="hljs-keyword">const</span> job = schedule.scheduleJob(date, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'The world is going to end today.'</span>);
});
</code></pre>
<details>
  <summary>Summary on how the package works internally</summary>
  <p>You basically send it the date and a callback function which has to be executed on that date.
Behind the scenes the package runs the callback function with a setTimout .</p>
<p> Since we know that setTimout cannot run for more than 24.8611 days , this uses a package called long-timeout  </p>
</details>

<p>This might not fit everyone's requirements, let me list down some limitations which will help you make a decision</p>
<ul>
<li><p><strong>Limitation 1:</strong> If the express app stops running or restarts, all the tasks scheduled will be flushed. (can be solved)</p>
</li>
<li><p><strong>Limitation 2:</strong> You can't upscale the service horizontally, because there may be a case where the same task can be scheduled in two different systems. (probably can be solved)</p>
</li>
<li><p><strong>Limitation 3:</strong> There is always a limit on how many jobs you can set up. If you plan to have millions of jobs, this might not be ideal.</p>
</li>
</ul>
<p>Let's address how these limitations weren’t a problem for me</p>
<h4 id="heading-fix-limitation-1-store-the-tasks-scheduled-in-a-collection"><strong>Fix Limitation 1:</strong> Store the Tasks scheduled in a collection</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671382640479/0OZbbk9pJ.png" alt class="image--center mx-auto" /></p>
<p>Whenever you schedule a job, store the information required in a collection.</p>
<p>In your express app, there is a place called app.listen which accepts a callback function which is executed when your server is ready to handle requests. Add a function which will get all the jobs from</p>
<pre><code class="lang-javascript">app.listen(port, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">/* reschedules all the jobs which are in the DB 
    when restarting the express app */</span>
    <span class="hljs-keyword">await</span> Scheduler.reScheduleAllJobs();
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Listening: http://localhost:<span class="hljs-subst">${port}</span>`</span>)
})
</code></pre>
<h4 id="heading-fix-limitation-2-scaling-issues"><strong>Fix Limitation 2:</strong> Scaling Issues</h4>
<p>If you have multiple instances running for the same service(codebase) then you will have the same tasks spawned in all the services.</p>
<p>This might be a problem especially if you are dealing with sending a notification to users. You don't want to send multiple notifications to your users for the same action.</p>
<p><strong>Here are some possible fixes.</strong></p>
<p><strong>Fix 1:</strong> Handle the multiple calls scenario in your code. if 2 requests are calling to publish the report for the user at the same time, you will publish the report only if it was not published before. Your code should use some kind of lock mechanism,</p>
<p>In MongoDB, the update queries like updateOne and findAndModify use a lock, what that means is, if two requests are trying to update the same resource, only one can update at a time.</p>
<p>so you can use an updateOne query with an if a condition like, if <code>isReportPublished</code> is false then make it true. updateOne returns an object with a property called <strong>nModified</strong> , if this value is 0 that means the document was not updated. So we send notification and other related logic only if the nModified!=0.</p>
<p><strong>Fix 2:</strong> If your code can't handle multiple jobs calling the same API at the same time for the same task, then the simple fix is to have only one job running for a particular task.</p>
<blockquote>
<p>Don't scale the Service Horizontally but do it vertically. - hahaha</p>
</blockquote>
<p>The chances of your service having downtime may be high, but since we restart the jobs, it should be alright (if you are okay with your jobs running a little later than expected due to downtime).</p>
<p>In this package <code>node-schedule</code> when scheduling the jobs, if the current date is greater than the scheduled date, it won't schedule the task, but in our case here, we need it to run immediately after restarting the service, if it failed. So you have to handle this and retry mechanisms, error notifications etc in your code.</p>
<p>You can have a separate service which just schedules jobs and runs them.</p>
<h4 id="heading-limitation-3-there-is-always-a-cap-on-the-number-of-jobs-you-can-run"><strong>Limitation 3:</strong> There is always a cap on the number of jobs you can run</h4>
<p>I want to share some numbers, depending on your requirements and scale, you can decide.</p>
<p>As I mentioned earlier, our app will not have more than 2000-3000 active jobs that are scheduled. Since we are a B2B EdTech SAAS, we usually are pre-aware of the scale.</p>
<p>This is mostly not the case with most of the SAAS products. But I ran some benchmarks.</p>
<p>Here is what I tested on a t3a.medium (AMD EPYC 7000 - 4GB RAM 2Core) EC2 Machine</p>
<p>90K Jobs to be executed at a different time in the future and 10K Jobs to be executed at the same date and time.</p>
<p>The RAM consumption went from 60MB to 140MB and the CPU Utilisation was at 95% at a point since I scheduled all the 90K jobs at once.</p>
<p>All the 10K Jobs ran within a minute. (Running 10K jobs at once took 49 seconds ).</p>
<p>This is 10X more jobs than my requirement, so I am good.</p>
<h2 id="heading-working-with-microservices">Working with Microservices</h2>
<p>Microservices are a way of building applications as a set of small, independent services. Each microservice has a specific function and can communicate with other microservices through REST APIs to perform tasks and accomplish the overall goals of the application.</p>
<p>For example, an app like Uber will have a different Microservice for finding a driver, handling payments, storing and managing reviews, user-related data etc.</p>
<p>I won't go into why to not use them or when to use them, it depends on the team size and various other things.</p>
<p>There are a few things I learnt that I want to share</p>
<ul>
<li><p>How do services communicate with others efficiently?</p>
</li>
<li><p>Can we maintain Atomicity while working with Microservices ?</p>
</li>
<li><p>Some things I didn't like</p>
</li>
</ul>
<h3 id="heading-how-do-microservices-communicate-with-each-other-efficiently">How do MicroServices Communicate with each other Efficiently?</h3>
<p>While there are different ways of inter-service communication with different protocols like GRPC, Event Driven, Thrift etc., we followed the REST HTTP approach.(Behind the scenes uses HTTP2).</p>
<p><strong>Simple Answer:</strong></p>
<blockquote>
<p>They communicate with API calls that doesn't have to go through the internet. That's it</p>
<p>You expose an endpoint and the consumer services call the API.</p>
</blockquote>
<p><strong>Importance of having a Mapping of ServiceNames, PortNumbers and BaseURL</strong></p>
<p>While working with micro-services, there must be some code/package which handles the inter-service calls easily for you.</p>
<p>It should have a mapping between all the service names, with their port number.</p>
<p>For the local communication, the port and other things can be from the mapping but for other environments, we can take the necessary values from the env variables/ AWS secrets manager.</p>
<p>You need to call this function to get the appropriate URL. Something like the getUrl function below.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServiceUrl</span>(<span class="hljs-params">serviceName: string, endPoint: string</span>) </span>{
    <span class="hljs-comment">// if we want only one of the services to point to local</span>
  <span class="hljs-keyword">const</span> localUrlExists = process.env[<span class="hljs-string">`<span class="hljs-subst">${serviceName}</span>_URL`</span>];
   <span class="hljs-keyword">if</span>(localUrlExists?.length){
        <span class="hljs-keyword">return</span> localUrlExists;
   }
  <span class="hljs-keyword">const</span> isLocal = process.env.isLocal;
  <span class="hljs-keyword">if</span> (isLocal) {
    <span class="hljs-keyword">const</span> port = getPortNumber(serviceName); <span class="hljs-comment">// stored mapping</span>
    <span class="hljs-keyword">const</span> baseUrl = constructBaseUrl(serviceName, isLocal);
    <span class="hljs-keyword">return</span> <span class="hljs-string">`http://localhost:<span class="hljs-subst">${port}</span>/<span class="hljs-subst">${baseUrl}</span>/endPoint`</span>;
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-keyword">const</span> domain = process.env.domain;
    <span class="hljs-keyword">const</span> baseUrl = constructBaseUrl(serviceName, isLocal);
    <span class="hljs-keyword">return</span> <span class="hljs-string">`https://<span class="hljs-subst">${domain}</span>/<span class="hljs-subst">${baseUrl}</span>/endPoint`</span>;
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">constructBaseUrl</span>(<span class="hljs-params">serviceName: string</span>) </span>{
  <span class="hljs-comment">// specific to your org.</span>
  <span class="hljs-keyword">const</span> version = process.env.version;
  <span class="hljs-keyword">const</span> name = getServiceBaseName(serviceName); <span class="hljs-comment">// a mapping</span>
  <span class="hljs-keyword">return</span> <span class="hljs-string">`api/<span class="hljs-subst">${version}</span>/name`</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getPortNumber</span>(<span class="hljs-params">serviceName:string</span>) </span>{
  <span class="hljs-keyword">const</span> portMap = {
    <span class="hljs-attr">userService</span>: <span class="hljs-number">4045</span>,
    <span class="hljs-attr">mapService</span>: <span class="hljs-number">4046</span>,
  };
  <span class="hljs-keyword">if</span> (!portMap[serviceName]) {
    <span class="hljs-comment">// throw Error</span>
  }
  <span class="hljs-keyword">return</span> portMap[serviceName];
}
</code></pre>
<p>The idea is, Each services can be on the same domain while they have a different path.</p>
<p>At our company we have a separate internal package which holds this mapping information.</p>
<blockquote>
<p>Imaginary Example:</p>
<p>https://uber.com/api/v2/userservice - points to userservice</p>
<p>https://uber.com/api/v2/reviewservice - points to review service</p>
</blockquote>
<h4 id="heading-isnt-it-slow">Isn't it Slow ?</h4>
<p>Isn't it slower, if we are making API calls over the internet for interservice communication?</p>
<p>Yup. But we won't make the calls through the internet from a public DNS.</p>
<p>We create a private DNS entry for the domain to the Internal Load Balancer which routes the traffic internally as if two services are talking to each other while they are running locally.</p>
<p>so the service when making an API call checks</p>
<ul>
<li><p>if there is any private DNS record for the domain</p>
</li>
<li><p>if yes, it routes the traffic to an internal load balancer</p>
</li>
<li><p>internal load balancer decides what instance will handle the request (based on rules like round robin etc) and get the resource directly from that instance without calling it through the internet</p>
</li>
</ul>
<p>If you have not configured a Private DNS and the Internal Load balancer, then the traffic will go through the normal Internet(slow).</p>
<h4 id="heading-overall-overview-for-setting-up-a-new-service">Overall Overview for setting up a new service</h4>
<ul>
<li><p>You have to Create a Mapping in the internal package.</p>
</li>
<li><p>Update the package in every other service, or in the service where the new service will be used, to begin with</p>
</li>
<li><p>Create a New Codebase with the mentioned BaseURL before the api starts ("/api/serviceName" ) and instal required packages.</p>
</li>
<li><p>Do the necessary Infra changes like adding the baseURL mapping to the deployed service.(Don't have that deep understanding about this)</p>
</li>
<li><p>If this is the first service, then you have to setup an external Load balancer, Internal Load balancer, Private, Public DNS and maybe some other steps which I might have missed.</p>
</li>
</ul>
<p>Now imagine, every time you have a new environment like Staging or UAT, you have to do this all over again.</p>
<p>This is why I was saying if you are a small team, Just keep it monolith until you hire someone who takes care of these things. (probably a nice place to plug <a target="_blank" href="https://www.qovery.com/">Qovery</a>)</p>
<p>I have personally never touched the infra side of things but my architect was sweet enough to show me how these things were setup when I asked questions around this.</p>
<h3 id="heading-few-things-which-are-annoying-in-microservices">Few things which are annoying in Microservices</h3>
<p>Let's say your PM want's a new feature like showing some extra data in a couple of pages.</p>
<p>For them it's just showing simple data in 2 pages, but for you,</p>
<p>you might have to modify 3-4 services,</p>
<p>get your code reviewed for all the services ,</p>
<p>make the necessary frontend changes</p>
<p>and get it merged to all the required branches. Oh dear this video is accurate 👇🏻</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/y8OnoxKotPQ">https://youtu.be/y8OnoxKotPQ</a></div>
<p> </p>
<p>Also, Did I forget about test cases?</p>
<p>I am a big believer in unit testcases. It might not be helpful when you are developing the code but oh boi when you are refactoring the code and want to check if all the API's are working fine, this is a huge saver.</p>
<p>But another pain is, you have to write testcases independently and mock the API response. If there is a change in the API response, you have to go in and change the testcases in all the other servies which are consuming it.</p>
<h3 id="heading-should-we-ensure-atomicity-in-microservices">Should we ensure Atomicity in Microservices ?</h3>
<p>Sure yeah, why not.</p>
<p>If you are updating something to 3 different services and one of them failed to respond, you ideally should not make the changes in all the remaining services. But this is hard and slow.</p>
<p>I think the term is called Distributed Transactions. Well in my current workplace we haven't implemented something like this because it adds more overhead, plus might add a single point of failure.</p>
<p>So No, We don't maintain Atomoicity through services but we maintain Service Level Atomoicity using MongoDB and hope for the best.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> saveDataInCourse({ endDate }); <span class="hljs-comment">// interservice call</span>
<span class="hljs-keyword">await</span> Quiz.updateOne({ <span class="hljs-attr">quizId</span>:<span class="hljs-string">"adsa"</span>}, { <span class="hljs-attr">$set</span>: { endDate } }, { <span class="hljs-attr">session</span>: getSession() }); <span class="hljs-comment">// updates the value in the service DB with sessions</span>
<span class="hljs-keyword">await</span> commitTransaction(); <span class="hljs-comment">// commits the transaction when the function is called</span>
</code></pre>
<p>Something like this where we are making an interservice call to save the quizData and then storing the quizData in the DB.</p>
<p>If the inter-service call fails, our Quiz Data doesn't save because the code won't reach commitTransaction where the actual commit happens to the DB - Good</p>
<p>if our inter-service call works but the QuizData.updateOne fails for some reason - Cry</p>
<p>I have not faced this issue though, But yeah before having any interservice logic, we can make sure our data which needs to be updated is validated in the code level and the DB mostly won't fail is what you can hope for. (especially if it's a managed service like atlas). Let me know, how you will handle this.</p>
<h2 id="heading-working-with-mongodb">Working with MongoDB</h2>
<p>MongoDB was the second NOSQL Database I tried after Firestore. It is similar to firestore but has so much more to offer like complex aggregations and compound indexes. (Both of which I have not worked on with firestore)</p>
<p>I have learnt a bunch of things while working on mongoDB from over an year.</p>
<h3 id="heading-schema-design-tips">Schema Design tips</h3>
<p>Let's start with basics, The idea of designing Schema's is simple</p>
<p>Store data in a way you want to query data.</p>
<p>While SQL recommends you store Data in a Normalized Form (Keeping Data in seprate Tables without Redundancy ) . MongoDB let's you be free, keep all the data at one place if it's queried that way, no one will ask.</p>
<p>Let's say you want to keep all the grade information of a student with his attempt information.</p>
<pre><code class="lang-javascript">{
    <span class="hljs-attr">userId</span>: <span class="hljs-string">"123"</span>,
    <span class="hljs-attr">attempts</span>: [ { <span class="hljs-attr">attemptId</span>: <span class="hljs-string">"456"</span>, <span class="hljs-attr">attemptName</span>: <span class="hljs-string">"sda"</span> }]
    <span class="hljs-attr">userName</span>: <span class="hljs-string">"Hsb"</span>
}
</code></pre>
<h3 id="heading-indexes-the-esr-rule">Indexes - The ESR Rule</h3>
<p>A MongoDB index is like an index in a library, but for a database. It helps the computer find things in the database more quickly. Instead of going through the entire library to find your book, you know where your book is located through an index.</p>
<p>This is the only thing I knew when I started working with MongoDB. I had created a bunch of primary indexes for a couple of collections, I knew they were fast and consumed memory to store them.</p>
<p>But at some use cases at my work, just querying with one field was not enough, there were multiple fields in the query.</p>
<p>let's say you want to query all the PRO Users from Bangalore.</p>
<pre><code class="lang-javascript">db.collection.find({ <span class="hljs-attr">membershipType</span>: <span class="hljs-string">"PRO"</span>, <span class="hljs-attr">location</span>: <span class="hljs-string">"Bangalore"</span>})
</code></pre>
<p>Assuming we have added an index for <strong>membershipType,</strong> this will be fast but mongo has to still filter out the records for location:"Bangalore" without an index. That means if there are 10,000 users with 500 Pro users and 10 Pro users from bangalore, the Index will definitely help us limit the data to 500 records but it has to still filter out and get you just 10 users in memory.</p>
<p>That's why we create a compound index like</p>
<p>{ <strong>membershipType:1, location:1</strong> }. Mongo will return just 10 users using the index.</p>
<p>Now if you want to get the latest Pro users from Bangalore and assuming you are having a field called createdAt, then you should create an compound index with</p>
<p>{ <strong>membershipType: 1, location: 1, createdAt: 1 }</strong></p>
<pre><code class="lang-javascript">db.users.find({ <span class="hljs-attr">membershipType</span>: <span class="hljs-string">"PRO"</span>, <span class="hljs-attr">location</span>: <span class="hljs-string">"Bangalore"</span>}).sort({ <span class="hljs-attr">createdAt</span>: <span class="hljs-number">-1</span> })
</code></pre>
<p>Now if you want to get the latest Pro users from Bangalore who have spent more than 150K in total, then your query will be like</p>
<pre><code class="lang-javascript">
db.users.find({ 
<span class="hljs-attr">membershipType</span>: <span class="hljs-string">"PRO"</span>,
<span class="hljs-attr">location</span>: <span class="hljs-string">"Bangalore"</span>, 
<span class="hljs-attr">amountSpent</span>: { <span class="hljs-attr">$gt</span>: <span class="hljs-number">150000</span> }
}).sort({ <span class="hljs-attr">createdAt</span>: <span class="hljs-number">-1</span> })
</code></pre>
<p>If you are thinking to add an index like { <strong>membershipType: 1, location: 1, amountSpent: 1, createdAt: 1 }</strong></p>
<p>you might not get the optimal results. The right way to do this is like this</p>
<p>{ <strong>membershipType: 1, location: 1, createdAt: 1, amountSpent: 1 }</strong></p>
<blockquote>
<p>Yes, the order matters. It's based on a Rule called ESR.</p>
<p>Equality , Sort , Range.</p>
<p><strong>membershipType: "PRO"</strong> is the equality match</p>
<p><strong>.sort({ createdAt: -1 }</strong> is the sort</p>
<p><strong>amountSpent: { $gt: 150000 }</strong> is the range operation</p>
</blockquote>
<p>Our compound indexes should follow this rule to get data in the most efficient way.</p>
<p>Don't just add compound indexes everywhere, if you know that with a single index or a compound index with less fields is going to filter data with less records then you don't have to create index for all the terms for the query.</p>
<h2 id="heading-adding-index-to-array-of-elements">Adding Index to Array of Elements</h2>
<p>MongoDB suggests you to have related data in one place.</p>
<p>Imagine that there is a quiz which can have a bunch of questions with this schema.</p>
<pre><code class="lang-jsx">    {
  <span class="hljs-attr">quizId</span>: string,
  <span class="hljs-attr">questions</span>: [{ <span class="hljs-attr">questionId</span>: string, <span class="hljs-attr">marks</span>: number, <span class="hljs-attr">title</span>: string }],
  .......
};
</code></pre>
<p>Now if you want to see, in how many quizes the same question is used ? You can write a query like</p>
<pre><code class="lang-jsx">{ <span class="hljs-string">"questions.questionId: "</span><span class="hljs-number">123</span><span class="hljs-string">" } // searching for the questionId 123</span>
</code></pre>
<p>This will scan the entire document if it’s not indexed. Here is how you can create an index for this using mongoose</p>
<pre><code class="lang-jsx">schema.index({ <span class="hljs-string">"questions.questionId"</span>: <span class="hljs-number">1</span> });
</code></pre>
<p>This was a total new discovery for me.</p>
<p>(Also, the above was just an example to show array of elements index, instead of querying it with an index, I would just store and increment the count in the questions collection whenever it’s used in an quiz)</p>
<p>The concept of having correct indexes has helped me improve the performance of multiple data fetching API by effectively indexing the values.</p>
<h3 id="heading-aggregation">Aggregation</h3>
<p>Aggregation is a powerful framework in mongo which can help you get complex computed data right from the database.</p>
<p>You won't need this unless you have to show some complex data which comes different places like in a dashboard or need to format data in a particular way. You write a series of pipelines for operations and it finally works.</p>
<p>While skimming through the codebase in the first week of my joining,</p>
<p>I was weirded out about what's happening seeing some crazy aggregation pipelines. I was scared of it to be honest.</p>
<p>After few months, I had to use aggregation for a feature and discovered this playlist on Aggregation from <a target="_blank" href="https://www.youtube.com/watch?v=dNXID1rZ5qU&amp;list=PLYxzS__5yYQmr3HQQJMPBMbKtMY37sdsv&amp;ab_channel=codedamn">Codedamn</a> and this totally gave me the confidence/motivation to get started.</p>
<p>Then started exploring it more and started playing around with it using the MongoDB Compass Aggregation Tab, This is such a good thing in MongoDB Compass. You can visualise what each pipleine is doing</p>
<p>I will share a step by step guide into getting started with aggregation in my other post, coming soon :)</p>
<h2 id="heading-built-a-notion-to-blog-using-the-official-notion-api">Built a Notion to Blog using the Official Notion API</h2>
<p>I have a side hustle called <a target="_blank" href="http://app.tapthe.link">tapthe.link</a> which can redirect people directly to the youtube app instead of youtube.com while sharing links on Tiktok.</p>
<p>I wanted to explore writing some articles for boosting SEO and also wanted to learn something new.</p>
<h3 id="heading-why-notion">Why Notion ?</h3>
<p>I spend a lot of my time on notion every day, so something like notion to Blog is what I was looking into.</p>
<p>So 10 months back, I built <a target="_blank" href="http://app.tapthe.link/blog">app.tapthe.link/blog</a> , where I just update something in my notion page and it's reflected the site within 5 minutes.</p>
<h3 id="heading-features-of-the-blog">Features of the Blog</h3>
<ul>
<li><p>Custom CTA at the end of each blog which comes from notion, if enabled</p>
</li>
<li><p>Custom OG Images compatible for all social media platforms</p>
</li>
<li><p>sitemap and robots.xml</p>
</li>
<li><p>Table of Contents (straight out copied the UI from hashnode because of how good it is, I hope they don't mind 🙏🏻 )</p>
</li>
</ul>
<p>The implementation used notion's Official API</p>
<p>-&gt; The API returns data in JSON blocks</p>
<p>-&gt; That get's converted into Markdown using <a target="_blank" href="https://github.com/souvikinator/notion-to-md">Notion-to-md</a></p>
<p>-&gt; Uses different Rehype plugins to format to HTML</p>
<p>-&gt; Uses Custom Code to generate TOC</p>
<p>-&gt; Get styled with tailwind typography</p>
<p>-&gt; Blog Ready.</p>
<p>If you want to build your own notion to blog, check this <a target="_blank" href="https://github.com/dharshatharan/dharsh.dev">repository</a> out. You can add other custom features on top of this.</p>
<h3 id="heading-why-didnt-i-just-use-rehype-toc">Why didn't I just use Rehype TOC ?</h3>
<p>Well, I did that in the first, it just took me to 3 minutes to add a TOC. I was mind blown by how easy it is to add a TOC. But the UI sucked</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672766332966/c61efec6-6018-472f-bc51-a1f77f891bce.png" alt class="image--center mx-auto" /></p>
<p>In my mind, I wanted a TOC just like hashnode and I coudn't figure out how to customise Rehype TOC to make it look and work like that.</p>
<p>That's why I added my own custom logic which will parse the markdown, form the structure I need to build a TOC and then uses getBoundingClientRect to get the height after which the the TOC Dropdown has to be closed. It's not as perfect as hashnode, but I didn't want to spend a lot of time perfecting it since I had already spent a good 4-5 days on making this work.</p>
<p>Shoutout to my friend rahul who is there to listen to me share everything I build lol.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672766705977/98b731de-8530-4cee-b8d1-b0fddc0bf5fe.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-improved-performances-of-apis">Improved Performances of API's</h2>
<p>While working on a particular feature on top of an existing module I started noticing that the API was really slow and there was something really bad happening there.</p>
<p>I didn't really do some black magic and made things faster, just did some basic optimisations and brought down the API response times from 3-6 seconds to 200ms in one of the API. I have already written about it here in my <a target="_blank" href="https://blog.hrithwik.me/3-basic-things-you-can-do-to-improve-api-performance-in-nodejs">previous blog post.</a></p>
<blockquote>
<p>It was basically , Right Indexing + Reducing Time Complexity + Reducing Bandwidth by projecting only required fields + Concurrent GET Calls wherever possible.</p>
</blockquote>
<h2 id="heading-learnt-about-pre-commit-hooks">Learnt about Pre Commit Hooks</h2>
<p>We use swagger to document our API. It basically allows you to document your API's by writing some lengthy ass structure like</p>
<p>wait, let me show you.</p>
<p>Here is an API to fetch users from a particular location.</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">/**
   *
   * <span class="hljs-doctag">@swagger</span>
   * /api/userservice/users/?location={location}:
   *  get:
   *    summary: Fetch Users from a location
   *    tags: [Users]
   *    parameters:
   *      - in: query
   *        name: location
   *        schema:
   *          type: string
   *        example: false
   *        required: true
   *        description: location of the user
   *    responses:
   *      200:
   *        description: Successfully retrieved the user
   *        content:
   *          application/json
   */</span>
</code></pre>
<p>This is how much code you have to add for a simple user fetching API from a location. This is used in most companies.</p>
<p>Now if you make any indentation mistakes or miss a semi column , the code build won't happen.</p>
<p>What used to happen is sometimes is ,</p>
<p>I used to make some silly mistakes like missing a semi column while writing the swagger doc and before pushing the code , I was not generating the docs everytime to verify if my documentation code was proper. The code used to get to develop and the deployment used to fail.</p>
<p>Why ? - There was a semi column missing haha</p>
<p>There is something called husky which will let you add some commands to be run before you commit your code to git. I added this command</p>
<pre><code class="lang-javascript">npm run generate-docs
<span class="hljs-comment">// will genereate docs if the syntax is proper, if not will throw error.</span>
</code></pre>
<p>Has saved me so much of trouble.</p>
<h2 id="heading-started-writing-unit-test-cases">Started Writing Unit Test Cases</h2>
<p>Here is what Unit test cases are,</p>
<p>you as a developer will write some positive and negative test cases of your API.</p>
<p>Something like, if your API is expected to send a "pong" message when you send it "ping" and you receive the same message while running the API, the test was successful.</p>
<p>Some other testcase can be like this, If someone sends pingg instead of ping, your API will throw error like "Unkown Input" with 400 status code. If you get the same error message while sending the same input then your test was succeeded.</p>
<h3 id="heading-initial-reaction">Initial Reaction</h3>
<p>Oh boi, I felt like I am wasting a lot of time on this, what can go wrong ? In 10 days sprint , I need to develop features + also write testcases for the expectations which is already in my mind, what a waste of time.</p>
<p>Then came a refactor. Oh boi, unit test cases saved so much time. What do I mean ?</p>
<p>Unit testcases makes your code more maintainable for the future,</p>
<p>Let's say, If some other developer touches something and breaks it in the code to fix a bug which has impact on a lot of API's. When running the tests, all the API's which have dependency will fail. You realise you have made a mistake .</p>
<p>Downside: On every feature improvement, you have to not only develop new features but also change the testcases in all dependant APIs.</p>
<h3 id="heading-how-to-do-it">How to do it ?</h3>
<p>You can write unit testcases with the help of Two Libraries, Mocha and Chai.</p>
<p>Here is an example</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { expect } <span class="hljs-keyword">from</span> <span class="hljs-string">"chai"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"mocha"</span>;

<span class="hljs-keyword">const</span> httpClient = axios.create({
  <span class="hljs-attr">baseURL</span>: <span class="hljs-string">'https://my-api.com/api/'</span> <span class="hljs-comment">// your baseurl</span>
});

describe(<span class="hljs-string">"Create a Bookmark for a Content"</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> courseId = Utils.generateUuid();
  <span class="hljs-keyword">const</span> contentId= Utils.generateUuid();


 before(<span class="hljs-keyword">async</span> () =&gt;{
    <span class="hljs-keyword">await</span> createContent(courseId, contentId);
  });

it(<span class="hljs-string">'throws an error if course is not provided'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> verifyAsyncError(
    <span class="hljs-string">`400 - "courseOfferingId may not be null, undefined or blank"`</span>,
    <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> httpClient.post(
        <span class="hljs-string">'/bookmarks/'</span>,
        {
          <span class="hljs-attr">elementId</span>: elementId,
        },
        {
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-attr">authorization</span>: jwttoken,
          },
        }
      );
    }
  );
});

it(<span class="hljs-string">'sucessfully creates a bookmark for content '</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> httpClient.post(
    <span class="hljs-string">'/bookmarks/'</span>,
    {
      <span class="hljs-attr">courseOfferingId</span>: courseOfferingId,
      <span class="hljs-attr">elementId</span>: elementId,
    },
    {
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-attr">authorization</span>: jwttoken,
      },
    }
  );
  expect(_.isEqual(elementId, result.elementId));
  expect(_.isEqual(<span class="hljs-literal">true</span>, result.isBookmarked));
});

after(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> httpClient.delete(<span class="hljs-string">'/bookmarks/clear-depencencies'</span>, {
    <span class="hljs-attr">headers</span>: {
      <span class="hljs-attr">authorization</span>: jwttoken,
    },
  });
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">verifyAsyncError</span>(<span class="hljs-params">expectedErrMsg, callback</span>) </span>{
  <span class="hljs-keyword">let</span> errMsg = <span class="hljs-string">''</span>;
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> callback();
  } <span class="hljs-keyword">catch</span> (err) {
    errMsg = err.message;
  }
  <span class="hljs-keyword">let</span> substringMatch = errMsg.indexOf(expectedErrMsg) !== <span class="hljs-number">-1</span>;
  <span class="hljs-keyword">if</span> (!substringMatch) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Expected:'</span>, expectedErrMsg);
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Actual:'</span>, errMsg);
  }
  chai_1.expect(substringMatch).to.be.true;
}
</code></pre>
<p>There are Three Things you need to know.</p>
<ul>
<li><p>Describe - Describes a Feature you want to test</p>
</li>
<li><p>before/after - What has to be done before and after running the testcases</p>
</li>
<li><p>it - It's a function which accepts a description and a callback function to be executed.</p>
</li>
</ul>
<p>But do note that,</p>
<p>If running testcases is not in your pre-deployment procedure and your developers are not updating their testcases on every feature improvement, then it's as good not keeping them in the codebase.</p>
<h2 id="heading-data-patches-in-production">Data Patches in Production</h2>
<p>So I don't know if I mentioned earlier, but I work at an EdTech company and we offer our LMS to some B2B Clients. Now sometimes few of these customers want to get their old data migrated to our LMS.</p>
<p>Something like</p>
<p>"We have these students who have taken the quiz on google form, and we want this to be imported to the LMS".</p>
<p>Or</p>
<p>"We have received the submission offline on google drive and want that to be imported to the LMS"</p>
<p>So a script should get this data from their excel sheet, convert it to the format your LMS expects, add all the dependencies like metadata etc and finally make it work.</p>
<p>This was a super fun and challenging task. Loved it</p>
<h2 id="heading-end">End</h2>
<p>Now that I look into the past while writing this article, I have learnt a lot of new things, it's just the beginning, my stomach is not filled, I am hungry for more.</p>
<p>What's for 2023 ?</p>
<ul>
<li><p>I want to build more useful tools like <a target="_blank" href="https://tapthe.link">tapthe.link</a></p>
</li>
<li><p>I want to explore React Native and want to go deep into reading research papers and engineering blogs :)</p>
</li>
</ul>
<p>If there is something here which you don't agree or is wrong, you can let me know, I am still a newbie and it's still day one for me.</p>
]]></content:encoded></item><item><title><![CDATA[3 Basic Things you can do to improve API Performance in Node.Js]]></title><description><![CDATA[I spent the last week improving the performance of a few APIs at work and improved response Times by 5X.
I just did 3 basic things which improved performance in most of the API routes.
This blog is really helpful especially if you are new to Javascri...]]></description><link>https://blog.hrithwik.dev/3-basic-things-you-can-do-to-improve-api-performance-in-nodejs</link><guid isPermaLink="true">https://blog.hrithwik.dev/3-basic-things-you-can-do-to-improve-api-performance-in-nodejs</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[performance]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Sun, 31 Jul 2022 03:54:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659239522944/KWqWTXBGx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I spent the last week improving the performance of a few APIs at work and improved response Times by 5X.</p>
<p>I just did 3 basic things which improved performance in most of the API routes.</p>
<p>This blog is really helpful especially if you are new to Javascript so let's get right into the solution.</p>
<blockquote>
<p>Do note that our REST APIs are built using Node.js+ typescript+mongoDB and this guide might use a few concepts that are applicable only to this.</p>
</blockquote>
<h2 id="heading-using-promiseall">Using Promise.all()</h2>
<p>When reviewing old code, I could see something like this</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> getUser(userId);
<span class="hljs-keyword">const</span> quizData = <span class="hljs-keyword">await</span> getScore(activityId, userId);
<span class="hljs-keyword">const</span> attemptData = <span class="hljs-keyword">await</span> getAttemptData(activityId, userId);
</code></pre>
<p><code>This is just an example, not the actual code from work</code></p>
<p>Here is what's happening, </p>
<ul>
<li>We wait till the user data is fetched and then</li>
<li>We wait for quizData to be fetched</li>
<li>and then fetch the attemptData. </li>
</ul>
<p>Now if you notice quizData is not dependant on user data and attemptData is not dependant on quizData, then why are we waiting until the previous promise is resolved?</p>
<p>We can concurrently fetch non-dependable values and literally 2X API performance.</p>
<p>Here is how you do it</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [user, quizData, attemptData] = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all([ 
getUser(userId), 
getScore(activityId, userId), 
getAttemptData(activityId, userId)
]);
</code></pre>
<p>Let's say your API was taking 700ms, this brings it down close to 300 - 350ms. </p>
<h2 id="heading-reducing-db-calls">Reducing DB Calls</h2>
<p>One of the other optimisations you can do is to reduce DB calls as much as possible.  Let me explain</p>
<p>Let's say you have 5 userIds and you want to fetch user details for it. </p>
<p>Here is the bad way, You are getting user details one by one</p>
<pre><code><span class="hljs-keyword">const</span> userIds = [<span class="hljs-string">'123'</span>, <span class="hljs-string">'345'</span>, <span class="hljs-string">'442'</span>, <span class="hljs-string">'567'</span>, <span class="hljs-string">'998'</span>];

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserDetails</span>(<span class="hljs-params">userIds</span>) </span>{
<span class="hljs-keyword">const</span> userDetails = [];
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> userId <span class="hljs-keyword">of</span> userIds) {
    <span class="hljs-keyword">const</span> userDetail = <span class="hljs-keyword">await</span> fetchUserDetails(userId);
    userDetails.push(userDetail);
  }
  <span class="hljs-keyword">return</span> userDetails;
}

<span class="hljs-keyword">const</span> users = <span class="hljs-keyword">await</span> getUserDetails(userIds);
</code></pre><p>This code becomes slower and slower when the user list grows.</p>
<p>Here we are making 5 different Inter-service API/DB calls to get 5 different resources.</p>
<p>Ideally, you shouldn't do this. </p>
<p>Here is how you reduce this to just one DB call</p>
<p>You can just do this </p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserDetails</span>(<span class="hljs-params">userIds</span>) </span>{
  <span class="hljs-keyword">const</span> userDetails = <span class="hljs-keyword">await</span> fetchUserDetails(userIds);
  <span class="hljs-keyword">return</span> userDetails;
}
</code></pre>
<p>As you can see there is just one function call where we are awaiting and the <code>fetchUserDetails(userIds)</code> should get all resources in one DB call.</p>
<p>For example in MongoDB here is what the implementation of this function will look like</p>
<pre><code><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUserDetails</span>(<span class="hljs-params">userIds</span>)</span>{
<span class="hljs-keyword">const</span> userDetails  = <span class="hljs-keyword">await</span> User.find(userId: { <span class="hljs-attr">$in</span>: userIds  });
<span class="hljs-keyword">return</span> userDetails;
}
</code></pre><p>In mongoDB you can use <a target="_blank" href="https://www.mongodb.com/docs/manual/reference/operator/query/in/">$in</a> operator which can query against an array of values.</p>
<h2 id="heading-avoiding-cursorskip-in-pagination">Avoiding <code>cursor.skip</code> in Pagination</h2>
<blockquote>
<p>You can skip this part if you don't use mongoDB.</p>
</blockquote>
<p>Pagination is a concept used to divide the data into pages and send only required data one by one to save bandwidth and to have faster response times.</p>
<p>I still remember how my friend Shithij explained pagination in one line with an example of P**n Hub 3 years back. 
"The 1,2,3 button you use, till you get the right video"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659187224727/Ovoj0A1Ls.png" alt="IMG_20220730_133336.png" /></p>
<p>We can implement Pagination in MongoDB using two methods called skip and limit</p>
<pre><code>    <span class="hljs-comment">// Page 1</span>
    await User.find().limit(<span class="hljs-number">5</span>)

    <span class="hljs-comment">// Page 2</span>
    await User.find().skip(<span class="hljs-number">5</span>).limit(<span class="hljs-number">5</span>)

    <span class="hljs-comment">// Page 3</span>
    await User.find().skip(<span class="hljs-number">10</span>).limit(<span class="hljs-number">5</span>)
</code></pre><p><code>cursor.limit</code> is used to indicate the size of the document and <code>cursor.skip</code> is used to skip to the next set of documents.</p>
<blockquote>
<p>To get Page 2, we say something like give me 5 documents after skipping 5 documents</p>
</blockquote>
<p>But the problem with this in Mongo is that <code>cursor.skip</code> has to traverse through all the data until it finds the right one.</p>
<p>So Let's say there are 100K Records and you want the last page, mongo has to go through all documents from the first to skip through documents. There is no way around this if you are implementing Specific Page Pagination (Basic Pagination).</p>
<p>But for my project, we have a dashboard where a teacher can view all comments from students serially with Infinite Scrolling.</p>
<p>It's basically like viewing YouTube comment section</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659187855563/TdX1fpdnL.gif" alt="ezgif.com-gif-maker (1).gif" /></p>
<p>If you also want to implement something like this (serial pagination/ infinite scrolling) then you don't actually need <code>cursor.skip</code></p>
<p>We can implement  Key-Set Pagination and Optimise Speed</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659164687913/81kHOU4RB.png" alt="image.png" />
<a target="_blank" href="https://medium.com/swlh/mongodb-pagination-fast-consistent-ece2a97070f3">Source</a> </p>
<p>How does this work?</p>
<p>In Key-Set Pagination, we use the _id property which Mongo Stores to retrieve the next set of records.
Something like</p>
<pre><code>     <span class="hljs-comment">// Page 1</span>
    <span class="hljs-keyword">await</span> User.find().limit(<span class="hljs-number">5</span>)

    <span class="hljs-comment">// Page 2</span>
    last_id = ...  # <span class="hljs-keyword">get</span> last_id from the client
    <span class="hljs-keyword">await</span> User.find({<span class="hljs-string">'_id'</span>: {<span class="hljs-string">'<span class="hljs-subst">$gt</span>'</span>: last_id}}).limit(<span class="hljs-number">5</span>)

    <span class="hljs-comment">// Page 3</span>
    last_id = ... # <span class="hljs-keyword">get</span> last_id from the client
    <span class="hljs-keyword">await</span> User.find({<span class="hljs-string">'_id'</span>: {<span class="hljs-string">'<span class="hljs-subst">$gt</span>'</span>: last_id}}).limit(<span class="hljs-number">5</span>)
</code></pre><blockquote>
<p>The query to get Page 2 is something like  "Get me 5 Documents whose _id is greater than last_id"</p>
</blockquote>
<p>the reason why this works is that _id is stored in a sorted order based on timestamps. Here is a screenshot from the <a target="_blank" href="https://www.mongodb.com/docs/manual/reference/bson-types/#objectid">Mongo Doc</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659165293567/2V0G6t_md.png" alt="Screenshot 2022-07-30 at 12.44.23 PM.png" /></p>
<p>Basically, If you insert Two Documents into a Collection, The first Record's _id is less than the second _id</p>
<p>_id is indexed by default by MongoDB and even $gt and $lt comparisons can be done in O(1) [ Fast] </p>
<p>and your client can store the latest last_id and send it in the request body.</p>
<p><strong>Extra Tip:</strong> If you want to get the latest documents while having serial pagination you can do something like this</p>
<pre><code>   <span class="hljs-comment">// Page 1</span>
    <span class="hljs-keyword">await</span> User.find().limit(<span class="hljs-number">5</span>).sort({ _id: <span class="hljs-number">-1</span> })

    <span class="hljs-comment">// Page 2</span>
    last_id = ...  # <span class="hljs-keyword">get</span> last_id from the client
    <span class="hljs-keyword">await</span> User.find({<span class="hljs-string">'_id'</span>: {<span class="hljs-string">'<span class="hljs-subst">$lt</span>'</span>: last_id}}).sort({ _id: <span class="hljs-number">-1</span> }).limit(<span class="hljs-number">5</span>)

    <span class="hljs-comment">// Page 3</span>
    last_id = ... # <span class="hljs-keyword">get</span> last_id from the client
    <span class="hljs-keyword">await</span> User.find({<span class="hljs-string">'_id'</span>: {<span class="hljs-string">'<span class="hljs-subst">$lt</span>'</span>: last_id}}).sort({ _id: <span class="hljs-number">-1</span> }).limit(<span class="hljs-number">5</span>)
</code></pre><h2 id="heading-miscellaneous-tips">Miscellaneous  Tips</h2>
<h3 id="heading-keep-all-related-data-together">Keep all Related Data Together</h3>
<p>As simple as it looks, this is sometimes missed. You need to design the schema based on how and what you want to query so that you can query all data in one go. </p>
<p>So Plan properly yo</p>
<h3 id="heading-try-avoiding-for-loop-inside-for-loop">Try Avoiding For Loop Inside For Loop</h3>
<p>If you are using a for-loop inside a for-loop(nested loop), there is usually a way to reduce it to one for-loop.</p>
<p>For Example, Let's say you want to send user information with game score which comes from a different source.  You might do something like this</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserDetailsWithScore</span>(<span class="hljs-params"></span>) </span>{
  const userDetails <span class="hljs-operator">=</span> [
    { userId: <span class="hljs-string">'123'</span>, name: <span class="hljs-string">'X'</span> },
    { userId: <span class="hljs-string">'345'</span>, name: <span class="hljs-string">'Y'</span> },
  ];

  const gameResults <span class="hljs-operator">=</span> [
    { userId: <span class="hljs-string">'123'</span>, score: <span class="hljs-number">50</span> },
    { userId: <span class="hljs-string">'345'</span>, score: <span class="hljs-number">20</span> },
  ];

  <span class="hljs-keyword">for</span> (const user of userDetails) {
    <span class="hljs-keyword">for</span> (const result of gameResults) {
      <span class="hljs-keyword">if</span> (result.userId <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> user.userId) {
        user.score <span class="hljs-operator">=</span> result.score;
      }
    }
  }
  <span class="hljs-keyword">return</span> userDetails;
}

console.log(getUserDetailsWithScore());
</code></pre><p>If you write something like this which has 2 for-loops or you use <code>Array.prototype.find()</code> inside the for-loop, this is a bad practice and your time complexity becomes O(n^2).</p>
<p>Here is how I would do it.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserDetailsWithScore</span>(<span class="hljs-params"></span>) </span>{
  const userDetails <span class="hljs-operator">=</span> [
    { userId: <span class="hljs-string">'123'</span>, name: <span class="hljs-string">'X'</span> },
    { userId: <span class="hljs-string">'345'</span>, name: <span class="hljs-string">'Y'</span> },
  ];

  const gameResults <span class="hljs-operator">=</span> [
    { userId: <span class="hljs-string">'123'</span>, score: <span class="hljs-number">50</span> },
    { userId: <span class="hljs-string">'345'</span>, score: <span class="hljs-number">20</span> },
  ];

  const userScoreMap <span class="hljs-operator">=</span> {};

  gameResults.forEach((result) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
    userScoreMap[result.userId] <span class="hljs-operator">=</span> result.score;
  });

  <span class="hljs-keyword">for</span> (const user of userDetails) {
    user.score <span class="hljs-operator">=</span> userScoreMap[user.userId] ? userScoreMap[user.userId] : <span class="hljs-number">0</span>;
  }
  <span class="hljs-keyword">return</span> userDetails;
}

const userDetails <span class="hljs-operator">=</span> getUserDetailsWithScore();
</code></pre><p>We can find one common value in both collections and then can keep that as a key and create an ObjectMap, so our Key, in this case, becomes <code>userId</code> and we store score like this <code>userScoreMap[userId] = score</code>. </p>
<blockquote>
<p>Do you know how much faster the second approach is?</p>
</blockquote>
<p>If you run the same code but with userDetails and gameResults having 100K records, the code with a nested loop takes 27 seconds to run and the latter one takes 18 milli seconds. You get the idea, Try to avoid nested loops</p>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>These are a few basic optimisations you can do in your project and improve response times and bandwidth. </p>
<p>I hope you learnt something new and if you did go ahead and click on all the reaction emojis hashnode gives you.</p>
<p>Also If you have some other tips, do put them in the comment sections-</p>
]]></content:encoded></item><item><title><![CDATA[How to add Modern Installation UI for your PWA]]></title><description><![CDATA[A few days back, I uninstalled the Twitter app and switched to the web app and I noticed something,
Twitter had like a different/modern Installation UI for its PWA. 
(Know more about PWAs here.)

I was like, Woah, this looks so dope and better than t...]]></description><link>https://blog.hrithwik.dev/how-to-add-modern-installation-ui-for-your-pwa</link><guid isPermaLink="true">https://blog.hrithwik.dev/how-to-add-modern-installation-ui-for-your-pwa</guid><category><![CDATA[PWA]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Sat, 28 May 2022 17:20:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653758164570/v2rr5BXv4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few days back, I uninstalled the Twitter app and switched to the web app and I noticed something,</p>
<p>Twitter had like a different/modern Installation UI for its PWA. 
(Know more about PWAs <a target="_blank" href="https://blog.hrithwik.me/convert-your-website-into-an-app-easily">here</a>.)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653756993280/c8GVkeV88.png" alt="tapthelink(4).png" /></p>
<p>I was like, Woah, this looks so dope and better than that boring installation screen, which most of the PWAs have, This is also similar to Playstore like UI with an image carousel</p>
<p>If you didn't know, here is how most of the PWA Installation Screen Look</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653757330010/ndVZrJF4u.png" alt="tapthelink(6).png" /></p>
<p>Now I wanted this installation UI for my PWA too, so started digging and Initially, I thought this might be some custom implementation of the Installation UI but then, I visited https://twitter.com/manifest.json.</p>
<p>and I noticed a new property called screenshots in the manifest JSON file, and the src property had the same images which we saw in the installation screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653755334975/fgE5obGFA.png" alt="image.png" /></p>
<p>Turns out, there is an option to turn this new Installation UI by just adding a bunch of screenshots of your app.</p>
<p>I just copied the same width and height of screenshots from twitter and created some images on <a target="_blank" href="https://www.canva.com/">Canva</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653756533153/V1wiygInB.gif" alt="ezgif.com-gif-maker(1).gif" /></p>
<p>you can follow any height and width which falls under this <a target="_blank" href="https://web.dev/add-manifest/#screenshots">critera</a>.</p>
<p>Now, time to add the screenshots property with images we created into the manifest.json</p>
<pre><code class="lang-json"> <span class="hljs-string">"screenshots"</span>: [
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"https://abs.twimg.com/responsive-web/client-web/twitter-lite-data-saver-marketing.68059867.png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"586x1041"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"https://abs.twimg.com/responsive-web/client-web/twitter-lite-explore-marketing.fd45b027.png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"586x1041"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>
    },
    {
      <span class="hljs-attr">"src"</span>: <span class="hljs-string">"https://abs.twimg.com/responsive-web/client-web/twitter-lite-timeline-marketing.befcdb47.png"</span>,
      <span class="hljs-attr">"sizes"</span>: <span class="hljs-string">"586x1041"</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"image/png"</span>
    }
  ],
</code></pre>
<p>Replace the src and sizes according to your image location and size. The Image can be either a CDN link or can be in your public folder.</p>
<h2 id="heading-final-result">Final Result</h2>
<p>Yay, Even my <a target="_blank" href="https://app.tapthe.link">PWA</a> has the same UI now.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653757831834/SB4gRDr6k.png" alt="tapthelink(7).png" /></p>
<p>That's it folks, I hope you update your PWA with this new UI and share this with your friends.</p>
<p>Also if you know any creators who make YouTube videos, tell them to checkout tapthe.link</p>
]]></content:encoded></item><item><title><![CDATA[Use Cloudflare Workers as a Reverse Proxy]]></title><description><![CDATA[Reverse Proxy / Rewrites allow us to serve content from different hosts/websites to our domain.
For example, this article you are reading, is on blog.hrithwik.me which is essentially a Reverse proxy / Rewrite of hrithwik.hashnode.dev.
So you get the ...]]></description><link>https://blog.hrithwik.dev/use-cloudflare-workers-as-a-reverse-proxy</link><guid isPermaLink="true">https://blog.hrithwik.dev/use-cloudflare-workers-as-a-reverse-proxy</guid><category><![CDATA[serverless]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[proxy]]></category><category><![CDATA[Cloud]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Tue, 15 Mar 2022 10:47:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1647273192443/eXmmDsOts.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Reverse Proxy / Rewrites allow us to serve content from different hosts/websites to our domain.</p>
<p>For example, this article you are reading, is on blog.hrithwik.me which is essentially a Reverse proxy / Rewrite of <a target="_blank" href="https://hrithwik.hashnode.dev">hrithwik.hashnode.dev</a>.</p>
<p>So you get the idea, this can be super useful for building SAAS with custom domains, Serving your blog from <a target="_blank" href="https://www.semrush.com/blog/subdomain-vs-subdirectory/">subdomain to subdirectory</a>, or even serving content from a no-code website builder to your own domain for *FREE.</p>
<p>Well, there are a plethora of other things you can do with Cloudflare workers as a Reverse Proxy, but here are a few things this article covers.</p>
<p>(if you have worked with next.js, this is similar to <a target="_blank" href="https://nextjs.org/docs/api-reference/next.config.js/rewrites">next.js rewrites</a>)</p>
<h2 id="heading-things-covered-in-this-article">Things covered in this article</h2>
<ul>
<li><strong>Getting Started</strong> with Cloudflare Workers</li>
<li><strong>Simple Reverse Proxy/ Rewrites Example</strong> with Cloudflare workers</li>
<li><strong>How to Block Few words from your Articles in a few regions</strong> with Cloudflare Workers</li>
</ul>
<h2 id="heading-what-is-cloudflare-workershttpsworkerscloudflarecom-and-why-use-it">What is <a target="_blank" href="https://workers.cloudflare.com/">Cloudflare Workers</a> and Why use it?</h2>
<p>For starters, Cloudflare Workers is a serverless architecture that can run JavaScript code on the edge.</p>
<p>That means you don't need to manage the infrastructure and scale it based on the traffic, also means your code is distributed at over 117+ countries and runs in the nearest location of the request with almost zero delay/cold start and is super quick (max 100ms).</p>
<p>It uses V8 Engine under the hood to run JavaScript but not a complete node.js environment so not all npm packages might work. But for most of our use case, this is more than enough.</p>
<p>Also, Cloudflare is super generous with its FREE Plan, which gives us 100K requests/day 😯</p>
<p>So in short, It's lightweight, fast and free to get started with.</p>
<h2 id="heading-things-you-will-need">Things you will need</h2>
<ul>
<li><p>Basic knowledge of JavaScript and NPM modules.</p>
</li>
<li><p>A Cloudflare <a target="_blank" href="https://www.cloudflare.com/?ref=blog.hrithwik.me">Account</a> , </p>
</li>
<li><p>Wrangler CLI, which makes our life easy while working with Cloudflare workers. Here is how you can install it globally.</p>
</li>
</ul>
<pre><code>npm i @cloudflare/wrangler -g
</code></pre><h2 id="heading-getting-started-with-cloudflare-workers">Getting Started with Cloudflare Workers</h2>
<p>Ensure you have installed the Wrangler CLI</p>
<ol>
<li><ul>
<li>Run  <code>wrangler generate &lt;project-name&gt;</code> in your command prompt.</li>
</ul>
</li>
</ol>
<p>(This will create a bunch of files in the directory  and the most important ones are <strong>wrangler.toml</strong>, <strong>index.js</strong> and <strong>package.json</strong> to be honest.)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1646751990120/5YUgKCeH4.JPG" alt="bunch.JPG" /></p>
<ol>
<li>Run <code>wrangler login</code>
(Accept the consent after logging in and you are done.)</li>
<li>Run <code>wrangler dev</code>  , which will start the local server and when you visit it you must get "Hello worker!" Response</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647180126295/WuIRlyqVH.png" alt="screely-1647180093389.png" /></p>
<p>Now Let's get to the meat of the topic</p>
<h2 id="heading-cloudflare-workers-as-a-reverse-proxy-doing-rewrites-using-cloudflare-workers">Cloudflare Workers as a Reverse Proxy / Doing Rewrites using Cloudflare Workers</h2>
<p>Rewrites as the name suggests, allow us to proxy a website to our domain, for example, </p>
<p>Let's say I want content from this website <code>something.site</code> on my personal domain <code>something.com</code>, </p>
<p>I can write some small piece of code, which will fetch content from <code>something.site</code>and then show that on <code>something.com</code> whenever someone visits <code>something.com</code></p>
<p>here is how you can make this work.</p>
<p>paste the below code in your index.js and replace example.com with the domain you want to proxy / fetch content from.</p>
<pre><code class="lang-js">addEventListener(<span class="hljs-string">'fetch'</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
  event.respondWith(handleRequest(event.request))
})

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleRequest</span>(<span class="hljs-params">request</span>) </span>{
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(request.url);
  url.hostname = <span class="hljs-string">'example.com'</span>;
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(url.toString(),request);
  <span class="hljs-keyword">return</span> data;
}
</code></pre>
<p><strong>addEventListener </strong> listens to every request and passes it to our handleRequest Function. Here we are creating a new URL object and replacing its host with example.com. Now we fetch the data from the site(This is very similar to the fetch browser API ) with the original request headers etc and return the data.</p>
<p>I will be using my domain <a target="_blank" href="https://richurl.tech/">richurl.tech</a> instead of example.com</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647183045915/6TOhneU1E.png" alt="image.png" /></p>
<p>and yay, it's working 🎉</p>
<p><strong>Note</strong>: If you observe the network tab,  on every reload you are making 35-50 requests, which means that you will exhaust your Free plan if you get 3000 -2000 requests per day. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647407452882/gSryGZU85.gif" alt="image.gif" /></p>
<p>I still feel the FREE plan is more than enough for most of your needs but if you want more you can look at the <a target="_blank" href="https://developers.cloudflare.com/workers/platform/pricing/">pricing here</a></p>
<h2 id="heading-how-to-block-few-words-from-your-articles-in-a-few-regions-with-cloudflare-workers">How to Block Few words from your Articles in a few regions with Cloudflare Workers</h2>
<p>If you want to create a cuss free mirror of a website, here is how you do it.</p>
<p>I will be using this website as an example https://whatthefuck.is/memoization . (Great Post by the way)</p>
<pre><code class="lang-js">addEventListener(<span class="hljs-string">'fetch'</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
  event.respondWith(handleRequest(event.request))
})

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleRequest</span>(<span class="hljs-params">request</span>) </span>{
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(request.url);
  url.hostname = <span class="hljs-string">'whatthefuck.is'</span>;
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(url.toString(),request);
  <span class="hljs-comment">// Read response body.</span>
  <span class="hljs-keyword">let</span> text = <span class="hljs-keyword">await</span> data.text();
  <span class="hljs-comment">// Modify it.</span>
  <span class="hljs-keyword">const</span> cussWordRegex = <span class="hljs-regexp">/fuck/g</span>;
  <span class="hljs-keyword">let</span> modified = text.replace(cussWordRegex , <span class="hljs-string">"fork"</span>);
  <span class="hljs-comment">// create a new response and return it</span>
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(modified, {
    <span class="hljs-attr">status</span>: data.status,
    <span class="hljs-attr">statusText</span>: data.statusText,
    <span class="hljs-attr">headers</span>: data.headers
  })
}
</code></pre>
<p>the first three lines of code inside the handleRequest function remain the same, that is we are fetching content from another host website, but instead of straight out returning the response, we modify a few things and create a new response and send it.</p>
<p>(We get the HTML text data and replace cuss words with something else and send the response.)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647271847926/-rCU-Pk3Y.png" alt="image.png" /></p>
<p>Works like a charm. Here is a <a target="_blank" href="https://cloudflareworkers.com/#fb560a49fc95598aae877bef38a4cdf7:https://whatthefuck.is/memoization">playground</a> if you want to play around with this</p>
<p>for some reason if you decide not to to show cuss words only for certain regions like India or Korea (just example lmao) , here is how you do it</p>
<pre><code class="lang-js">addEventListener(<span class="hljs-string">'fetch'</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
  event.respondWith(handleRequest(event.request))
})

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleRequest</span>(<span class="hljs-params">request</span>) </span>{
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(request.url);
  url.hostname = <span class="hljs-string">'whatthefuck.is'</span>;
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(url.toString(),request);

  <span class="hljs-keyword">const</span> country = request.cf.country;
  <span class="hljs-keyword">const</span> cussFreeCountries = [<span class="hljs-string">'IN'</span>, <span class="hljs-string">'KP'</span>];

  <span class="hljs-keyword">if</span>(cussFreeCountries.includes(country)){
    <span class="hljs-keyword">let</span> text = <span class="hljs-keyword">await</span> data.text();
    <span class="hljs-keyword">const</span> cussWordRegex = <span class="hljs-regexp">/fuck/g</span>;
    <span class="hljs-keyword">let</span> modified = text.replace(cussWordRegex , <span class="hljs-string">"fork"</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(modified, {
      <span class="hljs-attr">status</span>: data.status,
      <span class="hljs-attr">statusText</span>: data.statusText,
      <span class="hljs-attr">headers</span>: data.headers
    })
  }

  <span class="hljs-keyword">return</span> data;

}
</code></pre>
<p>Cloudflare workers also allow us to identify countries using request.cf.country, so we can probably keep an array of not allowed countries and replace cuss words if the request is coming from those countries otherwise just return the same original data.</p>
<p><strong>So you get it</strong>, we are kind of <strong>intercepting data</strong> by fetching data from the original host and then <strong>modifying a few things</strong> and <strong>sending the response</strong>. You can even add styles and some other js code too if you want some additional functionality in your proxied site.</p>
<h2 id="heading-lets-publish-it">Let's Publish it</h2>
<p>Run this command <code>wrangler publish</code> and this will publish your code to a subdomain of Cloudflare, </p>
<p>Here is how you add Cloudflare workers to your custom domain.</p>
<h3 id="heading-step-1-add-a-route-for-your-workers-after-selecting-the-domain-in-the-dashboard">Step 1 - Add a route for your workers after selecting the domain in the dashboard</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647191064252/xGiMlCQuc.png" alt="image.png" /></p>
<p>Here I am using my service paytm-tap (It's the project name), but you can choose the name of your project</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647191169984/kRijLftq1.png" alt="image.png" /></p>
<h3 id="heading-step-2-point-your-domain-to-a-random-ip-address-in-cloudflare">Step 2 - Point your domain to a random IP address in Cloudflare</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1647191246990/mGV_pY5_i.png" alt="image.png" /></p>
<p>and it's done, your domain now runs Cloudflare workers 🎉</p>
<hr />
<p>That's it folks, a small introduction to Cloudflare worker as a reverse proxy/rewrites.</p>
<p>There are several other use cases like using blog.domain.com as a reverse proxy at domain.com/blog etc which I will cover in the future if time permits.</p>
<p>I think if you play around with workers a little bit, you will figure out this by yourself too.</p>
<p>I do some random shitposting on <a target="_blank" href="https://twitter.com/hrithwik_">Twitter</a>, so let's stay in touch there. </p>
<p>If you have doubts or struck somewhere while using Cloudflare workers there are always people who help you here on the <a target="_blank" href="https://discord.gg/ghdYSPxx">Cloudflare Discord</a></p>
]]></content:encoded></item><item><title><![CDATA[How I used HarperDB Custom Functions to build a web app for my newsletter]]></title><description><![CDATA[I run a Whatsapp newsletter called  Smart-Internet ⚡  where I share useful resources and articles about products, startups and marketing. 
But the problem with Whatsapp Newsletter is, new subscribers can't access the old content.
So, I decided to cre...]]></description><link>https://blog.hrithwik.dev/how-i-used-harperdb-custom-functions-to-build-a-web-app-for-my-newsletter</link><guid isPermaLink="true">https://blog.hrithwik.dev/how-i-used-harperdb-custom-functions-to-build-a-web-app-for-my-newsletter</guid><category><![CDATA[database]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[serverless]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Wed, 29 Sep 2021 12:06:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632917417372/Pa3oS2V6A.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I run a Whatsapp newsletter called <strong> <a target="_blank" href="https://richurl.tech/join-Smart-Internet">Smart-Internet ⚡</a> </strong> where I share useful resources and articles about products, startups and marketing. </p>
<p>But the problem with Whatsapp Newsletter is, new subscribers can't access the old content.</p>
<p>So, I decided to <strong>create a simple project </strong>where you can <strong>access all the articles/resources</strong> which I have shared with the group, segregated into different sections.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632401261806/CO1aG1tNL.png" alt="image.png" /></p>
<p>Building a curation website like this is super easy. </p>
<p>By following this tutorial you will <strong>create your own curation website</strong> and <strong>will learn about creating different endpoints in the backend to access data on HarperDB</strong>.</p>
<p>For the backend I was planning on using an Express server and deploying it to a Digital Ocean instance.</p>
<p>Luckily, we don't need to spend extra cash on running another instance somewhere else.</p>
<p>Because HarperDB recently announced Custom Functions which lets you write endpoints to access and process data. It runs a Fastify server behind the scenes and can be deployed in the same instance as your DB. So I will be using this as the backend for our website.</p>
<h2 id="things-to-do">Things to Do 📚</h2>
<p>Here are few things we need to setup to create our own curation web app</p>
<ul>
<li>Create a HarperDB Cloud instance</li>
<li>Create a schema and table for our data</li>
<li>Create a custom function project </li>
<li>Create different endpoints </li>
</ul>
<h3 id="creating-a-harperdb-cloud-instance">Creating a HarperDB Cloud Instance ⚙️</h3>
<p>First Sign up here  <a target="_blank" href="https://studio.harperdb.io/sign-up/?ref=blog.hrithwik.me">studio.harperdb.io</a> </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632329114953/xDd2gfPHo.jpeg" alt="signup.JPG" /></p>
<p>then click on create new HarperDB Cloud Instance </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632329158436/-ExZETPV3.jpeg" alt="instanec.JPG" />
Here we will be choosing cloud instance </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632329239682/txYk3zqlM.jpeg" alt="create HarperDB Cloud Instance.JPG" /></p>
<p>There are different Instance plans here, I will choose the free option for now</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632329274427/yzpi_WSgb.jpeg" alt="choose the free tier.JPG" /></p>
<p><strong>Congratulations 🎉</strong>
You have successfully completed the first step of creating a cloud instance.<strong>
You are now the owner of your very own HarperDB Cloud Instance!</strong></p>
<h3 id="creating-a-schema-and-table">Creating a Schema and Table 📋</h3>
<p>Let's now create a table -&gt; create a schema and -&gt; add data.</p>
<p>Open your cloud Instance and create a schema for your table. I will name it "example".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632330451395/mEXSpMWqr.jpeg" alt="create schema.JPG" /></p>
<p>Now create a table, I will name it "resources" and for the hash attribute, I will be using "id"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632330535538/O14R4Xj8A.jpeg" alt="create resources.JPG" />
Time to add data... </p>
<p>Click on the plus symbol 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632330373976/xm82bLmOu.jpeg" alt="add button.JPG" />
and here you can either send in one json object or multiple ones in an array. I will be pasting the below json:</p>
<pre><code class="lang-json">[
  {
    <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://matthewmcateer.me/"</span>,
    <span class="hljs-attr">"title"</span>: <span class="hljs-string">"A Blog on AI and Blockchain"</span>,
    <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Biologist-turned-ML-Engineer in San Francisco. I blog about machine learning, biotech, blockchain, dogs, and more."</span>,
    <span class="hljs-attr">"cover"</span>: <span class="hljs-string">"https://matthewmcateer.me/photo-large.png"</span>,
    <span class="hljs-attr">"category"</span>: <span class="hljs-string">"AI"</span>
  },
  {
    <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://future.a16z.com/a-taxonomy-of-tokens-distinctions-with-a-difference/"</span>,
    <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Designing Internet-Native Economies: A Guide to Crypto Tokens - Future"</span>,
    <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Crypto protocols, social apps, online communities, and marketplaces will need to deeply understand the interplay between fungible and non-fungible tokens to create their own internet economies."</span>,
    <span class="hljs-attr">"cover"</span>: <span class="hljs-string">"https://future.a16z.com/wp-content/uploads/2021/06/V7_GenericTopic_Crypto.jpg"</span>,
    <span class="hljs-attr">"category"</span>: <span class="hljs-string">"Crypto"</span>
  },
  {
    <span class="hljs-attr">"url"</span>: <span class="hljs-string">"https://www.youtube.com/watch?v=R9ch1Jvaj7A"</span>,
    <span class="hljs-attr">"title"</span>: <span class="hljs-string">"How to Create a Killer Marketing Message"</span>,
    <span class="hljs-attr">"description"</span>: <span class="hljs-string">"how to go to any event n leave with potential clients"</span>,
    <span class="hljs-attr">"cover"</span>: <span class="hljs-string">"https://img.youtube.com/vi/R9ch1Jvaj7A/maxresdefault.jpg"</span>,
    <span class="hljs-attr">"category"</span>: <span class="hljs-string">"Marketing"</span>
  }
]
</code></pre>
<p>Now we have successfully added data to our table. Time to create some API endpoints which we can use in the frontend.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632330665066/2vAAPzR81.jpeg" alt="tableLooksNice.JPG" /></p>
<h3 id="creating-your-first-custom-function">Creating your first Custom Function 💾</h3>
<p>Head over to the Functions Section and create a Project. I will name my project as api.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632330871633/AqwH38DKc.jpeg" alt="createCustomFunctionHarperDB.JPG" /></p>
<p>This gives you a file for adding routes, a file for adding helper functions and a static folder. I will discuss about helper functions later in the tutorial, Right now head over to the example.js file in the Routes folder and you will see some template code given. Let's remove it for now and just send "Hello world" as a response to check if our endpoint works.</p>
<pre><code><span class="hljs-meta">'use strict'</span>;


<span class="hljs-built_in">module</span>.exports = <span class="hljs-keyword">async</span> (server) =&gt; {

  server.route({
    <span class="hljs-attr">url</span>: <span class="hljs-string">'/'</span>,
    <span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,
    <span class="hljs-attr">handler</span>: <span class="hljs-function">() =&gt;</span> {

      <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello World!"</span>;
    }
  });

}
</code></pre><p>This will send Hello World as the output when we hit our endpoint.</p>
<p>You can access this endpoint at -&gt; <strong>{http://baseURL}/{projectName}</strong></p>
<p>In our case it is https://functions-cloud-hsb.harperdbcloud.com/api</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632394982646/4tvlSqjle.png" alt="image.png" /></p>
<p>Nice, It's working!</p>
<p>Now let's create a route to fetch data by getting category from params.</p>
<p> <strong>{baseurl}/api/resources/:category </strong></p>
<p>Here we are using a SQL query to select all the documents in the table resources which is from schema "example" where "category" comes from our params.</p>
<pre><code class="lang-js">
server.route({
    <span class="hljs-attr">url</span>: <span class="hljs-string">'/resources/:category'</span>,
    <span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,

    <span class="hljs-attr">handler</span>: <span class="hljs-function">(<span class="hljs-params">request</span>) =&gt;</span> {
      request.body= {
        <span class="hljs-attr">operation</span>: <span class="hljs-string">'sql'</span>,
        <span class="hljs-attr">sql</span>: <span class="hljs-string">`select * from example.resources where category="<span class="hljs-subst">${request.params.category}</span>"`</span>
      };
 <span class="hljs-keyword">return</span> hdbCore.requestWithoutAuthentication(request);

    }
  });
</code></pre>
<p>Also, notice that HarperDB allows access to the database with no authentication with their built-in method. If you are doing a POST request, do create some prevalidation which checks auth token etc.</p>
<p>To showcase this, I will create a  a simple prevalidator like throwing an error if a particular category is not available in our list.</p>
<p>For this we can use helper functions. Let's create one called "checkForCategory"
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632332288340/C0GZnlk_lg.png" alt="image.png" /></p>
<p>Now import the function and send the request through the prevalidation</p>
<pre><code><span class="hljs-meta">'use strict'</span>;
<span class="hljs-keyword">const</span> checkForCategory = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../helpers/checkForCategory'</span>);

  server.route({
    <span class="hljs-attr">url</span>: <span class="hljs-string">'/resources/:category'</span>,
    <span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>,
    <span class="hljs-attr">preValidation</span>: <span class="hljs-function">(<span class="hljs-params">request</span>) =&gt;</span> checkForCategory(request, logger),


    <span class="hljs-attr">handler</span>: <span class="hljs-function">(<span class="hljs-params">request</span>) =&gt;</span> {
      request.body= {
        <span class="hljs-attr">operation</span>: <span class="hljs-string">'sql'</span>,
        <span class="hljs-attr">sql</span>: <span class="hljs-string">`select * from example.resources where category="<span class="hljs-subst">${request.params.category}</span>"`</span>
      };



      <span class="hljs-keyword">return</span> hdbCore.requestWithoutAuthentication(request);


    }
  });
</code></pre><p>Congratulations! You have successfully created a few endpoints to get data from your database . While also being hosted in the same instance. So, no need to deploy your backend somewhere else.</p>
<p>You can also do pagination etc here like</p>
<pre><code><span class="hljs-keyword">server</span>.route({
    url: <span class="hljs-string">'/resources'</span>,
    <span class="hljs-keyword">method</span>: <span class="hljs-string">'GET'</span>,
    <span class="hljs-keyword">handler</span>: (request) =&gt; {
      const size = request.query.size|| <span class="hljs-number">10</span>;
      const page = request.query.page || <span class="hljs-number">0</span>;
      const skip = parseInt(page)*parseInt(size);



      request.body= {
        operation: <span class="hljs-string">'sql'</span>,
        <span class="hljs-keyword">sql</span>: `<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> example.resources <span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> category <span class="hljs-keyword">LIMIT</span> ${size} <span class="hljs-keyword">OFFSET</span> ${skip}`
      };
      <span class="hljs-keyword">return</span> hdbCore.requestWithoutAuthentication(request);
    }
  })};
</code></pre><h2 id="frontend">Frontend 📺</h2>
<p>I sketched a simple UI using  <a target="_blank" href="excalidraw.com/">excalidraw</a> 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632332709544/X7_4KIVTo.jpeg" alt="sketch.JPG" />
Once that was done , I set up a React project and changed the app.js to this</p>
<pre><code class="lang-js">

<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;
<span class="hljs-keyword">import</span> { useState,useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [items, setItems] = useState([]);
  <span class="hljs-keyword">const</span> [activeIndex, setActiveIndex] = useState(<span class="hljs-string">"Marketing"</span>);
  <span class="hljs-keyword">const</span> [selectedTag,setSelectedTag] = useState(<span class="hljs-string">"Marketing"</span>)
  useEffect(<span class="hljs-function">()=&gt;</span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchData</span> (<span class="hljs-params"></span>) </span>{

      fetch(<span class="hljs-string">`https://functions-cloud-hsb.harperdbcloud.com/api/resources/<span class="hljs-subst">${selectedTag}</span>`</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">'GET'</span>, <span class="hljs-comment">// or 'PUT'</span>


  })
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
    setItems(data);
  })
    }
    fetchData()


  },[selectedTag]);



  <span class="hljs-keyword">const</span> tags=[<span class="hljs-string">"Marketing"</span>,<span class="hljs-string">"Startups"</span>,<span class="hljs-string">"Podcasts"</span>,<span class="hljs-string">"Product"</span>,<span class="hljs-string">"Crypto"</span>,<span class="hljs-string">"Learn"</span>];



<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ChangeResource</span>(<span class="hljs-params">tag</span>)</span>{

  setSelectedTag(tag);
  setActiveIndex(tag);
}

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"row"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"Boxtitle"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Curated List of Best Articles and Resources 📚<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

     <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"Boxcontent"</span>&gt;</span>

     {tags.map(tag=&gt;(
       <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> ChangeResource(tag)} key={tag} className={activeIndex === tag ? "sectionType active" : "sectionType"}&gt; 
       <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>  &gt;</span> {tag} <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
       <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
     ))}

     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"gridWrap"</span>&gt;</span> 
 {items.map((item,key)=&gt;{


    return(
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{item.title}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"GridView"</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{item.url}</span> &gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">img</span>   <span class="hljs-attr">className</span>=<span class="hljs-string">"ImageStyle"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{item.cover}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span> 
     <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{color:</span>"<span class="hljs-attr">white</span>",<span class="hljs-attr">width:</span>"<span class="hljs-attr">100</span>%",<span class="hljs-attr">maxWidth:</span>"<span class="hljs-attr">400px</span>",<span class="hljs-attr">textAlign:</span>"<span class="hljs-attr">center</span>",<span class="hljs-attr">display:</span>"<span class="hljs-attr">absolute</span>"}}&gt;</span>  {item.title}  <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
     <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> ) }
  )} 

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>





    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Here is the <a target="_blank" href="https://github.com/hrithwikbharadwaj/smart-internet"> repo to the frontend code.</a> </p>
<p>Here it is deployed on vercel-&gt; https://smart-internet.vercel.app/</p>
<p>(Fun Fact : You can deploy your frontend on HarperDB too, if it is static . Read the FAQ section to know more)</p>
<p>You can find the backend code <a target="_blank" href="https://github.com/hrithwikbharadwaj/HarperDB-CustomFunctions-Example-">here</a> </p>
<h3 id="misc">Misc 💭</h3>
<blockquote>
<p>Can we upload our Own Custom Functions?</p>
</blockquote>
<p>Yes, you can. your local code should have routes and a proper project structure. You can start by cloning the official <a target="_blank" href="https://github.com/HarperDB/harperdb-custom-functions-template">repo</a> and change the code along the way.</p>
<blockquote>
<p>How to Upload a Custom Functions to HarperDB?</p>
</blockquote>
<p>At the time of writing this article, the best way to upload your local code to your cloud instance without having a local instance running is by creating a .tar file using 7zip or any tool and then converting it to a base64 string by uploading your tar to this  <a target="_blank" href="https://base64.guru/converter/encode/file">website</a>.</p>
<p>Then you need to make a POST request to your cloud instance. You will find your auth header and instance URL in the “config” section of your HarperDB instance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632383843668/0OIi0z5gy.png" alt="image.png" />
While adding the auth header don't forget to add Basic before your token. (E.g. "Basic dsdfndfkdsad-")</p>
<p>Here is the request body with project property as api (since our project name was api) and the payload will be that long base64 encoded tar text. The file section is dummy but necessary so just copy what I have written.</p>
<pre><code>{
    <span class="hljs-attr">"operation"</span>: <span class="hljs-string">"deploy_custom_function_project"</span>,
    <span class="hljs-attr">"project"</span>: <span class="hljs-string">"api"</span>,
    <span class="hljs-attr">"file"</span>: <span class="hljs-string">"/tmp/144275e9-f428-4765-a905-208ba20702b9.tar"</span>,
    <span class="hljs-attr">"payload"</span>: <span class="hljs-string">"aGVscGVycy8AAAAAAAAAAAAAAAAAAAAAAA........"</span>
}
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632384189060/OIe9rNHwy.png" alt="image.png" /></p>
<p>Congratulations, you just deployed a cloud function from your local project.</p>
<p>I hope you learned something new today. If you did, do give this a Like :)</p>
<p>Let me know how you will use  <a target="_blank" href="https://harperdb.io/?ref=blog.hrithwik.me">HarperDB</a>  to create your next project.</p>
<p>I will go now and resume adding more resources from my  <a target="_blank" href="richurl.tech/Join-Smart-Internet">whatsapp newsletter</a> to this  <a target="_blank" href="https://smart-internet.vercel.app">website </a> </p>
]]></content:encoded></item><item><title><![CDATA[How to grow your Personal blog on Hashnode]]></title><description><![CDATA[Growing your personal blog on your own domain is not that easy. 
It's like a private space in the internet and getting new people to read it is hard. 
Hashnode solves this. You can blog on your own domain and also get a community which reacts to your...]]></description><link>https://blog.hrithwik.dev/how-to-grow-your-personal-blog-on-hashnode</link><guid isPermaLink="true">https://blog.hrithwik.dev/how-to-grow-your-personal-blog-on-hashnode</guid><category><![CDATA[General Advice]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[HashnodeCommunity]]></category><category><![CDATA[#growth]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Tue, 17 Aug 2021 12:14:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629171427928/DwxEoAdOb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Growing your personal blog on your own domain is not that easy. </p>
<p>It's like a private space in the internet and getting new people to read it is hard. </p>
<p><strong>Hashnode</strong> solves this. You can blog on your own domain and also get a community which reacts to your articles.</p>
<p>But when I was just scrolling down Hashnode feed for 20 minutes and I could see that there were many new faces and amazing new articles but had very little engagement . What if I tell you that with a few small tweeks , your blog could actually blow up 🚀.</p>
<p>I am not pro at blogging but as a YouTuber, I have learnt a thing or two about growing your online presence. Currently My  <a target="_blank" href="https://YouTube.com/HSBTechYt">YouTube</a>  Channel has 2M+ views and my <a target="_blank" href="https://blog.hrithwik.me"> blog</a>  has 50,000+ total views here on Hashnode.</p>
<p>Hashnode currently doesn't have a custom recommendation algorithm so chances that you get more exposure is still high , compared to medium or Dev.to  </p>
<h2 id="the-basics">The Basics</h2>
<p>If you recently started your blogging journey and confused what to write , here are some recommendations </p>
<ul>
<li>It's fine to share life experiences </li>
<li>General Things like your tech interview experience </li>
<li>Your first project </li>
<li>Your hackathon experience ,etc . 
(Hashnode and Auth0  currently have a  <a target="_blank" href="https://townhall.hashnode.com/auth0-hackathon">hackathon running where you could win $1000</a>  ) . </li>
</ul>
<p>When I recently called <a class="user-mention" href="https://hashnode.com/@atapas">Tapas Adhikary</a> for some guidance . I asked him how he is consistent and some suggestions for articles , here is what he had to tell</p>
<blockquote>
<p>if you were searching something online and it didn't really match the exact problem you were trying to solve. After you figure out the solution to that problem, Write about it. </p>
</blockquote>
<p>I have also observed one thing which even I was feeling initially, that is not writing about a particular topic because there are already some articles about it but </p>
<blockquote>
<p>If you learnt something recently like react ,Vue or shifted from one framework to the other. Writing just makes your understanding strong, helps beginners and if you forget about something , you can get back to it.</p>
</blockquote>
<h3 id="publishing-checklist">Publishing Checklist</h3>
<p>Here is a checklist after you publish your article.</p>
<ul>
<li>Have a Crisp Title focused on Viewers/ Problem</li>
<li>Have a cover Photo ( checkout  <a target="_blank" href="https://slickr.vercel.app">slickr </a> by <a class="user-mention" href="https://hashnode.com/@saviomartin">Savio Martin</a> or  <a target="_blank" href="https://coverview.now.sh">CoverView</a> by <a class="user-mention" href="https://hashnode.com/@rutikwankhade">Rutik Wankhade</a>)</li>
<li>Make sure you add 5 relevant tags</li>
</ul>
<p>Those were the basics which few still miss out. </p>
<hr />
<p>Now that you have written an article. Getting <strong>initial traction</strong> is very important. Post your Blog on Twitter / Reddit and if you are ready for some hate then Hackernews aswell ( it's a rabbit hole, no one knows how something gets viral there, my last post got like 15K views for being number 4 for 3 hours ) .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629168156271/TBUbYbQJE.png" alt="image.png" /></p>
<p>But Hrithwik , I don't have Twitter or friends on Twitter , what can I do ?? </p>
<p>Let's start with me. Just DM me on  <a target="_blank" href="https://twitter.com/hrithwik_">Twitter</a>  and I will retweet your article if I like it. </p>
<p>Also If you are from college, share your blog in your college dev discord / whatsapp groups. Joining Clubs in college has huge upside to your network (But do you know that Hashnode has it's own discord  <a target="_blank" href="https://discord.com/invite/AfS5j6u">community</a>  ? )</p>
<p>This get's you those initial traction especially if your article is something very unique or your dev friends from college have not herd of. If something is interesting people automatically like and comment. </p>
<p>Now if you are serious about writing or anything in life , you need to have a group of friends in the same field. Support your friends , have small talks , collaborate and the support becomes mutual. Developers are one of the nicest and friendly people in the world (atleast everyone who write on hashnode ) . </p>
<p>So I am sure you would have guessed where I am going. Yes community. </p>
<ul>
<li>It's important to have atleast 20-30 people from the same group who are there for you always and you are too. </li>
<li>Comment on others stories and react to their stories. This let's people know that you exist and supporting others is always good karma . </li>
<li>Linkedin is unnoticed but if you have a bunch of tech connections on LinkedIn you have high chances to get the initial traction from there too . </li>
</ul>
<h2 id="additional-tips">Additional Tips</h2>
<p>In the home page the first two articles are featured posts which stay on top for few hours and if you have more reactions than the third or fourth post you will be the third post and if the article is good enough for a larger audience , your article will be featured on Hashnode. Congratulations 🎉
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629168286041/lBYxT7UbU.png" alt="image.png" /></p>
<h2 id="the-second-boost">The Second Boost</h2>
<p>Hashnode promotes all the good article on their twitter , facebook and linkedin. You get the second boost from their newsletter too. Also some of my viewers also came from   <a target="_blank" href="https://daily.dev/">Daily. dev </a> </p>
<p>That's it everyone. I hope you get more reach and grow your online presence.</p>
<hr />
<h2 id="who-am-i">Who am I ?</h2>
<p>I am Hrithwik from Mysore , India . I am Curious about startups and tech in general. </p>
<p>I belong to different cults xD . I am a  <a target="_blank" href="youtube.com/hrithvikbharadwaj">musician</a>  ,  <a target="_blank" href="https://www.youtube.com/HSBTechYt">a tech guy</a> , <strong>cool college senior</strong> and<strong> I can also code</strong>. So I have multiple groups I hangout with. </p>
<p>I also run a  <a target="_blank" href="https://richurl.tech/join-Smart-Internet">whatsapp newsletter </a> which people love , I share interesting things about product, code, startups and podcasts. Highly recommend you to join if you use whatsapp . </p>
<p>Also newsletter helps you convert first time viewers into recurring viewers .  <a target="_blank" href="https://edidiongasikpo.com/how-to-increase-your-blogs-readership-on-hashnode">Hashnode has an inbuilt newsletter</a>  . Soon you will be able to send custom messages in the newsletter too .</p>
<p>I am learning react and next.js and it is very exciting. Will share my journey from vue to react soon. Follow here and stay tuned</p>
<p>Here are all my  <a target="_blank" href="https://bio.link/hrithwik">socials</a>  where we could chit chat .</p>
]]></content:encoded></item><item><title><![CDATA[The Good and the Limitations of Github Copilot]]></title><description><![CDATA[I have been trying to generate code with the help of GPT3 from few months now and recently got access to a better product called Github copilot. 
 Github Copilot  is an VS Code extension which can autocomplete your code and also synthesize code by se...]]></description><link>https://blog.hrithwik.dev/the-good-and-the-limitations-of-github-copilot</link><guid isPermaLink="true">https://blog.hrithwik.dev/the-good-and-the-limitations-of-github-copilot</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[AI]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Mon, 05 Jul 2021 03:23:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1625419325999/HGPBZ26lZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have been trying to generate code with the help of GPT3 from few months now and recently got access to a better product called <strong>Github copilot</strong>. </p>
<p> <a target="_blank" href="https://copilot.github.com/"><strong>Github Copilot</strong></a>  is an VS Code extension which can autocomplete your code and also synthesize code by seeing your comments and function name. This is built using the same model and trained on billions of public code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625455957844/-90gokQHv.jpeg" alt="gpt3copilot.JPG" /></p>
<p>When I told my friends about Github Copilot  the first question I got is</p>
<blockquote>
<p>Can it do DSA Problems and help me crack into FAANG xD?</p>
</blockquote>
<p>This was funny but I wanted to try it out and the results were mind blowing. AI could solve most of the DSA problems and I have shared some results  <a target="_blank" href="https://richurl.tech/dsacopilot">here </a> .</p>
<p>Later I tried using github copilot in some real development work like writing email validation , making api calls to github and even building a simple email sending client.</p>
<p>Now I have some clear idea on the limitations and things that Copilot is good at this movement .</p>
<p>Before moving on to the article if you prefer videos over an article, Here is my video on  <a target="_blank" href="https://www.youtube.com/watch?v=9Pw-Roo_duE">Solving DSA Problems using Github Copilot</a> </p>
<p> <a target="_blank" href="https://www.youtube.com/watch?v=9Pw-Roo_duE"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625455007755/XNtYm-8jT.jpeg" alt="copilot.jpg" /></a> </p>
<h2 id="the-good">The Good✨</h2>
<h3 id="forgot-the-syntax-no-worries-ai-got-your-back">Forgot the Syntax ? No worries. AI got your back</h3>
<p>When building a project I had forgot status code for what response to send and writing a comment about it gave me a result. Also I had written python after long time and at one point I had forgot the syntax for slicing and this helped me there aswell.</p>
<h3 id="can-help-you-with-email-validation-and-api-calls">Can help you with Email Validation and API Calls</h3>
<p>As I shared before it was really easy to <strong>generate simple functions</strong>  for calling some  <a target="_blank" href="https://richurl.tech/8bRT4sxX6">API's and write some regex code</a>  without learning it or depending on <strong>documentation</strong>. ( Not recommended if you are a beginner) . </p>
<h3 id="bioler-plate-code">Bioler Plate code</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625456225356/0uYrXfTAj.png" alt="vlcsnap-2021-07-05-09h06m42s448.png" />
It can also help you get like a boiler plate code for express and helped me write some mongo schemes aswell .</p>
<blockquote>
<p>Overall I just love how seamlessly  Github Copilot can show you suggestions on vs code. Beautifully done</p>
</blockquote>
<hr />
<h2 id="limitations">Limitations 🙃</h2>
<p>Github Copilot for an first generation/ Beta product is way too good. But there are a lot of biased articles online so I just wanted to show the other side aswell.</p>
<h3 id="doesnt-follow-the-best-practices">Doesn't Follow the Best Practices</h3>
<p>The code synthesized doesn't always follow the best practices or is not optimized to use it for backend development. Like in Javascript, it generates <strong>var</strong> and <strong>==</strong> than <strong>const </strong>and <strong>===</strong> which can lead to different bugs and shadowing.</p>
<p>Checkout my article on  <a target="_blank" href="https://blog.hrithwik.me/10-best-javascript-practices-recommended-by-top-developers">best practices for JS developers</a> </p>
<h3 id="version-conflicts">Version Conflicts</h3>
<p>Some Code Generated might not work for the version your codebase is on and can lead to conflicts. Also sometimes AI can give out a lot of unnecessary code. Developers with experience can definitely handle this out but what if a newbie directly starts with the help of AI, he will spend more time on stack overflow than writing actual code. ( oh wait that's how most of the developers are lmao)</p>
<h3 id="weird-copyright-messages">Weird Copyright messages</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1625456179507/n5Oyz_WBL.png" alt="Creating an actual project using Github Copilot.png" />
When I tried to generate code for converting linkedlist into a tree which is like a famous DS problem, The AI started showing copyright messages in the comments and it was from a person called Stephen. </p>
<blockquote>
<p>Hey Stephen, If you are reading this, please follow me on hashnode .</p>
</blockquote>
<hr />
<h2 id="frequently-asked-questions">Frequently asked Questions</h2>
<ul>
<li>What's Good ? <blockquote>
<p>It's great if you want to create functions like email validation or user schema or API request since it has enough data but again some code might not really be efficient.</p>
</blockquote>
</li>
<li><p>Can it help you crack DSA Problems <strong>(if it is legal)</strong> ? </p>
<blockquote>
<p>The Answer is not  binary. it can help you give building blocks according to your needs and you are the one who should build the building.</p>
</blockquote>
</li>
<li><p>Will it Replace Humans ?</p>
</li>
</ul>
<blockquote>
<p>Absolutely NOT. As the name suggests ,  it's  a copilot making your life easier. You are the pilot who can understand human narratives and stories to build product from code.</p>
</blockquote>
<h3 id="lets-connect">Let's Connect</h3>
<p>Thanks for reading my article. I want to make new friends in the dev world. Let's connect on  <a target="_blank" href="twitter.com/hrithwik_">Twitter</a> and <a target="_blank" href="https://www.linkedin.com/in/hrithwik-bharadwaj">LinkedIn </a> .</p>
<p>Also a tiny Observation</p>
<blockquote>
<p>After using this to write my project code for more than 2 hours I got so used to copilot that without using github copilot suggestion I literally didn't know what to write next in my code . I am a little scared. IT's a TRAP to make developers even lazy xD . Can't wait to see the pricing.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How to stop Your Heroku app from sleeping😴 (FREE)]]></title><description><![CDATA[The Story Behind 📚
Few months back I built a tool called  richurl.tech which is like a url shortner 🔗 but with super power ⚡ . When someone clicks on the richurl, it sends them directly to the YouTube app instead of opening videos on FB/Instagram/L...]]></description><link>https://blog.hrithwik.dev/how-to-stop-your-heroku-app-from-sleeping-free</link><guid isPermaLink="true">https://blog.hrithwik.dev/how-to-stop-your-heroku-app-from-sleeping-free</guid><category><![CDATA[Heroku]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Sat, 24 Apr 2021 07:21:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619249015697/eKQr84kMD.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="the-story-behind">The Story Behind 📚</h2>
<p>Few months back I built a tool called  <a target="_blank" href="https://richurl.tech">richurl.tech</a> which is like a url shortner 🔗 but with super power ⚡ . When someone clicks on the richurl, it sends them directly to the YouTube app instead of opening videos on FB/Instagram/Linkedin Broswer.</p>
<p>The backend API was deployed on heroku. It's a cloud platform as a service where you can deploy apps built using python, node, Go, and many more. </p>
<p>If you are on a free tier on Heroku your app sleeps if it is not active for more than 30 minutes. But My back-end should never sleep since it causes delay to wake up the server and defeats the whole purpose of simplifying the user flow through the service. </p>
<p>Here is how I fixed it </p>
<h2 id="solution">Solution ✨</h2>
<p>Adding a  credit card on heroku gives you total 1000 hours/month , allows you to deploy more than 5 apps and allows custom domain mapping all for FREE.</p>
<h3 id="first-method">First method</h3>
<p>There are many ways on the internet by which you can stop your heroku from sleeping but by far this is the simplest way on the internet.</p>
<blockquote>
<p>Follow this only if you have more than 750hours of dyno time since you won't run out of monthly quota. </p>
</blockquote>
<p>Visit  <a target="_blank" href="https://kaffeine.herokuapp.com/">Kaffeine Shots</a> and enter your heroku app.
It basically pings your app every 30 minutes once and doesn't make it sleep except for the minimum 6 hours which is mandatory.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619243262087/mb9GleOTX.jpeg" alt="kafeeine shot.JPG" /></p>
<p>If you don't want this to continue or running out of quota then you can even stop this.</p>
<h3 id="second-method">Second method</h3>
<p><strong>Hobby Dynos </strong></p>
<p>Hobby Dynos are same as free dynos but they never sleep by default. </p>
<p>They cost $7/month but if you are a student like me you can sign up for  <a target="_blank" href="https://education.github.com/pack">GitHub Students beneifts</a>  and can get free hobby dynos for 2 years . </p>
<p>Currently I am using Hobby Dynos since I am a student.</p>
<hr />
<p>That's it folks. If you have a friend who is a youtuber  . Ask him to try out  <a target="_blank" href="https://richurl.tech">Rich URL</a>  while sharing his links on social media platform. I am very close to 100 followers on hashnode. Click on Follow :)</p>
<p>I am also available for free lance gigs or Full time offer. You can contact me on  <a target="_blank" href="https://twitter.com/HSBTechYt">Twitter</a>  or  on <a target="_blank" href="https://www.linkedin.com/in/hrithwik-bharadwaj">Linkedin</a> 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1599034192769/tdRNTK_i9.jpeg" alt="hrithwik.jpg" /></p>
]]></content:encoded></item><item><title><![CDATA[5 Web API's for your Next Project]]></title><description><![CDATA[There are a few amazing web API's supported by modern browsers and these are few you might want to use in your next project.

 Do note that some browsers might not support all these API's

Clipboard API 📋
Implementing clipboard functionality is even...]]></description><link>https://blog.hrithwik.dev/5-web-apis-for-your-next-project</link><guid isPermaLink="true">https://blog.hrithwik.dev/5-web-apis-for-your-next-project</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Web API]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[HashnodeCommunity]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Thu, 25 Mar 2021 12:02:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1616673279193/fl0mZ9Dxx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are a few amazing web API's supported by modern browsers and these are few you might want to use in your next project.</p>
<blockquote>
<p> Do note that some browsers might not support all these API's</p>
</blockquote>
<h2 id="clipboard-api">Clipboard API 📋</h2>
<p>Implementing clipboard functionality is even simpler now with the clipboard API.</p>
<p>Using Clipboard API ,You can either Copy or Paste from your Clipboard</p>
<p>Here is how to copy</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> text = <span class="hljs-string">"Some Information"</span>
<span class="hljs-keyword">if</span> (!navigator.clipboard) {
    <span class="hljs-comment">// Clipboard API not available</span>
    <span class="hljs-keyword">return</span>
  }

 <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">await</span> navigator.clipboard.writeText(text)
    <span class="hljs-comment">// copies to clipboard</span>
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to copy!'</span>, err)
  }
</code></pre>
<p>Here is how to Paste from the user's clipboard</p>
<pre><code class="lang-js">
<span class="hljs-keyword">if</span> (!navigator.clipboard) {
    <span class="hljs-comment">// Clipboard API not available</span>
    <span class="hljs-keyword">return</span>
  }

 <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> text = <span class="hljs-keyword">await</span> navigator.clipboard.readText()
    <span class="hljs-comment">// copies info from clipboard to text variable</span>
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Failed to copy!'</span>, err)
  }
</code></pre>
<h2 id="share-target-api">Share Target API 🔗</h2>
<p>Let's say you have built a PWA where people upload photos or share links and allowing users to see your app while clicking on the share button makes your PWA look dope.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614230907803/qyVg9Kczq.gif" alt="ezgif.com-video-to-gif.gif" /></p>
<p>Add this in your <strong>mainfest.json</strong> file. If you don't know about manifest json file or PWA's in general .Check out my article on  <a target="_blank" href="https://blog.hrithwik.me/convert-your-website-into-an-app-easily">Converting your website into PWA</a> </p>
<p>Manifest.json</p>
<pre><code class="lang-js"><span class="hljs-string">"share_target"</span>: {
  <span class="hljs-string">"action"</span>: <span class="hljs-string">"/share-target/"</span>,
  <span class="hljs-string">"method"</span>: <span class="hljs-string">"GET"</span>,
  <span class="hljs-string">"params"</span>: {
      <span class="hljs-string">"text"</span>: <span class="hljs-string">"link"</span>,
 }
}
</code></pre>
<p>Now on the app side, you can get the data that the user has shared through a query parameter called link</p>
<p>The above code works only for links or text but what if you have to share images or files?   </p>
<p>To implement for images/files checkout an article at web.dev  <a target="_blank" href="https://web.dev/web-share-target/">here</a> </p>
<h2 id="file-system-api">File System API</h2>
<p>Let's say you want a user to upload a file and the below code works for reading the file</p>
<pre><code class="lang-js">&lt;input type=<span class="hljs-string">"file"</span>&gt;
</code></pre>
<p>and you can save the file using download inside an anchor tag</p>
<pre><code class="lang-js">&lt;a href=<span class="hljs-string">""</span> download=<span class="hljs-string">"file.txt &gt; Save File &lt;/a&gt;</span>
</code></pre>
<p>But you can't just edit the file which you have accessed from the above method. With File Share API you can edit the files you have read and save them which sends a new prompt to the user. </p>
<blockquote>
<p>Do note that this is a new feature and only chrome 86 or greater supports this.</p>
</blockquote>
<p>index.html</p>
<pre><code class="lang-js">&lt;button id=<span class="hljs-string">"fs-open"</span>&gt; Upload File &lt;/button&gt;
</code></pre>
<p>index.js</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getFile = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'fs-open'</span>)

getFile.onClick = <span class="hljs-keyword">async</span>() =&gt;{
[fileHandle] = <span class="hljs-keyword">await</span> <span class="hljs-built_in">window</span>.showOpenFilePicker();
<span class="hljs-keyword">if</span> (fileHandle.type === <span class="hljs-string">'file'</span>) {
          <span class="hljs-keyword">const</span> fileData = <span class="hljs-keyword">await</span> fileHandle.getFile();
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(fileHandle.type===<span class="hljs-string">'directory'</span>){
          <span class="hljs-keyword">const</span> dirName = <span class="hljs-string">'directoryToGetName'</span>;

           <span class="hljs-comment">// assuming we have a directory handle: 'currentDirHandle'</span>
          <span class="hljs-keyword">const</span> subDir = currentDirHandle.getDirectoryHandle(dirName, {<span class="hljs-attr">create</span>: <span class="hljs-literal">true</span>});
}

};
</code></pre>
<p>To save a file to disk, you can either use that filehandle that you got earlier or call showSaveFilePicker() to get a new filehandle.</p>
<pre><code class="lang-js">
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveFile</span>(<span class="hljs-params">fileHandle</span>) </span>{
  <span class="hljs-keyword">if</span> (!fileHandle) {
    fileHandle = <span class="hljs-keyword">await</span> <span class="hljs-built_in">window</span>.showSaveFilePicker();
  }
  <span class="hljs-keyword">const</span> writable = <span class="hljs-keyword">await</span> fileHandle.createWritable();
  <span class="hljs-keyword">await</span> writable.write(contents);
  <span class="hljs-keyword">await</span> writable.close();
}
</code></pre>
<p>You can even get directories and create files in the directories.</p>
<p>This is especially useful if you want to create Notepad Applications on the web.
 Read more about it  <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API">here </a> .</p>
<h2 id="web-storage-api">Web Storage API</h2>
<p>Local Storage is great for storing information that shouldn't be sent to the server, it also doesn't have any expiration, and also it has more storage capacity on the other hand session storage can be used for a session and for a fixed amount of time.</p>
<p>Here is how to store let's say a username</p>
<pre><code class="lang-js"><span class="hljs-built_in">localStorage</span>.username= <span class="hljs-string">'hrithwik'</span>
</code></pre>
<p>now let's say you have to retrieve the username of the username without a further API call</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> username = <span class="hljs-built_in">localStorage</span>.username
</code></pre>
<p>Remember I told you that there is no expiration for this? </p>
<pre><code class="lang-js"><span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">'username'</span>)
</code></pre>
<h2 id="user-media-api">User Media API</h2>
<p>Let's say you are building the next zoom or an AR app. How do you access the camera ?</p>
<p>That can be done using navigator api</p>
<pre><code>
<span class="hljs-string">navigator.mediaDevices.getUserMedia({</span>
  <span class="hljs-attr">video:</span> <span class="hljs-literal">true</span><span class="hljs-string">,</span>
  <span class="hljs-attr">audio:</span> <span class="hljs-literal">true</span>
<span class="hljs-string">})</span>
<span class="hljs-string">//</span> <span class="hljs-string">get's</span> <span class="hljs-string">both</span> <span class="hljs-string">audio</span> <span class="hljs-string">and</span> <span class="hljs-string">video</span> <span class="hljs-string">from</span> <span class="hljs-string">the</span> <span class="hljs-string">user</span>
</code></pre><p>This returns a promise and can be stored in a variable. Let's Display the stream on the browser now</p>
<pre><code class="lang-js">&lt;button id=<span class="hljs-string">"video-on"</span>&gt;Get access to camera&lt;<span class="hljs-regexp">/button&gt; &lt;video autoplay&gt;&lt;/</span>video&gt;
</code></pre>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>
  .querySelector(<span class="hljs-string">'#video-on'</span>)
  .addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span>(<span class="hljs-params">e</span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> stream = <span class="hljs-keyword">await</span> navigator.mediaDevices.getUserMedia({
        <span class="hljs-attr">video</span>: <span class="hljs-literal">true</span>
        <span class="hljs-attr">audio</span>:<span class="hljs-literal">true</span>
      })
      <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'video'</span>).srcObject = stream
      <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#video-on'</span>).setAttribute(<span class="hljs-string">'hidden'</span>, <span class="hljs-literal">true</span>)
      <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        track.stop()
      }, <span class="hljs-number">3</span> * <span class="hljs-number">1000</span>)
    } <span class="hljs-keyword">catch</span> (error) {
      alert(<span class="hljs-string">`<span class="hljs-subst">${error.name}</span>`</span>)
      <span class="hljs-built_in">console</span>.error(error)
    }
  })
</code></pre>
<p>This hides the button after clicked and shows the video on the browser.</p>
<h2 id="bonus-geo-location-api">Bonus - Geo Location API</h2>
<p>What if you are building an app that requires constant GPS Information from the users' device.</p>
<p>That's where GeoLocation API comes in. It gives you not only information regarding the longitude and latitude of users but also access to other various sensors which can be workaround with more use cases.</p>
<pre><code class="lang-js"> <span class="hljs-keyword">if</span>(!navigator.geolocation) {
    status.textContent = <span class="hljs-string">'Geolocation is not supported by your browser'</span>;
  } <span class="hljs-keyword">else</span> {
    status.textContent = <span class="hljs-string">'Locating…'</span>;
    navigator.geolocation.getCurrentPosition(success, error);
  }

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sucess</span>(<span class="hljs-params">position</span>)</span>{
<span class="hljs-keyword">const</span> latitude  = position.coords.latitude;
<span class="hljs-keyword">const</span> longitude = position.coords.longitude;
mapLink = <span class="hljs-string">`https://www.openstreetmap.org/#map=18/<span class="hljs-subst">${latitude}</span>/<span class="hljs-subst">${longitude}</span>`</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">error</span>(<span class="hljs-params"></span>)</span>{
 status.textContent = <span class="hljs-string">'Unable to retrieve your location'</span>;
}
</code></pre>
<p>You can even see if the device is in motion by adding a event listner.</p>
<pre><code class="lang-js"><span class="hljs-built_in">window</span>.addEventListner(<span class="hljs-string">'devicemotion'</span>,<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span>{
<span class="hljs-built_in">console</span>.log(event)
}
</code></pre>
<hr />
<p> If you want to discover more Web API's <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API">Here is a list of all Web API's</a> </p>
<p>If you are on Hashnode and seeing this. Consider following my blog :) </p>
<p>Also, I love Filter Coffee</p>
<div class="hn-embed-widget" id="buyme"></div>]]></content:encoded></item><item><title><![CDATA[I Created a Deep Linking Tech for YouTube Influencers and Marketeers (RICH URL)]]></title><description><![CDATA[Story Behind
I use Instagram extensively and while surfing there I see a lot of influencers add their YouTube links in the bio and stories but when I click on their link it opens it on Instagram's white browser which sucks for viewers. 
I have been a...]]></description><link>https://blog.hrithwik.dev/i-created-a-deep-linking-tech-for-youtube-influencers-and-marketeers</link><guid isPermaLink="true">https://blog.hrithwik.dev/i-created-a-deep-linking-tech-for-youtube-influencers-and-marketeers</guid><category><![CDATA[Amplify Hashnode]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[youtube]]></category><category><![CDATA[marketing]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Thu, 25 Feb 2021 13:31:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1614259542521/pGyzaQ5DZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-story-behind">Story Behind</h2>
<p>I use Instagram extensively and while surfing there I see a lot of influencers add their YouTube links in the bio and stories but when I click on their link it opens it on Instagram's white browser which sucks for viewers. </p>
<p>I have been a  <a target="_blank" href="https://richurl.tech/hrithwik">YouTuber</a>  myself and have seen my friends complaining about why they don't click my bio link. To Summarise below is the problem statement. </p>
<p><strong>Update</strong>: this project got me selected as a  <a target="_blank" href="https://townhall.hashnode.com/aws-amplify-hackathon-winners">winner for AWS Amplify Hackathon</a> .</p>
<h2 id="heading-problem">Problem</h2>
<p> Content Creators / Influencers on YouTube and marketers who use Instagram, Facebook, and Linkedin for sharing their video links have observed that all these platforms use their own browsers while opening external links.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614256709491/MYQuvCAiR.gif" alt="ezgif.com-video-to-gif.gif" /></p>
<p>This might be good for Facebook as it makes people stay on their own platform for more time but <strong>not good for creators and end consumers.</strong> </p>
<p>End Consumers can't see videos in high quality and end up having a bad experience while creators can't get better ad revenues or better engagement since not all users would have logged in to YouTube on their browser.</p>
<h2 id="heading-my-solution">My Solution ✨</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614256718716/K5skFFv-Y.gif" alt="ezgif.com-video-to-gif(1).gif" /></p>
<p>I created  <a target="_blank" href="https://main.d378z6kep2qz7.amplifyapp.com/">richurl.tech</a> which takes normal YouTube and Amazon links and converts them to magical rich URLs for <strong>absolutely FREE with unlimited redirects and unlimited links</strong>. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614259012276/NHGsue03s.gif" alt="ezgif.com-video-to-gif(3).gif" />
<strong>Generating Rich URL's for YouTube</strong>  Increases the chances of viewers staying more on your video, better ad revenue, and better chances of commenting.</p>
<p><strong>Generating Rich URL's for Amazon</strong> helps digital marketers increase the chances of users clicking the buy button resulting in better affiliate commission.  </p>
<h3 id="heading-how-does-it-work">How does it work?</h3>
<p>Let me try to put it in the simplest way. When someone generates a rich URL for their YouTube video, I create 3 links. one for the web(https), android(intent), and IOS. Later based on the user agent of the request I do a 301 redirect to the respective link.</p>
<h3 id="heading-features">Features 🔥</h3>
<ul>
<li>Supports YouTube Videos/Channels </li>
<li>Supports Amazon India</li>
<li>Get click counts based on the device.</li>
<li>Directly share the link from YouTube to  <a target="_blank" href="https://main.d378z6kep2qz7.amplifyapp.com/">richurl.tech</a> or paste Links from Clipboard with one click.</li>
<li>Resultant URL gets copied to your clipboard automatically so you can start sharing with ease.</li>
<li>Progressive Web App</li>
</ul>
<blockquote>
<p>If you are a YouTuber this is a must try and let me know if you are liking it.</p>
</blockquote>
<h2 id="heading-developing-experience">Developing Experience 😊</h2>
<p>I had a basic idea of how to implement it but was not sure if it would work. That's when I started breaking the problem into small chunks and assigned myself small tasks every day till the 23rd of February to complete on Notion.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614258194818/UjOvys6nC.gif" alt="ezgif.com-video-to-gif(2).gif" />
Notion is amazing. I created different pages for the Backend and frontend. Created boards and assigned work for every day.</p>
<p>Technology Stack</p>
<ul>
<li>Nuxt</li>
<li>Buefy</li>
<li>Mongo DB</li>
<li>Express JS</li>
<li>Amplify </li>
</ul>
<p>In the first 6-8 days built the rest-api iteratively and added small features here and there when I got new ideas. The learnings from building Rest API were building auth, Relational Data with Moongoose, and the main logic to implement deep linking on the web. Learnings from building the front end side were <a target="_blank" href="https://web.dev/web-share-target/">Share Target API</a> and  <a target="_blank" href="https://buefy.org/">Buefy</a> .</p>
<p>The next 3 days setup the nuxt project handling and functionalities like Auth, Clipboard web API, web share api, and handling dynamic routes in Nuxt. </p>
<p>The final days(3 Days) were for building the UI side of things using Buefy Extention to Nuxt.</p>
<h2 id="heading-challenges-during-the-project">Challenges during the project ⚙️</h2>
<ul>
<li>Deep Linking Functionality (it's different for Yt Video and channel)</li>
<li>Implementing Auth in Nuxt (Once it's figured it's piece of cake but took me an entire day)</li>
<li>BUEFY TABLES (Customization, handling clicks, and other small details are hard to find in the documentation and took me 2 days just to implement basic features in the frontend.)</li>
</ul>
<p>Overall loved building this tool for marketers and influencers as I was new to most of the stack in this project and got to learn a lot by building this and pushed myself to write code every day. Shout out to <a class="user-mention" href="https://hashnode.com/@hashnode">Hashnode</a> and Amplify for finally motivating me to build this.</p>
<h2 id="heading-future-improvements">Future Improvements</h2>
<ul>
<li>Complete Statistics with Geo-Location and From location (on it right now)</li>
<li>Add support for more social platforms</li>
<li>Map to a custom domain for better branding ( not sure how this works. Need to dive deep in)</li>
</ul>
<div class="hn-embed-widget" id="payment"></div><p>Here is the GitHub Repo - <a target="_blank" href="https://github.com/hrithwikbharadwaj/deeply-frontend">Click Here</a>  </p>
<blockquote>
<p>This is a soft launch of RichURL.tech and my submission to Hashnode's Amplify Hackathon. Use it and please give feedback so that I can add more features and improve the existing ones.</p>
</blockquote>
<p>Also, share this on Twitter with your other Youtube Friends so that they can be benefited. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1614258444324/oUuEj1d7u.jpeg" alt="Capture.JPG" /></p>
]]></content:encoded></item><item><title><![CDATA[10 best JavaScript practices recommended by Top Developers]]></title><description><![CDATA[If you have recently started learning JavaScript or a beginner I would highly recommend you to read the complete article so that you follow better practises while coding in JavaScript as it's a little different. 

It's been a few months since I have ...]]></description><link>https://blog.hrithwik.dev/10-best-javascript-practices-recommended-by-top-developers</link><guid isPermaLink="true">https://blog.hrithwik.dev/10-best-javascript-practices-recommended-by-top-developers</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[HashnodeCommunity]]></category><category><![CDATA[best practices]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Tue, 17 Nov 2020 13:11:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1605618615972/PjfcbX6pV.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>If you have recently started learning JavaScript or a beginner I would highly recommend you to read the complete article so that you follow better practises while coding in JavaScript as it's a little different. </p>
</blockquote>
<p>It's been a few months since I have started programming in JavaScript and these are some of the practises I and several other senior developers follow.</p>
<h2 id="dont-use">Don't use ' == '</h2>
<p>In JavaScript there are both '== ' and '===' and you might be used to "==" in other programming languages and might continue using the same, But using it without knowing how it works might bring few bugs which might be difficult to track. Read my  <a target="_blank" href="https://blog.hrithwik.me/lose-equality-and-strict-equality-in-javascript">previous article</a>  to know more.</p>
<h2 id="use-let-over-var">Use "let" over "var"</h2>
<p>When declaring variables you might have come across 'var' and 'let' but "var" is not recommended as it brings some problems along with it. It will be easier to understand with an example.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>;i&lt;<span class="hljs-number">5</span>;i++){
    <span class="hljs-built_in">console</span>.log(i);
}
<span class="hljs-built_in">console</span>.log(i)

<span class="hljs-comment">// Output : 0 1 2 3 4 5</span>
</code></pre>
<p>Notice that variable i is still accessible outside the block/for-loop which is bad. On the other hand let's write the same code using "let"</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i=<span class="hljs-number">0</span>;i&lt;<span class="hljs-number">5</span>;i++){
            <span class="hljs-built_in">console</span>.log(i);
        }
        <span class="hljs-built_in">console</span>.log(i)
<span class="hljs-comment">// Output : i is not defined</span>
</code></pre>
<p>the output throws an error as the variable i is not accessible outside the for loop/block thanks to "let" as its block-scoped. </p>
<p>There is also something called as shadowing. For example </p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> a= <span class="hljs-number">100</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">example</span>(<span class="hljs-params"></span>)</span>{
a=<span class="hljs-number">20</span>;
} 
example();
<span class="hljs-comment">// 20 just shadowed 100 of the global scope </span>
<span class="hljs-built_in">console</span>.log(a);
<span class="hljs-comment">// Output : 20</span>
</code></pre>
<p>Here you can see that both the variables access the same memory space that's why changing the value inside a block changed the value of the variable outside.</p>
<p>'var' also leads to Hoisting which I will discuss <a class="post-section-overview" href="#What-is-hoisting?">later</a> in the same article. Whenever you want to declare variables in the future where data might change use"let".</p>
<p>Go through some of the articles regarding the same from <a class="user-mention" href="https://hashnode.com/@caelinsutch">Caelin Sutch</a> -  <a target="_blank" href="https://cometcode.hashnode.dev/why-you-need-software-requirements-for-your-application-ckdxjte2o046rjas15howgghq">Let vs var</a> and <a class="user-mention" href="https://hashnode.com/@shumia">Faith Gaiciumia</a> -  <a target="_blank" href="https://faithgaiciumia.hashnode.dev/the-difference-between-let-var-and-constjavascript-ckd7gcry1001nyds1cyt27k3j">Difference between var and let</a> .</p>
<h2 id="use-immutable-variables-or-const">Use Immutable variables or "const"</h2>
<p>Use 'const' to declare variables as much as you can Unless the data changes in the variable like the 'i' inside the for-loop.  Here are few examples</p>
<pre><code class="lang-js">
<span class="hljs-keyword">const</span> x = <span class="hljs-string">'SECRET'</span>
<span class="hljs-built_in">console</span>.log(x)
<span class="hljs-comment">//Output: SECRET</span>
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Here are few illegal things </span>
<span class="hljs-comment">// number 1</span>

<span class="hljs-keyword">const</span> x = <span class="hljs-string">'SECRET'</span>
x=<span class="hljs-string">'Hacking'</span>
<span class="hljs-built_in">console</span>.log(x)
<span class="hljs-comment">// Error: Identifier 'x' has already been declared</span>

<span class="hljs-comment">// Number 2 </span>
<span class="hljs-keyword">const</span> x;
x=<span class="hljs-string">"SECRET"</span>;
<span class="hljs-comment">// Error: Missing initializer in const declaration</span>
</code></pre>
<p>Read more about const <a target="_blank" href="https://www.w3schools.com/js/js_const.asp">here</a> .</p>
<h2 id="use-function-expressions">Use Function Expressions</h2>
<p>With the introduction to ES6, there is a new way to write functions. Here are few examples </p>
<pre><code class="lang-js"><span class="hljs-comment">// Method 1  </span>
<span class="hljs-keyword">let</span> sum = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>) </span>{
    <span class="hljs-keyword">return</span> a + b;
  };
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">//Method 2 </span>
<span class="hljs-keyword">let</span> sum = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> { <span class="hljs-comment">// using arrow function</span>
    <span class="hljs-keyword">return</span> a + b;
  };
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Method 3 </span>
<span class="hljs-keyword">let</span> sum= <span class="hljs-function">(<span class="hljs-params">a,b</span>) =&gt;</span> a+ b ;  <span class="hljs-comment">/* if there is only line inside function. 
There is no need for return */</span>
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">//Method 4 (Annonymous Function)</span>
(<span class="hljs-function">() =&gt;</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"annonymous  functions"</span>)
  })();

<span class="hljs-comment">// Notice our function doesn't have anything but still works.</span>
</code></pre>
<p>This is called Function Expression. Having function expression instead of the normal function declaration also avoids Hoisting. </p>
<h3 id="what-is-hoisting">What is hoisting?</h3>
<p>to explain hoisting in functions let me take an example.</p>
<pre><code class="lang-jsx">exampleFunction(); <span class="hljs-comment">// function call </span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">exampleFunction</span>(<span class="hljs-params"></span>)</span>{ <span class="hljs-comment">// function declaration</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hashnode is awesome"</span>)

}
<span class="hljs-comment">// Output: Hashnode is awesome</span>
</code></pre>
<p>Did you observe how calling exampleFunction() even before definition didn't throw any error.</p>
<p>Why did this happen ? In JavaScript unlike other languages an entire copy of function is copied in the execution context even before executing the code. But doing the same using function expressions would throw an error. </p>
<p>To understand that let's see what happens to variables declared using "var" keyword. Here the memory is allocated even before the execution of the program but it will have undefined value until it goes to the line where the variable is assigned with a value.</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Before Assignment: "</span>,a);

<span class="hljs-keyword">var</span> a=<span class="hljs-number">10</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After assignment: "</span>,a)

<span class="hljs-comment">/* Output:

        Before Assignment: undefined

        After assignment: 10</span>
</code></pre>
<p>The above is called variable hoisting. But coming back to function expressions.</p>
<pre><code class="lang-jsx">exampleFunction();

<span class="hljs-keyword">const</span> exampleFunction= <span class="hljs-function">() =&gt;</span>{

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hashnode is awesome"</span>);

}

<span class="hljs-comment">// Output : ReferenceError: exampleFunction is not defined</span>
</code></pre>
<p>In function expressions the values are not copied to memory even before execution which leads to an error. </p>
<p>Some developers leverage hoisting with function definition by declaring all the functions in the bottom and access it on top but it depends on you. I would suggest you use function expressions and call functions after declarations as it might lead to fewer errors and even reading becomes easier.</p>
<h2 id="use-pure-functions">Use Pure Functions</h2>
<p>Pure functions is a function where  everytime you call that function you get the same result and it should not have side effects.</p>
<p>Why should you care ?  </p>
<p>This helps in testing the function and debugging becomes really easy. Understanding this wih an example would be better . Below is an impure function which multiples all values in an array by 2.</p>
<pre><code class="lang-js">array=[<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>];
<span class="hljs-keyword">const</span> doubleArrayValuesImpure= <span class="hljs-function">(<span class="hljs-params">array</span>)=&gt;</span>{

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> number <span class="hljs-keyword">in</span> array) { 

   array[number] = array[number] *<span class="hljs-number">2</span> ; 

    }
    <span class="hljs-keyword">return</span> array; 
    }
<span class="hljs-comment">// changes the values in original array</span>
</code></pre>
<p>Let's call the same function 2-3 times</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(doubleArrayValuesImpure(array)) ;
<span class="hljs-built_in">console</span>.log(doubleArrayValuesImpure(array)) ;
<span class="hljs-built_in">console</span>.log(doubleArrayValuesImpure(array)) ;

<span class="hljs-comment">/*Output:
[ 2, 4, 6, 8, 10 ]
[ 4, 8, 12, 16, 20 ]
[ 8, 16, 24, 32, 40 ]
*/</span>
</code></pre>
<p>Notice how the values are changing on the original array every time we call the function. Let's write a pure function with the same logic.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> doubleArrayValuesPure= <span class="hljs-function">() =&gt;</span> array.map(<span class="hljs-function"><span class="hljs-params">number</span> =&gt;</span> number *<span class="hljs-number">2</span>) ; 
<span class="hljs-comment">// returns a new array with new values</span>
</code></pre>
<p>calling the pure function</p>
<pre><code><span class="hljs-string">console.log("Pure</span> <span class="hljs-string">Function</span> <span class="hljs-string">results")</span>
<span class="hljs-string">console.log(doubleArrayValuesPure(array));</span>
<span class="hljs-string">console.log(doubleArrayValuesPure(array));</span>
<span class="hljs-string">console.log(doubleArrayValuesPure(array));</span>
<span class="hljs-string">/*Output:</span>
[ <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span> ]
[ <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span> ]
[ <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span> ]
<span class="hljs-string">*/</span>
</code></pre><p>Notice how calling the same function 3 times didn't change the original array. 
Whenever we declare functions we should focus on writing pure functions unless we are changing a file or writing into database.</p>
<h2 id="name-things-properly">Name things properly</h2>
<p>We developers are very lazy and usually use random names for variables and cry in a corner when we have to revisit the same code. You don't actually need to document your code if you have named things in the right way. Also use camel casing.</p>
<pre><code class="lang-js"><span class="hljs-comment">// BAD</span>
<span class="hljs-keyword">let</span> ad=<span class="hljs-string">"124 Broadkill Rd #483"</span>;
<span class="hljs-keyword">let</span> c=<span class="hljs-string">"Milton"</span>;

<span class="hljs-comment">// Good</span>
<span class="hljs-keyword">let</span> address=<span class="hljs-string">"124 Broadkill Rd #483"</span>;
<span class="hljs-keyword">let</span> city=<span class="hljs-string">"Milton"</span>;
</code></pre>
<h2 id="use-destructing">Use Destructing</h2>
<p>Let's consider having an object called person.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> person= {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Hrithwik"</span>,
    <span class="hljs-attr">age</span>:<span class="hljs-number">20</span>,
    <span class="hljs-attr">number</span>: <span class="hljs-number">9999999999</span>,
    <span class="hljs-attr">jobStatus</span>:<span class="hljs-string">"Give me a job please"</span>,
}
</code></pre>
<p>Now if you want to access multiple values which are inside an object you use object destruction instead of manually writing extra lines of code.  Check this out. </p>
<pre><code class="lang-js"><span class="hljs-comment">//noob </span>
<span class="hljs-keyword">let</span> name = person.name;
<span class="hljs-keyword">let</span> age= person.age;
<span class="hljs-keyword">let</span> phoneNumber= person.number;
<span class="hljs-keyword">let</span> occupation= person.jobStatus


<span class="hljs-comment">// Pro </span>
<span class="hljs-keyword">let</span> { name,age,number, jobStatus} = person ;
</code></pre>
<p>But do note that the name of the variable outside the object should be the same as the ones inside. You can also destructuring arrays, read this  <a target="_blank" href="https://javascript.info/destructuring-assignment">article</a>  to know more.</p>
<h2 id="use-promises-over-call-backs">Use Promises over Call Backs</h2>
<p>I am not sure if you have discovered about handling asynchronous code. if you haven't skip this and read about it later. </p>
<p>Here is an example of asynchronous code which takes the user object and checks the commit name in the first repository of the GitHub user. </p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"before"</span>);

getUser(<span class="hljs-number">1</span>,<span class="hljs-function">(<span class="hljs-params">user</span>)=&gt;</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"username:"</span>,user.github);
    getRepo(user.github,<span class="hljs-function">(<span class="hljs-params">repo</span>)=&gt;</span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Repositories are "</span> + repo);
        getCommits(repo[<span class="hljs-number">0</span>],<span class="hljs-function">(<span class="hljs-params">commit</span>)=&gt;</span>{
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Commits"</span>)
        })
    })
})


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">id,callback   </span>)</span>{
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">()=&gt;</span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"reading user from database"</span>)
    callback({ <span class="hljs-attr">id</span>:id*<span class="hljs-number">2</span>,<span class="hljs-attr">github</span>:<span class="hljs-string">'hrithwikbharadwaj'</span>});
},<span class="hljs-number">2000</span>)
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRepo</span>(<span class="hljs-params">username,callback</span>)</span>{
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">()=&gt;</span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"reading repo from "</span>+username);
        callback([<span class="hljs-string">'repo1'</span>,<span class="hljs-string">'repo2'</span>,<span class="hljs-string">'repo3'</span>]);
    },<span class="hljs-number">2000</span>)

}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCommits</span>(<span class="hljs-params">repo,callback</span>)</span>{
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">()=&gt;</span>{
        callback(repo);
    },<span class="hljs-number">300</span>);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After"</span>)
</code></pre>
<p>Callbacks are cool unless there are a lot of callbacks inside callbacks.</p>
<p>Isn't it difficult to read? It's also called callback hell/Christmas tree problem. You can fix it by named functions but a better way to do it is by using promises. Here is the same code using promises.</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"before"</span>)

getUser(<span class="hljs-number">1</span>)
.then(<span class="hljs-function"><span class="hljs-params">user</span>=&gt;</span> getRepos(user.github)) <span class="hljs-comment">// is user available ?</span>
.then(<span class="hljs-function"><span class="hljs-params">repos</span>=&gt;</span>getCommits(repos[<span class="hljs-number">0</span>])) <span class="hljs-comment">// oh great now find his first repo</span>
.then(<span class="hljs-function"><span class="hljs-params">commits</span>=&gt;</span><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"commit name: "</span>,commits)); <span class="hljs-comment">// found the repo ? cool now show the commits</span>



<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">id</span>)</span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve,reject</span>)=&gt;</span>{
        <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">()=&gt;</span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"reading user from database"</span>)
    resolve({ <span class="hljs-attr">id</span>:id*<span class="hljs-number">2</span>,<span class="hljs-attr">github</span>:<span class="hljs-string">'hrithwikbharadwaj'</span>});
},<span class="hljs-number">2000</span>);
    })

}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRepos</span>(<span class="hljs-params">username</span>)</span>{
     <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve,reject</span>)=&gt;</span>{
          <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">()=&gt;</span>{
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"reading repo from "</span>+username);
        resolve([<span class="hljs-string">'repo1'</span>,<span class="hljs-string">'repo2'</span>,<span class="hljs-string">'repo3'</span>]);
    },<span class="hljs-number">2000</span>);
     });


}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCommits</span>(<span class="hljs-params">repo</span>)</span>{
   <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve,reject</span>)=&gt;</span>{
        <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">()=&gt;</span>{
        resolve([<span class="hljs-string">'commits'</span>]);
    },<span class="hljs-number">2000</span>);
   });
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"After"</span>)
</code></pre>
<p>Read more about promises by  <a class="user-mention" href="https://hashnode.com/@Favourite">Jome Favourite</a> <a target="_blank" href="https://favouritejome.hashnode.dev/promises-in-javascript-part-2">here</a> on <a class="user-mention" href="https://hashnode.com/@hashnode">Hashnode</a>.</p>
<h2 id="write-functions-for-everything">Write Functions for everything</h2>
<p>Most of the times we write functionality for many things but we don't name it. Keeping everything inside a function helps to again search for what you want easily. Also just keep one functionality inside one function. </p>
<pre><code class="lang-js"><span class="hljs-comment">// Bad code</span>
<span class="hljs-keyword">let</span> number1=<span class="hljs-number">2</span>;
<span class="hljs-keyword">let</span> number2=<span class="hljs-number">5</span>;

<span class="hljs-keyword">let</span> sum= number1+number2;

<span class="hljs-comment">// Good</span>
<span class="hljs-keyword">const</span> sum = <span class="hljs-function">(<span class="hljs-params">number1,number2</span>) =&gt;</span>{
    <span class="hljs-keyword">return</span> number1+number2;
}

<span class="hljs-built_in">console</span>.log(sum(<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
</code></pre>
<h2 id="eliminate-decimals-without-killing-performance">Eliminate Decimals without killing performance</h2>
<p>You might have a situation where you need to generate random whole numbers between 0 to 1000 and we usually use math.floor or math.ceil</p>
<pre><code class="lang-js"><span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random()*<span class="hljs-number">1000</span>)
</code></pre>
<p>but instead of that try using</p>
<pre><code class="lang-js">~~ (<span class="hljs-built_in">Math</span>.random()*<span class="hljs-number">1000</span>)
</code></pre>
<p>this can improve performance when micro-optimization of code. refer to this  <a target="_blank" href="http://rocha.la/JavaScript-bitwise-operators-in-practice">article</a>  to know more.</p>
<h2 id="deleting-array-like-a-pro">Deleting array like a pro</h2>
<p> There are several ways to delete an array on javascript but this is my favourite way.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> numbers=[<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>];
numbers.length=<span class="hljs-number">0</span>;
</code></pre>
<hr />
<p>Most of the times we jump into a language without knowing its fundamentals but I hope with this article you would write better code in JavaScript . </p>
<blockquote>
<p>You can never learn from just one article. Google concepts and read multiple articles, books and play around the code by making projects and that's how you learn. </p>
</blockquote>
<p>Checkout a curration of learning resources for JavaScript by <a class="user-mention" href="https://hashnode.com/@rahxul">Rahul</a>  <a target="_blank" href="https://blog.rahulism.co/the-ultimate-and-free-javascript-resources">here</a> .</p>
]]></content:encoded></item><item><title><![CDATA[Convert your Website into an APP with 3 easy steps]]></title><description><![CDATA[There are several websites which let you convert your website into an Android/IOS app, But in reality, They provide a web view of the website with tons of watermark
Instead of using these services let me tell you about PWA's and how you can convert y...]]></description><link>https://blog.hrithwik.dev/convert-your-website-into-an-app-easily</link><guid isPermaLink="true">https://blog.hrithwik.dev/convert-your-website-into-an-app-easily</guid><category><![CDATA[PWA]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Fri, 16 Oct 2020 03:26:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602759688887/JBOQ2F1Fs.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are several websites which let you convert your website into an Android/IOS app, But in reality, They provide a web view of the website with tons of watermark</p>
<p>Instead of using these services let me tell you about PWA's and how you can convert your website into a Progressive Web Application (PWA) by following 3 easy steps.</p>
<h2 id="heading-whats-a-pwa">What's a PWA?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602742334446/jFSmL3aGw.png" alt="WHAT (1).png" /></p>
<p>** Progressive Web Applications ** is a technology built by Google developers which allow developers to add native looks and some features like offline load &amp; Push Notifications to your website.</p>
<h2 id="heading-advantages-of-pwa">Advantages of PWA</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602743943196/ctqg7BwDZ.png" alt="WHAT (6).png" /></p>
<ul>
<li><p><strong>Easy Installation for users:</strong> It just take few seconds to install PWAs and they are lightweight which is the reason why Instagram lite and Facebook lite is basically a PWA.</p>
</li>
<li><p><strong>Easy to build:</strong> Web technologies are easier to learn than native development and numbers of developers required to build a project is also less.</p>
</li>
<li><p><strong>Cost-Effective:</strong> With one code base your website can run on android phones, iPhones and Windows Computers.</p>
</li>
<li><p><strong>Better Performance:</strong> With image and code caching the performance is increased drastically.</p>
</li>
</ul>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li><p>Basics of HTML and JavaScript</p>
</li>
<li><p>Current Website should load with HTTPS</p>
</li>
<li><p>Current Website should be responsive</p>
</li>
</ul>
<h2 id="heading-how-can-you-do-it">How can you do it?</h2>
<p>These are the three files needed to convert your current website into an installable PWA.</p>
<ul>
<li><p><a class="post-section-overview" href="#manifest-json">Manifest.json</a></p>
</li>
<li><p><a class="post-section-overview" href="#service-worker">Service Worker</a></p>
</li>
<li><p><a class="post-section-overview" href="#adding-the-installable-component">Installable Navigator</a></p>
</li>
</ul>
<h2 id="heading-manifest-json">Manifest JSON</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602743687301/kEZeCYE18.png" alt="WHAT (4).png" /></p>
<p>This is the file which helps you add splash screens and icons to your app. In this file, you specify basic metadata like your app name, icon size, icon directory and start URL of your website.</p>
<p>Here is my Manifest.JSON which you can copy and replace it with your details.</p>
<pre><code class="lang-javascript">{ 
  <span class="hljs-string">"name"</span>: <span class="hljs-string">"Hrithwik Bharadwaj"</span>,
  <span class="hljs-string">"short_name"</span>: <span class="hljs-string">"Hrithwik"</span>,
  <span class="hljs-string">"description"</span>: <span class="hljs-string">"Portfolio PWA of Hrithwik Bharadwaj"</span>,
  <span class="hljs-string">"icons"</span>: [
    {
      <span class="hljs-string">"src"</span>: <span class="hljs-string">"/assets/img/icons/512x512.png"</span>,
      <span class="hljs-string">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-string">"sizes"</span>: <span class="hljs-string">"512x512"</span>
    },
    {
      <span class="hljs-string">"src"</span>: <span class="hljs-string">"/assets/img/icons/256x256.png"</span>,
      <span class="hljs-string">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-string">"sizes"</span>: <span class="hljs-string">"256x256"</span>
    },
    {
      <span class="hljs-string">"src"</span>: <span class="hljs-string">"/assets/img/icons/192x192.png"</span>,
      <span class="hljs-string">"type"</span>: <span class="hljs-string">"image/png"</span>,
      <span class="hljs-string">"sizes"</span>: <span class="hljs-string">"192x192"</span>
    }
  ],
  <span class="hljs-string">"start_url"</span>: <span class="hljs-string">"/"</span>,
  <span class="hljs-string">"scope"</span>: <span class="hljs-string">"/"</span>,
  <span class="hljs-string">"dir"</span>: <span class="hljs-string">"ltr"</span>,
  <span class="hljs-string">"background_color"</span>: <span class="hljs-string">"#111111"</span>,
  <span class="hljs-string">"display"</span>: <span class="hljs-string">"standalone"</span>,
  <span class="hljs-string">"theme_color"</span>: <span class="hljs-string">"#111111"</span>,
  <span class="hljs-string">"orientation"</span>: <span class="hljs-string">"portrait"</span>,
  <span class="hljs-string">"prefer_related_applications"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>This might be confusing to understand if you are a beginner so just check out this <a target="_blank" href="https://manifest-gen.netlify.app/">manifest generator</a> to generate icons and later download the file.</p>
<p>Also don't forget to Include this in your HTML file</p>
<pre><code class="lang-HTML"> <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/static/manifest.json"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"manifest"</span>&gt;</span>
</code></pre>
<h2 id="heading-service-worker">Service Worker</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602743693680/oRZ9df2Qk.png" alt="WHAT (5).png" /></p>
<p>This file helps in making your app work offline by caching important files. If you have worked on React or Vue Projects this file is usually shipped along.</p>
<p>Here I am using WorkBox API for service worker as its very simple. Just create a file called sw.js and paste the below code there.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (<span class="hljs-string">'undefined'</span> === <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span>) {
    importScripts(<span class="hljs-string">'https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'</span>);
}

workbox.core.skipWaiting();
workbox.core.clientsClaim();

<span class="hljs-keyword">if</span> (workbox) {

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Yay! Workbox is loaded 🎉`</span>);

    workbox.precaching.precacheAndRoute([
        {
            <span class="hljs-string">"url"</span>: <span class="hljs-string">"/"</span>,
            <span class="hljs-string">"revision"</span>: <span class="hljs-string">"1"</span>
        }
    ]);

    workbox.routing.registerRoute(
        <span class="hljs-regexp">/\.(?:js|css)$/</span>,
        <span class="hljs-keyword">new</span> workbox.strategies.StaleWhileRevalidate({
            <span class="hljs-attr">cacheName</span>: <span class="hljs-string">'static-resources'</span>,
        }),
    );

    workbox.routing.registerRoute(
        <span class="hljs-regexp">/\.(?:png|gif|jpg|jpeg|svg)$/</span>,
        <span class="hljs-keyword">new</span> workbox.strategies.CacheFirst({
            <span class="hljs-attr">cacheName</span>: <span class="hljs-string">'images'</span>,
            <span class="hljs-attr">plugins</span>: [
                <span class="hljs-keyword">new</span> workbox.expiration.Plugin({
                    <span class="hljs-attr">maxEntries</span>: <span class="hljs-number">60</span>,
                    <span class="hljs-attr">maxAgeSeconds</span>: <span class="hljs-number">30</span> * <span class="hljs-number">24</span> * <span class="hljs-number">60</span> * <span class="hljs-number">60</span>, <span class="hljs-comment">// 30 Days</span>
                }),
            ],
        }),
    );

    workbox.routing.registerRoute(
        <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'https://fonts.(?:googleapis|gstatic).com/(.*)'</span>),
        <span class="hljs-keyword">new</span> workbox.strategies.CacheFirst({
            <span class="hljs-attr">cacheName</span>: <span class="hljs-string">'googleapis'</span>,
            <span class="hljs-attr">plugins</span>: [
                <span class="hljs-keyword">new</span> workbox.expiration.Plugin({
                    <span class="hljs-attr">maxEntries</span>: <span class="hljs-number">30</span>,
                }),
            ],
        }),
    );
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Boo! Workbox didn't load 😬`</span>);
}

workbox.googleAnalytics.initialize();
</code></pre>
<p>Now that you have created an sw.js file just add the link to it on your HTML page.</p>
<pre><code class="lang-HTML"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"sw.js"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<h2 id="heading-adding-the-installable-component">Adding the installable component</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602691361972/tzUp6E9OQ.gif" alt="lolzRag.gif" /></p>
<p>This part is the one which will allow you to get automatic "install now" prompt.</p>
<pre><code class="lang-javascript">   &lt;script&gt;
            <span class="hljs-keyword">if</span> (<span class="hljs-string">'serviceWorker'</span> <span class="hljs-keyword">in</span> navigator) {
              navigator.serviceWorker
                .register(<span class="hljs-string">"sw.js"</span>, {<span class="hljs-attr">scope</span>: <span class="hljs-string">'/'</span>})
                .then(<span class="hljs-function"><span class="hljs-params">registration</span> =&gt;</span> {
                  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"ServiceWorker running"</span>);
                })
                .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
                   <span class="hljs-built_in">console</span>.log(err);
                })
            }

&lt;/script&gt;
</code></pre>
<p>Copy this and add it in your HTML file.</p>
<hr />
<h3 id="heading-testing">Testing</h3>
<p>After you add these things. To check if everything is working fine, Use Lighthouse in chrome and check if it is showing a PWA sign.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602818537815/uF0ATL4OB.jpeg" alt="dev.jpg" /></p>
<hr />
<h2 id="heading-what-next">What next?</h2>
<p>PWA's can have many other features and even have a different type of service worker. Above code was the easiest implementation for beginners.</p>
<p>Below are some small things which you can add.</p>
<h3 id="heading-custom-install-button">Custom Install Button</h3>
<p>You can do something like this where the button hides after installation using this code some simple JavaScript code and CSS.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602690787891/X3aWKlpz1.gif" alt="lol.gif" /></p>
<h3 id="heading-push-notifications">Push Notifications</h3>
<p>From BookMyShow to Instagram everyone sends Push Notifications from PWA to their users. This can be implemented using <a target="_blank" href="https://onesignal.com/">OneSignal</a> or <a target="_blank" href="https://medium.com/firebase-developers/mobile-app-push-notification-with-firebase-cloud-functions-and-realtime-database-194a82e43ba">Firebase Cloud Functions</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602740998803/YsJ17UID7.jpeg" alt="push.JPG" /></p>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you have a small team which has already built a mobile first website than it's easier to switch to PWA.</p>
<p>To be honest, it's a temporary fix until your native app is getting ready.  </p>
<p>Yeah sure, PWA looks like a mobile app but it isn't as smooth as a native app. A lot of developers like me are waiting for PWA's to become smooth.</p>
<p>(Update: There is also a new kind of Installation Widget that twitter started using for it's PWA - Here is <a target="_blank" href="https://blog.hrithwik.dev/how-to-add-modern-installation-ui-for-your-pwa">short guide</a> on it.)</p>
]]></content:encoded></item><item><title><![CDATA[Top 10 Python Packages you should try right now]]></title><description><![CDATA[Python has various packages to make your life easy so that you don't need to code from scratch. These are some of the packages which you can use to build your next project in Python.
PDF Miner
pip install pdfminer
PDF Miner   lets you extract text fr...]]></description><link>https://blog.hrithwik.dev/top-10-python-packages-you-should-try-right-now</link><guid isPermaLink="true">https://blog.hrithwik.dev/top-10-python-packages-you-should-try-right-now</guid><category><![CDATA[Python]]></category><category><![CDATA[python beginner]]></category><category><![CDATA[HashnodeCommunity]]></category><category><![CDATA[Hashnode]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Fri, 09 Oct 2020 06:16:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1602224171705/KPrMYG4Ge.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python has various packages to make your life easy so that you don't need to code from scratch. These are some of the packages which you can use to build your next project in Python.</p>
<h2 id="pdf-miner">PDF Miner</h2>
<pre><code><span class="hljs-attribute">pip</span> install pdfminer
</code></pre><p><strong><a target="_blank" href="https://github.com/euske/pdfminer">PDF Miner </a> </strong> lets you extract text from pdf files. This can be useful if you are building a product which needs text from say resumes or reports.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1601567476205/gEMzqA16J.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1601567476205/gEMzqA16J.png" /></p>
<p>There is also a similar library called <strong><a target="_blank" href="https://github.com/OmkarPathak/pyresparser">PyreParser </a> </strong> which is specially made just for extracting resume information(This tech is pretty much used in every company in the hiring process)</p>
<hr />
<h2 id="pillow">Pillow</h2>
<pre><code><span class="hljs-attribute">pip</span> install Pillow==<span class="hljs-number">2</span>.<span class="hljs-number">2</span>.<span class="hljs-number">1</span>
</code></pre><p><strong> <a target="_blank" href="https://github.com/python-pillow/Pillow">Pillow</a>  </strong> is a library which allows for image manipulation &amp; conversion. You can do a wide variety of things like adding text to an image or blurring an image. Below is a simple example of adding text to an image.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1601567416894/lZZwHPh8p.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1601567416894/lZZwHPh8p.png" />
Below is the before and after running this code. We just added "hashnode is amazing" in the bottom right using the x y coordinates.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602186397002/p9xKUVxh5.png" alt="New Project(1).png" /></p>
<p>There is also a python package called <strong> <a target="_blank" href="movie">moviepy</a> </strong> which lets you do similar things but with videos.</p>
<hr />
<h2 id="opencv">OpenCV</h2>
<pre><code class="lang-python">pip install opencv-python
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602215251451/FTsTOiPzs.png" alt="image.png" /></p>
<p>This is one of the booming packages and LinkedIn is filled with project demos built with OpenCV. You can do anything from resizing an image to Controlling Subway surfers from your hands through image recognition. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602172874634/Pzr3fVlCg.png" alt="carbon(12).png" /></p>
<p>Above is a simple example to open a greyscale image and resize it.</p>
<p>Refer to these Resources to learn more about OpenCV( <a target="_blank" href="https://www.edureka.co/blog/python-opencv-tutorial/">Edureka</a> 
and <a target="_blank" href="https://www.youtube.com/c/MurtazasWorkshopRoboticsandAI">Murtazas YouTube Channel</a> )</p>
<hr />
<h2 id="furl">Furl</h2>
<pre><code><span class="hljs-attribute">pip</span> install furl
</code></pre><p><a target="_blank" href="https://github.com/gruns/furl">Furl</a> makes parsing and manipulating URLs easy for you. Here is an example of paths and query using furl </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602172475271/YzWB1Gpjn.png" alt="carbon(7).png" /></p>
<p>Output:</p>
<pre><code class="lang-python">http://www.google.com/path?two=<span class="hljs-number">2</span>&amp;three=<span class="hljs-number">3</span>
</code></pre>
<hr />
<h2 id="scikit-learn">Scikit- learn</h2>
<pre><code><span class="hljs-attribute">pip</span> install scikit-learn
</code></pre><p><strong>Scikit- learn</strong> can be used for a variety of applications which include classification, regression, clustering, model selection, naive Bayes’, grade boosting, K-means, and preprocessing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602186441729/tVTIFwkbr.png" alt="carbon(14).png" />
Above is a snippet from one of my 2nd-year projects at engineering which predicts prices for houses in Bangalore. This uses Linear Regression and I didn't know the formula and other details but using scikit-learn I could easily use the concept to build a model.</p>
<h2 id="html2text">Html2Text</h2>
<pre><code><span class="hljs-attribute">pip</span> install html<span class="hljs-number">2</span>text
</code></pre><p>This allows you to convert HTML code to markdown with just one line of python code.<br />But you can't directly add websites instead of HTML code, using a beautiful soup can help you do that. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1601567238934/El7D8Tr6j.png" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1601567238934/El7D8Tr6j.png" /></p>
<p><strong>Output</strong> :</p>
<pre><code class="lang-markdown"><span class="hljs-section">#  Hello world</span>

<span class="hljs-strong">**Html2 text is amazing**</span>

[<span class="hljs-string"> My Blogs are cool </span>](<span class="hljs-link">blog.hrithwik.me/</span>)
</code></pre>
<hr />
<h2 id="beautiful-soup">Beautiful Soup</h2>
<pre><code><span class="hljs-attribute">pip</span> install beautifulsoup<span class="hljs-number">4</span>
</code></pre><p><strong>Beautiful Soup</strong> allows you to parse HTML data from websites and get the data you want by finding the element you want using id or class name. This is one of the most used tools in the field of web scraping. (NOTE: Web Scrapping might be illegal on some websites )</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602172933926/YFDvKh1jb.png" alt="carbon(8).png" /></p>
<p>Here We just parsed through <a class="user-mention" href="https://hashnode.com/@pbteja1998">Bhanu's</a> Article and Generated a markdown from the URL using  <a class="post-section-overview" href="#html2text">HTML2Text</a></p>
<hr />
<h2 id="kivy">Kivy</h2>
<pre><code><span class="hljs-attribute">pip</span> install kivy==<span class="hljs-number">1</span>.<span class="hljs-number">11</span>.<span class="hljs-number">1</span>
</code></pre><p> <a target="_blank" href="https://kivy.org/doc/stable-1.10.1/installation/installation.html">Kivy</a>  is a really interesting GUI framework that you can use to create desktop user interfaces and mobile applications on both iOS and Android.</p>
<p> Kivy applications will not look like native apps on any platform. This can be an advantage if you want your application to look and feel different from the competition. There are even some alternatives like PyQt and Quirt.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602172834173/5hqHM65XE.png" alt="carbon(9).png" /></p>
<hr />
<h2 id="faker">Faker</h2>
<pre><code class="lang-python">pip install Faker
</code></pre>
<p>Faker is a Python package that generates fake data for you. This can be really useful for testing or bootstrapping your database.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602186490378/cAKYe-5sY.png" alt="carbon(10).png" /></p>
<p>You can even checkout <a target="_blank" href="https://pypi.org/project/radar/">radar</a> which can generate random date and time.</p>
<h2 id="selenium">Selenium</h2>
<pre><code class="lang-python">pip install selenium
</code></pre>
<p>Selenium is one of the testing frameworks which can be used for fun stuff like automation and building bots. You can automate anything like sending WhatsApp messages to increasing views for your blog.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1602172635341/2Iv8kHbMT.png" alt="carbon(11).png" /></p>
<p>This is a code which opens your website for n number of times in a browser. You can add different user-agents as well. </p>
<hr />
<h2 id="conclusion">Conclusion</h2>
<p>These were some packages which can do testing or build machine learning projects. Try using any one of them and let me know what you built using these Packages. Hit me up on <a target="_blank" href="https://twitter.com/HSBTechYt">Twitter</a> or  <a target="_blank" href="https://www.linkedin.com/in/hrithwik-bharadwaj-a77810150/">Linkedin </a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1599034192769/tdRNTK_i9.jpeg" alt="hrithwik.jpg" /></p>
]]></content:encoded></item><item><title><![CDATA[Why you shouldn't use Double Equals Operator in JavaScript]]></title><description><![CDATA[Unlike many other programming languages JavaScript has both double equals '=='   and triple equals  '==='  comparison operator. 
They might seem to do the same exact thing, but there is one major difference between the two that makes triple equals al...]]></description><link>https://blog.hrithwik.dev/lose-equality-and-strict-equality-in-javascript</link><guid isPermaLink="true">https://blog.hrithwik.dev/lose-equality-and-strict-equality-in-javascript</guid><category><![CDATA[Hashnode]]></category><category><![CDATA[2Articles1Week]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[HashnodeCommunity]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Wed, 02 Sep 2020 08:44:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1599035105651/VszI3iNvz.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Unlike many other programming languages JavaScript has both double equals <strong>'=='</strong>   and triple equals <strong> '===' </strong> comparison operator. 
They might seem to do the same exact thing, but there is one major difference between the two that makes triple equals almost always better.</p>
<h2 id="whats-the-difference">What's the Difference?</h2>
<h3 id="the-operator">The '==' Operator</h3>
<p>This is called <strong>Loose equality comparison operator</strong> in JavaScript.</p>
<p>Let's take an example here when comparing a string and an integer with the same value.</p>
<pre><code><span class="hljs-keyword">let</span> a=<span class="hljs-number">1</span>;
<span class="hljs-keyword">let</span> b=<span class="hljs-string">'1'</span>; 
<span class="hljs-built_in">console</span>.log(a==b);
</code></pre><p><strong>OUTPUT</strong></p>
<pre><code><span class="hljs-literal">true</span>
</code></pre><p>or wait let's try this</p>
<pre><code><span class="hljs-keyword">let</span> a=<span class="hljs-number">1</span>;
<span class="hljs-keyword">let</span> b=<span class="hljs-literal">true</span>; 
<span class="hljs-built_in">console</span>.log(a==b);
</code></pre><p><strong>OUTPUT</strong></p>
<pre><code><span class="hljs-literal">true</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1599030905638/ChglLb-z-.jpeg" alt="https://cdn.hashnode.com/res/hashnode/image/upload/v1599030905638/ChglLb-z-.jpeg" /></p>
<p><strong>WHAT?? How is it true??</strong></p>
<p>You may be wondering how this is possible? well because the '==' operator takes only value into consideration, not the type. Therefore matches boolean true to 1 by converting one of them. </p>
<h3 id="the-operator">The '===' Operator</h3>
<p>This is called <strong>Strict equality comparison operator</strong> in JavaScript.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> a=<span class="hljs-number">1</span>;
<span class="hljs-keyword">let</span> b=<span class="hljs-string">'1'</span>; 
<span class="hljs-keyword">let</span> c=<span class="hljs-literal">true</span>;
<span class="hljs-built_in">console</span>.log(a===b);
<span class="hljs-built_in">console</span>.log(a===c);
</code></pre>
<pre><code class="lang-js"><span class="hljs-literal">false</span>
<span class="hljs-literal">false</span>
</code></pre>
<p>This returns false for the values which are not of a similar type. This operator performs type casting for equality. If we compare 1 with '1' using ===, then it will return a false value.</p>
<h2 id="when-to-use-the-operator">When to use the '==' Operator</h2>
<p>I don't usually recommend to use this often but you can use this when </p>
<ul>
<li>Checking if a value is null/undefined</li>
<li>When you know both the operators of the same type</li>
</ul>
<h2 id="to-summarize">To Summarize</h2>
<ul>
<li><h3 id="operator-is-value-based-comparison"><strong> '==' </strong>    Operator is Value based comparison</h3>
</li>
<li><h3 id="operator-is-typevalue-based-comparison"><strong>'==='</strong>    Operator is Type+Value based comparison</h3>
</li>
</ul>
<p>So most of the times you should be using triple equals insead of double equals as it's more precise, accurate and doesn't bring up bugs which are not easy to find.</p>
<hr />
<p>I love speaking to new people on the internet. Hit me up on <a target="_blank" href="https://twitter.com/hrithwik_">Twitter</a> or  <a target="_blank" href="https://www.linkedin.com/in/hrithwik-bharadwaj-a77810150/">Linkedin </a>, Lets talk tech.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1599034192769/tdRNTK_i9.jpeg" alt="hrithwik.jpg" /></p>
]]></content:encoded></item><item><title><![CDATA[How to Deploy Flask apps for Free with Heroku]]></title><description><![CDATA[Let's say you have built a flask app and want to deploy it for free. For example, Here is a single page flask app which I built few days back which displays random developer quotes.

There are a few options you have like  PythonAnyWhere  or Nitrious....]]></description><link>https://blog.hrithwik.dev/deploy-flask-apps-for-free-using-heroku</link><guid isPermaLink="true">https://blog.hrithwik.dev/deploy-flask-apps-for-free-using-heroku</guid><category><![CDATA[Python]]></category><category><![CDATA[flash]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[Heroku]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Mon, 31 Aug 2020 12:45:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598875216475/9o7giXaJX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's say you have built a flask app and want to deploy it for free. For example, Here is a single page flask app which I built few days back which displays random developer quotes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598857925804/n7f79Se7D.jpeg" alt="website.jpg" /></p>
<p>There are a few options you have like  <a target="_blank" href="https://www.pythonanywhere.com/">PythonAnyWhere</a>  or Nitrious.io but both of them aren't that reliable and easy. That's where  <a target="_blank" href="heroku.com">Heroku</a>  comes in.</p>
<h2 id="whats-heroku">What's Heroku?</h2>
<p> <a target="_blank" href="https://devquoteflask.herokuapp.com/">
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598854899836/BHP66bhCC.png" alt="heroku-logo.png" /></a> </p>
<p>Heroku is a container-based cloud Platform as a Service (PaaS). You can use Heroku to deploy, manage, and scale modern apps. You don't need to add credit card details to deploy apps here.</p>
<h3 id="advantages-of-heroku">Advantages of Heroku</h3>
<ul>
<li>Deployable using Git</li>
<li>Free of Cost with 450 Hours of runtime </li>
</ul>
<h2 id="tools-needed-on-your-machine">🛠️Tools needed on your machine</h2>
<p>Before we begin you need to install these on to your windows/mac machine with the Gunicorn Pip Package.</p>
<ul>
<li><strong><a target="_blank" href="https://desktop.github.com/">Github</a></strong></li>
<li><strong><a target="_blank" href="https://devcenter.heroku.com/articles/heroku-cli#download-and-install">Heroku CLI</a></strong></li>
<li><strong><a target="_blank" href="https://pypi.org/project/gunicorn/">Gunicorn </a>  </strong></li>
</ul>
<h2 id="setting-up-heroku">💻Setting up Heroku</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598854912425/iXKYSIJB2.png" alt="hash3.PNG" /></p>
<p>Now that you have the essential tools installed on your PC/laptop, Go to <a target="_blank" href="https://signup.heroku.com/login">Heroku Signup</a> and fill in your details by confirming your email address. </p>
<p>Open the project folder and open command line terminal there and do the following commands</p>
<pre><code class="lang-bash">heroku login
</code></pre>
<p>If everything is good you will see something like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598858392095/kdsXnmzah.png" alt="hash2.PNG" /></p>
<h2 id="three-important-files-for-heroku">🦄 Three important files for Heroku</h2>
<p>Before deploying the flask app to Heroku you need to create these 3 files in your project.</p>
<ul>
<li>The procfile</li>
<li>Requieremnet.txt</li>
<li>runtime.txt</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598858439864/C2_SYwuv0.png" alt="hash4.PNG" /></p>
<h3 id="the-proc-file">The Proc File</h3>
<p>In simple words, this file tells the Heroku machine what program to run by which dyno. In case you are interested in reading more about the Proc File check this <a target="_blank" href="https://devcenter.heroku.com/articles/procfile">article.</a></p>
<pre><code class="lang-bash">web: gunicorn app:app
</code></pre>
<h3 id="requirementtxt">Requirement.txt</h3>
<p>This file contains all the packages which are imported in the  <a target="_blank" href="https://blog.hrithwik.me/deploy-flask-apps-for-free-using-heroku">app.py</a>  which needs to be installed. You can generate this using <a target="_blank" href="https://pypi.org/project/pipreqs/">pipreqs</a> utility or using the command "pip freeze". Also don't forget to add jinja2 and gunicorn inside requirements.txt file.</p>
<pre><code class="lang-jsx">Flask_Compress==<span class="hljs-number">1.4</span><span class="hljs-number">.0</span>
Flask==<span class="hljs-number">1.1</span><span class="hljs-number">.0</span>
Flask_SSLify==<span class="hljs-number">0.1</span><span class="hljs-number">.5</span>
requests==<span class="hljs-number">2.20</span><span class="hljs-number">.1</span>
gunicorn
Jinja2
gevent
</code></pre>
<h3 id="runtimetxt">Runtime.txt</h3>
<pre><code class="lang-bash">python-3.7.5
</code></pre>
<h2 id="deploying-to-heroku">🚀 Deploying to Heroku</h2>
<pre><code class="lang-bash">heroku create (your app name)
</code></pre>
<p>This would create a git repository and a Heroku app with the unique link generated. </p>
<pre><code class="lang-bash">D:\Deshik\HashNode\Developer Quotes&gt;heroku create devquoteflask
Creating ⬢ devquoteflask... <span class="hljs-keyword">done</span>
https://devquoteflask.herokuapp.com/ | https://git.heroku.com/devquoteflask.git
</code></pre>
<p>Now Heroku creates its own private git repo. You can either use it by typing the following command every time you add new changes to your project.</p>
<pre><code class="lang-bash">git init 
git commit -m <span class="hljs-string">"commit"</span>
git push heroku master
</code></pre>
<p>or you can even connect your GitHub repository so that every time you push something to your main GitHub repository, Any changes made to the app will automatically be reflected in the website. Follow this  <a target="_blank" href="https://www.freecodecamp.org/news/how-to-deploy-a-nodejs-app-to-heroku-from-github-without-installing-heroku-on-your-machine-433bec770efe/">article</a>  to connect your Github Repository to Heroku.</p>
<h2 id="my-single-page-flask-app">🌐 My Single Page Flask app</h2>
<p>Here is a simple Flask app I built for this article, Which Gives you new Programmers Quote every single time you refresh -  <a target="_blank" href="http://devquoteflask.herokuapp.com/">http://devquoteflask.herokuapp.com/</a>.</p>
<p><a target="_blank" href="https://github.com/hrithwikbharadwaj/BasicFlaskQuoteApp"><img src="https://github-readme-stats.vercel.app/api/pin/?username=hrithwikbharadwaj&amp;repo=BasicFlaskQuoteApp" alt /></a> 
Refer the full source code in case you have any doubt with the files </p>
<h2 id="whats-the-catch">😮 What's the Catch?</h2>
<p>The free tier of Heroku is actually pretty good. You are limited to 10k database rows and the dyno spools down when it hasn't been used in about 5 minutes.</p>
<p> It makes the initial page load quite slow and it won't be able to handle heavy traffic but it's a seriously generous package and great for development.</p>
<p>You are allowed to create only 5 projects with 450 hours of dynos per month without adding the credit card. By adding credit card you get extra 550 hours of dynos.</p>
<hr />
<p>Now that I helped you save some cash for deployment. Follow me on  <a target="_blank" href="https://twitter.com/HSBTechYt">Twitter</a>  and  <a target="_blank" href="https://www.linkedin.com/in/hrithwik-bharadwaj-a77810150/">Linkedin </a> to stay connected.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/HSBTechYt/status/1300411279517990915">https://twitter.com/HSBTechYt/status/1300411279517990915</a></div>
<p>Also, Check out my previous article on <a target="_blank" href="https://blog.hrithwik.me/how-i-created-a-python-meme-bot-for-instagram">How I Created a MEME Bot using Python </a> </p>
]]></content:encoded></item><item><title><![CDATA[Why everyone is using Firebase and Why you should too]]></title><description><![CDATA[What is FireBase?

Firebase is Backend as a Service (BaaS) where it takes care of user authentication, Database and hosting all by itself. 
My Experience with Firebase
I have personally built 3 production-level projects using most of the firebase fea...]]></description><link>https://blog.hrithwik.dev/why-everyone-is-using-firebase-and-why-you-should-too</link><guid isPermaLink="true">https://blog.hrithwik.dev/why-everyone-is-using-firebase-and-why-you-should-too</guid><category><![CDATA[Firebase]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[HashnodeCommunity]]></category><category><![CDATA[NoSQL]]></category><category><![CDATA[2Articles1Week]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Wed, 26 Aug 2020 11:03:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598437028556/KPvbpK9O8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><iframe width="100%" height="166" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/882292165&amp;color=%235edde9&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;show_teaser=true"></iframe></p>
<h2 id="what-is-firebase">What is FireBase?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598439512964/B3OfDiBGI.png" alt="social.png" /></p>
<p>Firebase is Backend as a Service (BaaS) where it takes care of user authentication, Database and hosting all by itself. </p>
<h2 id="my-experience-with-firebase">My Experience with Firebase</h2>
<p>I have personally built 3 production-level projects using most of the firebase features and I have faced 0 problems with it and the best part I haven't spent a single penny on it.</p>
<h2 id="3-reasons-why-you-should-care-about-firebase">3 Reasons Why you Should Care about Firebase</h2>
<ul>
<li><strong>Experience</strong> - Firebase has the best documentation and has good support in case you are stuck somewhere.</li>
<li><strong>Price </strong>- It's free for your small/experimental projects and you can pay as you go if the project grows linearly</li>
<li><strong>Maximize Time</strong> - You can implement a lot of features in less time with small code</li>
</ul>
<p>Go To <a target="_blank" href="http://console.firebase.com">console.firebase.com</a> and explore by creating a project inside but before that have a look at this article.</p>
<h2 id="what-does-firebase-offer">What does Firebase offer?</h2>
<ul>
<li><strong>Authentication</strong></li>
<li><strong>Firestore (NO SQL Database)</strong></li>
<li><strong>Hosting</strong></li>
<li><strong>Cloud Functions</strong></li>
</ul>
<h2 id="authentication">Authentication</h2>
<p>If you have to build an application which has “login” features you definitely know building an authentication system with encryption and other things involved is a pain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598372642203/zh7EqYs6u.png" alt="hash3.png" />
With Firebase authentication you can let users log in with email or even let users log in to your product via Google Sign in with a small piece of Code. 
Here is the documentation for  <a target="_blank" href="https://firebase.google.com/docs/auth/web/google-signin">Google sign in method</a>  and   <a target="_blank" href="https://firebase.google.com/docs/auth/web/email-link-auth">email sign in method</a> </p>
<h2 id="firestore">FireStore</h2>
<p>If you are a computer science student you might have learnt MYSQL which is a relation based SQL DBMS. </p>
<p>Firestore is No SQL database like Mongo DB which is made of Collections and Documents stored in JSON format. It has its own pros and cons. For beginners, this is very easy to learn, even querying/filtering is so much better.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598374159797/4FPpMISs9.png" alt="hash4.PNG" /></p>
<p>Let's say that we have to keep information about a user and keep a record of his order history. 
For that, we will build 2 collections </p>
<p>-Users
-Orders</p>
<p> which will have a document inside with information stored in JSON format.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598374183144/J_77SVjH-.png" alt="hash5.PNG" /></p>
<h2 id="hosting">Hosting</h2>
<p>So you have now built a Web App using Firebase and need to host it somewhere.
 Well, Firebase has got your back. 
Make sure that you have a folder with the public as a name which would have your index.html file. Project Structure should look something like this 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1598374811020/VdtPt3U8l.png" alt="hash6.PNG" />
Run the following commands to deploy your web app to firebase.</p>
<pre><code>Firebase <span class="hljs-keyword">init</span>
</code></pre><p>In Response, you get this</p>
<pre><code class="lang-cmd">? Are you ready to proceed? Yes
? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices.
 ( ) Database: Deploy Firebase Realtime Database Rules
 ( ) Firestore: Deploy rules and create indexes for Firestore
 ( ) Functions: Configure and deploy Cloud Functions
&gt;(*) Hosting: Configure and deploy Firebase Hosting sites
 ( ) Storage: Deploy Cloud Storage security rules
 ( ) Emulators: Set up local emulators for Firebase features
</code></pre>
<p>Choose the services as hosting and select a public folder where you should have your index.html inside. This is how it should look </p>
<pre><code class="lang-cmd">=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? public
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
? File public/index.html already exists. Overwrite? (y/N) N
</code></pre>
<p>After the initialization, you can deploy it with this code</p>
<pre><code><span class="hljs-attribute">firebase</span> deploy
</code></pre><p>You might want to connect your own domain or might get stuck at something. Refer to the  <a target="_blank" href="https://firebase.google.com/docs/hosting/quickstart">Firebase Hosting Documentation</a>  for better reference.</p>
<h2 id="cloud-functions">Cloud Functions</h2>
<p>This is one of the favourite things about Firebase is cloud Functions. I might write a few articles down the lane so stay tuned.</p>
<p>Cloud Functions is a hosted, private, and scalable Node.js environment where you can run JavaScript code. 
Cloud Functions for Firebase integrates the Firebase platform by letting you write code that responds to events and invokes functionality exposed by other Firebase features.</p>
<p>And it has a lot of interesting use cases, like:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/firebase/functions-samples/tree/master/fcm-notifications">You can send notification to users when data changes </a> </p>
</li>
<li><p><a target="_blank" href="https://github.com/firebase/functions-samples#image">Image processing</a> </p>
</li>
</ul>
<p>You can host only 2 cloud Functions for free of cost in a Spark plan, just keep that in mind.</p>
<h2 id="is-firebase-used-in-tech-companies">Is Firebase used in tech companies?</h2>
<p>Yes. Usually by startups without a lot of time and resources. Firebase is a godsend.</p>
<p>But not in big corporates where securing user data is a bigger priority, they prefer building it inhouse instead of using BaaS like firebase.</p>
<p>(The other reason why few companies don't prefer firebase is that the product they are building might be for global users and we know that some countries have banned google and hence firebase won't work there.)</p>
<p>Don't' worry though . if you understand how NO-SQL works using firebase, It's pretty similar to mongo, so it won't be a challenge.</p>
<h2 id="in-conclusion">In conclusion:</h2>
<p>Firebase is easily the best backend as a service for beginners or freelancers who are just getting off the ground.</p>
<hr />
<p>I will soon write on how you can integrate Firebase to Flask apps to stay tuned to my newsletter and follow me here on  <a target="_blank" href="https://blog.hrithwik.me/">Hashnode</a>. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.hrithwik.me">https://blog.hrithwik.me</a></div>
]]></content:encoded></item><item><title><![CDATA[How I Created a Python Meme Bot for Instagram !!]]></title><description><![CDATA[The Story behind
Most of my time is spent on Instagram and I use it mostly for the memes.
So, some of my friends told me that most of the memes are uploaded to Reddit and later spread to Instagram, and Reddit was the best place to go for funny conten...]]></description><link>https://blog.hrithwik.dev/how-i-created-a-python-meme-bot-for-instagram</link><guid isPermaLink="true">https://blog.hrithwik.dev/how-i-created-a-python-meme-bot-for-instagram</guid><category><![CDATA[2Articles1Week]]></category><category><![CDATA[Hashnode]]></category><category><![CDATA[Python]]></category><category><![CDATA[bot]]></category><category><![CDATA[Heroku]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Tue, 11 Aug 2020 16:55:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1597131237647/YZ8N3Wmop.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="the-story-behind">The Story behind</h1>
<p>Most of my time is spent on Instagram and I use it mostly for the memes.</p>
<p>So, some of my friends told me that most of the memes are uploaded to Reddit and later spread to Instagram, and Reddit was the best place to go for funny content but I wasn't a big fan of the Reddit UI and didn't really get used to it.</p>
<p>One day I randomly thought, what if I could start a meme page that gets content from Reddit but without downloading and uploading the images manually and still be the first account to upload those memes on Instagram straight from Reddit?</p>
<p>And, I Built a BOT which uploads memes from some subreddits like <strong>r/dankmemes</strong> and <strong>r/memes</strong> and uploads it on my Instagram account - <a target="_blank" href="https://instagram.com/thiru.bot">@thiru.bot</a></p>
<h2 id="how-did-i-do-it">How did I do it?</h2>
<p>At this stage, I was a beginner and knew few things about python, had some experience building flask apps, had some experience in web scrapping and had huge hunger to build this just to flex my skills with my friends.</p>
<p>Before I started building it I had to visualize what I needed?</p>
<ul>
<li>Reddit API &amp; Basics of web scrapping to get the images and save them.</li>
<li>Any Instagram API which lets me upload photos to my account.</li>
<li>A server to host this later to make it work 24/7</li>
</ul>
<blockquote>
<p>Friends, When you are a beginner you just google things, mix code from different repositories, add your own code and make it work.</p>
</blockquote>
<p>and that's what I did!
There were no Instagram Reddit bot but I found a Reddit to twitter project which gave me a clarity of thought in building this.</p>
<h2 id="the-working-instagram-api">The Working Instagram API</h2>
<p>The Official Instagram API doesn't allow developers to upload photos or videos to post. Most of the other third party APIs also dint work but at last found this pip package.</p>
<pre><code class="lang-python">pip install instabot
</code></pre>
<p>Later Tested if this worked by giving my Instagram credentials and uploaded a random photo from my computer.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> instabot <span class="hljs-keyword">import</span> Bot
bot=Bot()
bot.login(username=<span class="hljs-string">"thiru.jpg"</span>,password=<span class="hljs-string">"followMeOnInstagram"</span>)

bot.upload_photo(<span class="hljs-string">'hey.png'</span>,caption=(<span class="hljs-string">"Test Upload "</span>))
</code></pre>
<p>and it worked :)</p>
<p>Next step - Scrapping the latest images from subreddits</p>
<h2 id="getting-images-from-reddit">Getting Images from Reddit</h2>
<p>To get the latest submissions from our subreddits we will be using PRAW API from subreddit. it's pretty simple not to worry.</p>
<h3 id="setting-up-praw-api">Setting up Praw API</h3>
<pre><code class="lang-python">reddit = praw.Reddit(client_id=<span class="hljs-string">''</span>,
client_secret=<span class="hljs-string">''</span>,
username=<span class="hljs-string">''</span>,
password=<span class="hljs-string">''</span>,
user_agent=<span class="hljs-string">''</span>)
</code></pre>
<h3 id="creating-an-reddit-app">Creating an Reddit App</h3>
<p>To Fill the above details you need to create an app on Reddit, Just Open <a target="_blank" href="https://ssl.reddit.com/prefs/apps/">https://ssl.reddit.com/prefs/apps/ </a> and click on create app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1596813314528/05I9oEKoA.png" alt="praw.PNG" /></p>
<p>I am here creating an app with the name test app. Client_Id parameter (the one which is below personal use script in the image above), client_secret is the secret key available. For username and password give your Reddit username and password. User Agent can be blank or chrome.</p>
<h3 id="setting-up-subreddits-to-get-memes">Setting up subreddits to get memes</h3>
<pre><code class="lang-python">red=<span class="hljs-string">'dankmemes'</span>
subreddit = reddit.subreddit(red)
newMemes = subreddit.hot(limit=<span class="hljs-number">3</span>)
</code></pre>
<p>I choose the subreddit 'dankmemes' and <strong> NewMemess </strong> Praw Class has all the hottest submissions from the subreddit.
You can get any type of submissions
(refer to official documentation <a target="_blank" href="https://praw.readthedocs.io/en/latest/code_overview/models/subreddit.html">here</a> )</p>
<h2 id="validating-and-picking-only-photos">Validating and Picking only Photos</h2>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> submission <span class="hljs-keyword">in</span> new_memes:
    <span class="hljs-keyword">if</span> submission.is_self == <span class="hljs-literal">True</span>:
        print(<span class="hljs-string">"Post was text, skipping to next post."</span>)
        <span class="hljs-keyword">continue</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">pass</span>
url = submission.url
time.sleep(waitTime)
</code></pre>
<p>You want just photos to upload. 
So, You need to validate them and choose only the submissions which have photos.</p>
<h2 id="downloading-the-images">Downloading the images</h2>
<p>Before Storing the images from Reddit we check Two Things</p>
<ul>
<li>if the submission is an Video/text or an image using <strong>isImageLink(url) Function</strong> and it returns the extension name of the image(Eg: jpg,png)</li>
<li>If the image was posted before using <strong>already_uploaded(id)</strong> function so that we don't post the same memes again.</li>
</ul>
<p>You can check out those functions and full code on my GitHub Repo <a target="_blank" href="https://github.com/hrithwikbharadwaj/redditToInstaBot">here</a> also follow me on GitHub.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> isImageLink(url) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> already_uploaded(id):
    <span class="hljs-keyword">try</span>:
        img=requests.get(submission.url)
        filename=str(counter)+<span class="hljs-string">'.'</span>+IsImageLink(submission.url)
        filename=os.path.join(<span class="hljs-string">'images'</span>, filename)
        imagefile=open(filename, <span class="hljs-string">'wb'</span>)
        imagefile.write(img.content)
        imagefile.close()
        post_ids.append(submission.id) <span class="hljs-comment"># A list of all submission ids</span>
        log_insta(post_ids)
        photoAlbum.append({<span class="hljs-string">'File'</span>:filename, <span class="hljs-string">'Title'</span>:submission.title})
        <span class="hljs-comment">#dictionary of all photos</span>
        counter+=<span class="hljs-number">1</span>
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        print(e)
</code></pre>
<p>After checking, You can download the image and save it with the count+ the extension (Eg: 2.png or 3.jpg). </p>
<p>Later you save a list with all the post id.</p>
<p>Remember you had to check if the post was already uploaded. How will it know if it is posted already?
Yes, you will be logging the post_id of the image using the function <strong> log_insta(post_ids)</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">log_insta</span>(<span class="hljs-params">post_ids</span>):</span>
    <span class="hljs-keyword">for</span> post_id <span class="hljs-keyword">in</span> post_ids:
        <span class="hljs-keyword">with</span> open(POSTED_CACHE, <span class="hljs-string">'a'</span>) <span class="hljs-keyword">as</span> out_file:
            out_file.write(str(post_id) + <span class="hljs-string">'\n'</span>)
</code></pre>
<h3 id="downloading-the-images-from-imgur">Downloading the images from Imgur</h3>
<p>Some Redditors upload photos to Imgur, and to download those images, You will using <strong><em>beautifulSoup</em></strong> and scrape data from those submissions. After you download, the saving part is same as above so I won't be posting the whole code.</p>
<pre><code><span class="hljs-function">elif <span class="hljs-title">str</span>(<span class="hljs-params">submission.url</span>).<span class="hljs-title">lower</span>(<span class="hljs-params"></span>).<span class="hljs-title">startswith</span>(<span class="hljs-params"><span class="hljs-string">'https://imgur.com'</span></span>) or <span class="hljs-title">str</span>(<span class="hljs-params">submission.url</span>).<span class="hljs-title">lower</span>(<span class="hljs-params"></span>).<span class="hljs-title">startswith</span>(<span class="hljs-params"><span class="hljs-string">'http://imgur.com'</span></span>) and counter&lt;max_images:

    <span class="hljs-keyword">try</span>:
        html_page</span> = urllib.request.urlopen(submission.url)
        soup = BeautifulSoup(html_page, <span class="hljs-string">'lxml'</span>)
        images = []
        <span class="hljs-keyword">for</span> img <span class="hljs-keyword">in</span> soup.findAll(<span class="hljs-string">'img'</span>):
        images.append(<span class="hljs-string">'https:'</span>+img.<span class="hljs-keyword">get</span>(<span class="hljs-string">'src'</span>))

        img=requests.<span class="hljs-keyword">get</span>(images[<span class="hljs-number">0</span>])
        filename=str(counter)+<span class="hljs-string">'.'</span>+images[<span class="hljs-number">0</span>][<span class="hljs-number">-3</span>:]
</code></pre><h2 id="downloaded-the-images-what-next">Downloaded the images, What next?</h2>
<p>Now that we have all the 3 images in the photo album Dictionary with the File and Title we can upload it to instagram using our <strong><em> unofficial Instagram API </em></strong> and give credits to the authors,subreddit and also add captionTags.</p>
<pre><code>authors = <span class="hljs-string">''</span>.<span class="hljs-keyword">join</span>(str(e + <span class="hljs-string">', '</span>) <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> authors)
captionTags=<span class="hljs-string">'#binod #memes #dank'</span>
<span class="hljs-keyword">for</span> photo <span class="hljs-keyword">in</span> photoAlbum:
    img=photo[<span class="hljs-string">'File'</span>]
    captionText=photo[<span class="hljs-string">'Title'</span>]
bot.upload_photo(img,caption=(captionText + <span class="hljs-string">'\n'</span> +<span class="hljs-string">'Reddit Authors:'</span>+authors+<span class="hljs-string">'\n'</span> captionTags))
</code></pre><p>Later we delete the image we downloaded just not to waste disk space.</p>
<pre><code><span class="hljs-selector-tag">for</span> <span class="hljs-selector-tag">filename</span> <span class="hljs-selector-tag">in</span> <span class="hljs-selector-tag">glob</span>(filePath + <span class="hljs-string">'/*'</span>):
<span class="hljs-selector-tag">os</span><span class="hljs-selector-class">.remove</span>(filename)
</code></pre><p><strong> Now Put all this code together into a single Python File, Run it and Hola, You have now uploaded a meme from Reddit to Instagram from your Python Code </strong> In my case, I named the file  <a target="_blank" href="https://github.com/hrithwikbharadwaj/redditToInstaBot/blob/master/bot.py">bot.py</a>, thought of telling you this as this might be useful later in the deployment part.</p>
<p>But the <a target="_blank" href="https://github.com/hrithwikbharadwaj/redditToInstaBot/blob/master/bot.py">bot.py</a> is run on the local machine and we can't just run this 24/7 on our local machine. Any Fix?</p>
<h2 id="deployment">Deployment</h2>
<p>To Run The Bot in a server for 24/7 you need to deploy this to cloud.
I used Heroku to deploy this Instagram meme bot. Follow this article to set up a Heroku account and know the basics of Heroku. I will soon be writing an article on the same.<a target="_blank" href="https://medium.com/the-andela-way/deploying-your-flask-application-to-heroku-c99050bce8f9">How to Upload Flask apps to Heroku</a> .</p>
<p>You need 3 files to be created for the deployment of your bot into <strong>Heroku</strong> .</p>
<ul>
<li>ProcFile</li>
<li>Runtime.txt</li>
<li>Requirements.txt</li>
</ul>
<p><strong> Runtime.txt </strong></p>
<pre><code><span class="hljs-attribute">python</span>-<span class="hljs-number">3</span>.<span class="hljs-number">7</span>.<span class="hljs-number">3</span>
</code></pre><p>In <strong><em> Runtime.txt </em></strong> you specify what language your code is in.</p>
<p><strong> The ProcFile </strong></p>
<pre><code class="lang-js">web: python3 bot.py
<span class="hljs-attr">worker</span>: python3 bot.py
</code></pre>
<p>Here you will be specifying the python file to be run by the dynos and note that I created two of these just to make sure one of them always stays on and doesn't sleep. You later need to scale them.</p>
<p><strong> Requirements.txt </strong></p>
<pre><code><span class="hljs-attribute">imageio</span>==<span class="hljs-number">2</span>.<span class="hljs-number">4</span>.<span class="hljs-number">1</span>
<span class="hljs-attribute">praw</span>
<span class="hljs-attribute">requests</span>
<span class="hljs-attribute">urllib3</span>
<span class="hljs-attribute">keyboard</span>
<span class="hljs-attribute">pillow</span>
<span class="hljs-attribute">beautifulsoup4</span>
<span class="hljs-attribute">instabot</span>
</code></pre><p>Heroku in simple words creates a virtual machine so you need to mention what are the packages you want to install for your <strong>bot.py</strong> to work.</p>
<p>After Uploading these files into a single folder. It's time to scale your dynos</p>
<pre><code class="lang-cmd">heroku ps:scale web=1 worker=1
</code></pre>
<h2 id="a-working-meme-bot">A working meme BOT</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1597081036441/GATenoKV9.png" alt="thiru.bot.PNG" /></p>
<p>But yeah , I need to work on the followers count lol.</p>
<h2 id="problems-and-suggestions">Problems &amp; Suggestions</h2>
<ul>
<li>Instagram Detecting Bots</li>
<li>Upload Frequency</li>
<li>Heroku Running out of Credits</li>
<li>Dynamic Tags</li>
</ul>
<h3 id="instagram-detecting-bots">Instagram Detecting Bots</h3>
<p>Instagram DOES NOT like Bots. </p>
<p>Initially, when I started this, my bot was detected and banned for 1 day and was not allowed to use any Instagram features like liking, etc for 1 week.</p>
<h4 id="solution-which-worked-for-me">Solution which worked for me</h4>
<p>It took me weeks to crack this but the reason why my bot was getting detected is that my posts were only from one subreddit and the authors were mostly same and hashtags as well so every post had somethings similar and with same upload frequency and Instagram started detecting.</p>
<p>With no options left, I had to stop giving credits to authors in the caption and created a list of subreddits and used <strong> random </strong> function in Python to select one subreddit and stoped using tags which fixed the issue.Upload frequency also matters and I will be speaking about it in the next paragraphs.</p>
<h3 id="upload-frequency">Upload Frequency</h3>
<blockquote>
<p>How many Posts should you upload at a time?</p>
<p>How many hours once should you upload?</p>
</blockquote>
<p>The safe bet is <strong> 3 posts /hour </strong></p>
<h3 id="heroku-running-out-of-credits">Heroku Running out of credits</h3>
<p>Heroku gives 550 hours of free dynos when you create an account. I had used all the 550 dynos and all my projects on Heroku had shut down, luckily I gave my credit card information and was able to get an extra 450 hours of dynos, But that won't be sufficient if you want to run this bot forever as 30 days = 1800 hours.
I usually was turning off the dynos when I was going to sleep and turning it on when required so worked. This is the solution that worked out for me and just to remind you, this is hosted for completely free of cost so nothing to complain.</p>
<h3 id="dynamic-tags">Dynamic Tags</h3>
<p>So, removing tags helped with not getting banned but I wanted better reach as my account had just 3 followers from weeks so created multiple lists of <strong> trending hashtags </strong> and wrote a code to choose the hashtags according to the subreddit and its working great.</p>
<h3 id="what-did-we-learn-from-this">What Did we learn from this?</h3>
<ul>
<li>You Don't need to know everything to start building things. Just the Hunger is enough.</li>
<li>The results don't come just in the first iteration. Experiment Fix experiment.</li>
<li>You can't get a girlfriend by creating a Meme bot :(</li>
</ul>
<h3 id="github-repository">Github Repository</h3>
<p>I still haven't added a ReadMe file(working on it). But this article is sufficient to understand the working of the same.</p>
<p><strong> Here is the complete Code - <a target="_blank" href="https://github.com/hrithwikbharadwaj/redditToInstaBot">GitHub Repo</a> </strong></p>
]]></content:encoded></item><item><title><![CDATA[The Story Behind!]]></title><description><![CDATA[Hey Guys 👋🏻
I am Hrithwik Bharadwaj a 20-year-old Full Stack Developer and a Tech Enthusiast🧑🏻‍💻. 
I always consumed knowledge in video📺 and never read books or blogs📚. Over time I learnt how important it is to read and continued reading and l...]]></description><link>https://blog.hrithwik.dev/the-story-behind</link><guid isPermaLink="true">https://blog.hrithwik.dev/the-story-behind</guid><category><![CDATA[Hashnode]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Hello World]]></category><dc:creator><![CDATA[Hrithwik Bharadwaj]]></dc:creator><pubDate>Fri, 07 Aug 2020 09:12:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1596959494686/hH_J0Wx3_.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey Guys 👋🏻</p>
<p>I am Hrithwik Bharadwaj a 20-year-old Full Stack Developer and a Tech Enthusiast🧑🏻‍💻. 
I always consumed knowledge in video📺 and never read books or blogs📚. Over time I learnt how important it is to read and continued reading and loved the experience. Now want to get into writing as writing makes your thought process clear.</p>
<h2 id="experience">Experience</h2>
<p>I have experience working at a tech startup for about a year and learnt a lot of things there but still consider myself a beginner and love learning new things everyday.</p>
<h2 id="the-motive">The Motive</h2>
<p>When I started out my journey as a developer with zero knowledge I didn't know where to start, what to do, which language to start with which made me really anxious. I don't want the same thing to happen with others so started this blog.</p>
<p>I want to help new developers make the right decisions with right tricks and teach the basics of developing in short stories.</p>
<p>In these short stories, I will be explaining and documenting about my past and upcoming projects in the simplest ways.</p>
<p>I choose this platform as its ad-free and has an amazing community.</p>
<div class="hn-embed-widget" id="payment"></div><h2 id="social-media-presence">Social Media Presence</h2>
<ul>
<li>Funny Vlogs Instagram -  <a target="_blank" href="https://instagram.com/thiru.jpg">@thiru.jpg</a></li>
<li>Tech Videos YouTube -  <a target="_blank" href="https://YouTube.com/HSBTechYt">Subscribe Here!</a> </li>
<li>Random Thoughts Twitter - <a target="_blank" href="https://twitter.com/HSBTechYt"> @HSBTechYt</a> </li>
</ul>
]]></content:encoded></item></channel></rss>