<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shrihari Mohan</title>
    <description>The latest articles on Forem by Shrihari Mohan (@shrihari).</description>
    <link>https://forem.com/shrihari</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg</url>
      <title>Forem: Shrihari Mohan</title>
      <link>https://forem.com/shrihari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shrihari"/>
    <language>en</language>
    <item>
      <title>Dynamic open graph images for your website | No code using dynamicog.com</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 13 Oct 2024 08:39:47 +0000</pubDate>
      <link>https://forem.com/shrihari/dynamic-open-graph-images-for-your-website-no-code-using-dynamicogcom-n62</link>
      <guid>https://forem.com/shrihari/dynamic-open-graph-images-for-your-website-no-code-using-dynamicogcom-n62</guid>
      <description>&lt;p&gt;DynamicOG solves the hassle of creating images for your dynamic websites that contain lot of pages.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;og-images&lt;/code&gt; are the preview images you see when you share the link in any communication channels.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;og-image&lt;/code&gt; is added using meta tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"{{IMAGE_URL}}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;IMAGE_URL&lt;/code&gt; is the only one you should take care.&lt;/p&gt;

&lt;p&gt;To generate docs image like this &lt;/p&gt;

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

&lt;p&gt;Use the following url in your meta tags!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://dynamicog.com/og/docs/img?
logo=https%3A%2F%2Fdynamicog.com%2Ffillers%2Fstripe-logo.png&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;
title=Find%20a%20guide%20to%20integrate%20Stripe's%20payments%20APIs%20%7C%20Stripe&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;
sub=Payments%20infrastructure%20for%20the%20internet&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;
name=Stripe&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;
website=stripe.com&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;
dark=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just change in the url &lt;code&gt;dark=true&lt;/code&gt; to &lt;code&gt;dark=false&lt;/code&gt; you will get this &lt;/p&gt;

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

&lt;p&gt;Try with your content and logos! &lt;a href="https://www.dynamicog.com/og/docs" rel="noopener noreferrer"&gt;https://www.dynamicog.com/og/docs&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Find all the &lt;a href="https://dynamicog.com" rel="noopener noreferrer"&gt;templates here&lt;/a&gt; and its free to use! &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Generate Dynamic Open Graph Images using Nextjs</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 16 Jun 2024 17:47:27 +0000</pubDate>
      <link>https://forem.com/shrihari/generate-dynamic-open-graph-images-using-nextjs-4k9g</link>
      <guid>https://forem.com/shrihari/generate-dynamic-open-graph-images-using-nextjs-4k9g</guid>
      <description>&lt;h2&gt;
  
  
  Dynamic OG
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.dynamicog.com/"&gt;Dynamic OG&lt;/a&gt; helps developers easily create og images without needing to develop their proprietary code.&lt;/p&gt;

&lt;p&gt;It is completely free to use and a self-hosted paid version is also available.  This tutorial serves as a base for &lt;a href="https://www.dynamicog.com/"&gt;Dynamic OG&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are some of the templates available in &lt;a href="https://www.dynamicog.com/"&gt;Dynamic OG&lt;/a&gt;. Get started with the &lt;code&gt;Simple theme&lt;/code&gt; below. &lt;/p&gt;

&lt;p&gt;All these are dynamically generated based on the queries on the url.&lt;/p&gt;

&lt;p&gt;Use &lt;a href="https://www.dynamicog.com/"&gt;Dynamic OG&lt;/a&gt; for your projects/companies for free.&lt;/p&gt;

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

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

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

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

&lt;h2&gt;
  
  
  Getting started witht the simple theme
&lt;/h2&gt;

&lt;p&gt;We're going to use &lt;code&gt;nextjs&lt;/code&gt; and &lt;code&gt;ImageResponse&lt;/code&gt; from &lt;code&gt;next/og&lt;/code&gt; to create our simple images.&lt;/p&gt;

&lt;p&gt;To create a new &lt;code&gt;nextjs&lt;/code&gt; app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i create-next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this simple-og project we're going to use &lt;code&gt;App Router&lt;/code&gt;.  You can also find the github repo at the bottom of the blog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔ What is your project named? … simple-og
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
Creating a new Next.js app in /Users/shrihari/testRepos/simple-og.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @vercel/og
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside your app folder create 2 files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd simple-og/src/app 
touch Simple.tsx
touch img/route.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;Simple.tsx&lt;/code&gt; file. You have to be picky with the css as the &lt;a href="https://nextjs.org/docs/app/api-reference/functions/image-response"&gt;ImageResponse&lt;/a&gt; supports only certain types of styles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TSimpleTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;website&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SimpleTemplate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TSimpleTemplate&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#f8fafc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#334155&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
        &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;column&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`#334155 2px solid`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#334155&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;hr&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`#334155 1px solid`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/hr&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;52&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fontWeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;700&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#334155&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;img/route.tsx&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SimpleTemplate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../Simple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ImageResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/og&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Route segment config&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;edge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Image generation&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No website&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ImageResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SimpleTemplate&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;630&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;public, max-age=3600, immutable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On your browser open &lt;a href="http://localhost:3000/simple/img?title=Every%20moment%20is%20a%20fresh%20beginning.&amp;amp;website=blogs.gratitude.com"&gt;http://localhost:3000/simple/img?title=Every%20moment%20is%20a%20fresh%20beginning.&amp;amp;website=blogs.gratitude.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just change the queries param values to generate a dynamic image based on the queries. &lt;/p&gt;

&lt;p&gt;Deploy on your preferred servers. You can use vercel for free if you are using only couple thousands requests per month!&lt;/p&gt;

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

&lt;p&gt;Source code on github &lt;a href="https://github.com/ShrihariMohan/simple-og-image"&gt;simple-og-image&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is completely free to use all our default templates and a self-hosted paid version is also available.  This tutorial serves as a base for &lt;a href="https://www.dynamicog.com/"&gt;Dynamic OG&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Self Hosted Dynamic OG Includes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get lifetime access for just $10 per template. Customize them to match your style. Own your templates for ever.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave server setup to us. Deploy on your preferred platform: Cloudflare Workers, Netlify Functions, Vercel, or even machines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You own the source code of your templates. This means your designs are yours, not ours. We simply provide the tools.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn more about &lt;a href="https://www.dynamicog.com/"&gt;Dynamic OG&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to test open graph meta tags locally ?</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 18 Feb 2024 13:16:43 +0000</pubDate>
      <link>https://forem.com/shrihari/how-to-test-open-graph-meta-tags-locally--4981</link>
      <guid>https://forem.com/shrihari/how-to-test-open-graph-meta-tags-locally--4981</guid>
      <description>&lt;p&gt;I have created a chrome extension that lets you preview your meta tags. &lt;a href="https://chromewebstore.google.com/detail/localhost-open-graph-test/nggoiohoonibebildpjhlaakfoccpfln" rel="noopener noreferrer"&gt;Localhost Open Graph Tester&lt;/a&gt; hosts your meta tags on a seperate website and gives you the link to preview test.&lt;/p&gt;

&lt;p&gt;Just click the extension icon on the development site , it will open a new tab with the link for you to share.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Local images won't share directly, upload the images in &lt;a href="https://postimages.org/" rel="noopener noreferrer"&gt;postimages&lt;/a&gt; or &lt;a href="https://imgbb.com/" rel="noopener noreferrer"&gt;imgbb&lt;/a&gt; first, use the url in the meta tags. Then click the extension again to create a new sharer link!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How this extension works ?
&lt;/h3&gt;

&lt;p&gt;When you click the extension we copy the meta tags of the active tab and host it in different domain, where it will be available for the internet.&lt;/p&gt;

&lt;p&gt;It also helps you debug your tags easily. I have attached a sample &lt;code&gt;dev.to&lt;/code&gt; where you can see the hosted tags in a table. Peep at the &lt;a href="https://github.com/ShrihariMohan/og-tester" rel="noopener noreferrer"&gt;Source code&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This extension saves the hassle of ngrok tunnels or public URLs. Simply click the extension icon to instantly test your OG tags on localhost. If this extension helps you &lt;a href="https://chromewebstore.google.com/detail/nggoiohoonibebildpjhlaakfoccpfln" rel="noopener noreferrer"&gt;Rate us&lt;/a&gt; &lt;/p&gt;




&lt;h2&gt;
  
  
  Important Links
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/ShrihariMohan/og-tester" rel="noopener noreferrer"&gt;Source code&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://chromewebstore.google.com/detail/nggoiohoonibebildpjhlaakfoccpfln" rel="noopener noreferrer"&gt;Chrome Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://localhost-og-checker.vercel.app/" rel="noopener noreferrer"&gt;Localhost open graph tester - Home&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

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

</description>
      <category>webdev</category>
      <category>seo</category>
    </item>
    <item>
      <title>Cloudflare Pages NextJs + D1 Database ᐧ My experience developing sharejson</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sat, 03 Feb 2024 16:22:22 +0000</pubDate>
      <link>https://forem.com/shrihari/cloudflare-pages-nextjs-d1-database-w-my-experience-developing-sharejson-ma3</link>
      <guid>https://forem.com/shrihari/cloudflare-pages-nextjs-d1-database-w-my-experience-developing-sharejson-ma3</guid>
      <description>&lt;p&gt;The biggest challenge I encountered during Next.js development was the lack of hot reloading when using a D1 database locally. We have to use &lt;code&gt;experimental-edge&lt;/code&gt; when using &lt;code&gt;getServerSideProps&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Development is time consuming! &lt;code&gt;npm run dev&lt;/code&gt; will not give D1 database bindings&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have to rebuild the entire project every time I make a change, even a minor one. This can be very time-consuming.&lt;/p&gt;

&lt;p&gt;I managed to complete &lt;a href="https://sharejson.com"&gt;sharejson.com&lt;/a&gt; because it's a single-page application with only one table. However, for larger projects with more tables, I wouldn't recommend using D1 due to the significant development time required. It simply doesn't feel efficient in these scenarios.&lt;/p&gt;

&lt;p&gt;Test your Next.js application with hot reload while mocking database responses and test the database logic later to make development easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Nextjs Pages &amp;amp; D1 Database
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create cloudflare@latest my-next-app &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--framework&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates a new Next.js project with pages setup. Once we have the wrangler cli , we can directly deploy app.&lt;/p&gt;

&lt;p&gt;We have to change the &lt;code&gt;env.d.ts&lt;/code&gt; for bindings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;NodeJS&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProcessEnv&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;DATABASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;D1Database&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After signing up with Cloudflare, you can create a database on their platform and access environment variables. Add &lt;code&gt;wrangler.toml&lt;/code&gt; file with D1 details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[d1_databases]]
binding = "DATABASE"
database_name = "db"
database_id = "database-id-from-website"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've isolated database operations in the &lt;code&gt;src/server&lt;/code&gt; folder. However, the &lt;code&gt;db&lt;/code&gt; variable remains &lt;code&gt;undefined&lt;/code&gt; during &lt;code&gt;npm run dev&lt;/code&gt; as hot reloading isn't supported. For database access, use &lt;code&gt;npm run pages:dev&lt;/code&gt;, but be aware that this disables hot reloading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectFromJsons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`select * from jsons where id = ?1`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overall, using D1 and Pages has been a positive experience, as it currently runs everything for free.&lt;/p&gt;




</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>development</category>
    </item>
    <item>
      <title>Funny Developing Mistakes I Wasted Hours on</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 27 Aug 2023 16:12:18 +0000</pubDate>
      <link>https://forem.com/shrihari/funny-developing-mistakes-i-wasted-hours-on-1hji</link>
      <guid>https://forem.com/shrihari/funny-developing-mistakes-i-wasted-hours-on-1hji</guid>
      <description>&lt;h2&gt;
  
  
  Using Routing Module Instead Of Module
&lt;/h2&gt;

&lt;p&gt;Because there were no erros in the console and whatever in the component file doesn't render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;loadChildren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./comps/CompsRoutingModule.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CompsRoutingModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// That should have been just module.&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Same Variable Names Different Files
&lt;/h2&gt;

&lt;p&gt;Sometimes we may introduce the same function or variable name in a different context. This can cause &lt;strong&gt;VS Code to mess up the imports&lt;/strong&gt; we were looking for, especially if we didn't know that the name had already been used.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;yarn dev&lt;/code&gt; vs &lt;code&gt;yarn start&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;yarn start&lt;/code&gt; doesn't refresh changes on file save. I sometimes accidently select &lt;code&gt;start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n4ZuEiAl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97w3ol8sr7i57gxhq8k8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n4ZuEiAl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97w3ol8sr7i57gxhq8k8.png" alt="node" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Wrong Environments in Postman
&lt;/h2&gt;

&lt;p&gt;I just hit some &lt;code&gt;post&lt;/code&gt; request to production without realizing for 10 mins.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3FuFGWNl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asxtpnalukjgqdvirpjt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3FuFGWNl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asxtpnalukjgqdvirpjt.png" alt="Postman" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Try Our new product for free!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docsai.app/"&gt;DocsAI&lt;/a&gt; - Create AI support agents with your documents in the most affordable price, starts at &lt;strong&gt;0$&lt;/strong&gt;. Don't need a bot , but need ai help on your docs just upload and start chating !&lt;/p&gt;

&lt;p&gt;Using for a company ? &lt;a href="https://docsai.app/pricing"&gt;Check out our pricing&lt;/a&gt; Just contact me for personalized pricing !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i2yl_xPB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://firebasestorage.googleapis.com/v0/b/shrihari-personal-storage.appspot.com/o/banner-docs-jpeg.jpeg%3Falt%3Dmedia%26token%3D45c47666-de2a-4e02-8881-beb6e43ce581" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i2yl_xPB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://firebasestorage.googleapis.com/v0/b/shrihari-personal-storage.appspot.com/o/banner-docs-jpeg.jpeg%3Falt%3Dmedia%26token%3D45c47666-de2a-4e02-8881-beb6e43ce581" alt="docsAi" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
    </item>
    <item>
      <title>MongoDB Basic design patterns and 6 rules of thumb - in 3 mins</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Wed, 16 Aug 2023 09:56:10 +0000</pubDate>
      <link>https://forem.com/shrihari/mongodb-design-patterns-and-6-rules-of-thumb-in-3-mins-3b8c</link>
      <guid>https://forem.com/shrihari/mongodb-design-patterns-and-6-rules-of-thumb-in-3-mins-3b8c</guid>
      <description>&lt;p&gt;Thanks to &lt;a href="https://www.mongodb.com/blog/authors/william-zola"&gt;William Zola&lt;/a&gt; for making this possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design"&gt;This article&lt;/a&gt; is a bit more in-depth than mine, if you have the time. I took bits and peices from that. &lt;/p&gt;

&lt;h2&gt;
  
  
  One to Few  (&amp;lt; couple 100s) - Embedding
&lt;/h2&gt;

&lt;p&gt;Storing &lt;code&gt;Devices&lt;/code&gt; against a &lt;code&gt;Person&lt;/code&gt;. You can save all those devices inside an array. Since a &lt;code&gt;person&lt;/code&gt; can own only few number of devices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   _id : ObjectID('1234'),
  name: 'MKBHD',
  devices : [
     { name: 'Samsung', model: 'S23 Ultra' },
     { name: 'Apple', model: '14 Pro Max' }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;No need second query since all of them are in one place.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Cannot treat &lt;code&gt;devices&lt;/code&gt; as stand alone entities. Like grouping devices based on &lt;code&gt;name&lt;/code&gt; will be tough to execute.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One to many (&amp;lt; couple 1000s) - Referencing
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;Book&lt;/code&gt; and its &lt;code&gt;Pages&lt;/code&gt;. There can several hundred pages but never more than couple 1000s.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Book
{
  _id : ObjectID('1111'),
  title : 'The Lord of the Rings' , 
  author : 'J.R.R. Tolkien' ,
  pages : [
  ObjectID('2222'),
  ObjectID('3333'),
  ObjectID('4444')
  ]  
}

// Fetch the Book document by id
&amp;gt; book = db.Book.findOne({id: 1111});
// Fetch all the pages that are linked to this Book
&amp;gt; bookPages = db.Pages.find({_id: { $in : book.pages } } );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Each pages can be queried  efficiently.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Need a application level second query to get both book and pages, which with a right index doesn't look different than sql level join.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One to squillions - (indefinitely large)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Likes&lt;/code&gt; and comments of a &lt;code&gt;Post&lt;/code&gt; can be arbitrarily large. You save the unique id of &lt;code&gt;Post&lt;/code&gt; in the &lt;code&gt;Likes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Post 
{
  _id : ObjectID('1111') ,
  content : "This is a good day!",
  creatorId : "1234",
  createAt: 2023-08-19T17:07:24.426Z
}

Likes 
{
   name : "Elon",
   postId :  ObjectID('1111'), // Reference to the Post document
   createdAt: 2023-08-19T17:06:24.426Z
}
{
   name : "Musk",
   postId :  ObjectID('1111') // Reference to the Post document
   createdAt: 2023-08-19T17:07:24.426Z
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also needs a appication level join and we can use mongodb operators to get count , recent 500 comments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; post = db.Post.findOne({id: ObjectID('1111') });  //index
&amp;gt; last500Likes = db.Likes.find({postId: post._id})
.sort({createdAt : -1}).limit(500) // postId is indexed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Two way referencing
&lt;/h2&gt;

&lt;p&gt;A user and their posts. This way we can get user and all his posts. In some other scenario , we can get a list of posts recently posted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 
{
  _id : ObjectID('1111'),
  posts : [                 // Reference to Post
    ObjectID('2222'),
    ObjectID('3333'),
    ObjectID('4444')
  ]
}

Post 
{
  _id : ObjectID('2222') ,
  content : "This is a good day!"
  userId : ObjectID('1111') // Reference to User
}

{
  _id : ObjectID('3333') ,
  content : "This is a great day!"
  userId : ObjectID('1111') // Reference to User
}

{
  _id : ObjectID('4444') ,
  content : "This is a day!"
  userId : ObjectID('1111') // Reference to User
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Denormailization
&lt;/h2&gt;

&lt;p&gt;This is used to prevent application level joins to to read frequently at the expense of costlier update query. We will use the same example of &lt;code&gt;Books&lt;/code&gt; and &lt;code&gt;Pages&lt;/code&gt;  with denormalizations.&lt;/p&gt;

&lt;p&gt;In the each pages with its id attached with a &lt;code&gt;context&lt;/code&gt;. This way when getting a &lt;code&gt;Book&lt;/code&gt; we can get a context of what each &lt;code&gt;Page&lt;/code&gt; looks like without application Join. However if you need more information about the page thats a seperate query.&lt;/p&gt;

&lt;p&gt;This comes with a expense of update becuase whenever context changes we have to update &lt;code&gt;Page&lt;/code&gt; and &lt;code&gt;Book&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Book
{
  _id : ObjectID('1111'),
  title : 'The Lord of the Rings' , 
  author : 'J.R.R. Tolkien' ,
  pages : [
   { id :ObjectID('2222'), 
     context: "In a hole in the ground there lived a hobbit." 
   },
   { id: ObjectID('3333'), 
     context: "It had a perfectly round door like a porthole" 
   },
   { id: ObjectID('3333'), 
     context: "There were doors on either side"
   }
  ]  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6 Rules of thumb
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One&lt;/strong&gt;: Favor embedding unless there is a compelling reason not to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two&lt;/strong&gt;: Needing to access an object on its own is a compelling reason not to embed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three&lt;/strong&gt;: If an array is likely to grow large, it is better to store it as a separate document or collection. This will improve performance and scalability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Four&lt;/strong&gt;: Don’t be afraid of application-level joins: If you index correctly and use the projection specifier, then application-level joins are barely more expensive than server-side joins in a relational database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Five&lt;/strong&gt;: Consider the read-to-write ratio with denormalization. A field that will mostly be read and only seldom updated is a good candidate for denormalization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Six&lt;/strong&gt;: How you model your data depends entirely on your particular application’s data access patterns.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>How Do GPT-3.5, Bing, and Bard Explain Promises to a 5-Year-Old?</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 30 Jul 2023 12:43:34 +0000</pubDate>
      <link>https://forem.com/shrihari/how-do-gpt-35-bing-and-bard-explain-promises-to-a-5-year-old-38kn</link>
      <guid>https://forem.com/shrihari/how-do-gpt-35-bing-and-bard-explain-promises-to-a-5-year-old-38kn</guid>
      <description>&lt;p&gt;AI Chatbots Are Making Learning to Program Easier&lt;/p&gt;

&lt;p&gt;As a developer, I've always found that the best way to learn something new is by asking questions. But sometimes, it can be hard to find someone who can explain complex concepts in a way that's easy to understand.&lt;/p&gt;

&lt;p&gt;That's where AI chatbots come in. In this blog post, I'll share my hot take on the 3 leading AI chatbots for learning to program.&lt;/p&gt;

&lt;p&gt;So without further ado, let's get started!&lt;/p&gt;

&lt;p&gt;Prompt - "Explain javascript promises like I am 5"&lt;/p&gt;

&lt;h3&gt;
  
  
  ChatGPT - 3.5
&lt;/h3&gt;

&lt;p&gt;Alright, imagine you're playing a game with your friend, and you want to get a cool toy from a vending machine. But the vending machine takes a little time to give you the toy, and you don't want to wait there doing nothing.&lt;/p&gt;

&lt;p&gt;So, you give your friend a special promise note that says, "Hey, I'll give you a toy when I get it from the machine." Your friend can continue playing other games or doing other stuff instead of just waiting.&lt;/p&gt;

&lt;p&gt;Now, when the vending machine finally gives you the toy, you keep your promise and give the toy to your friend. Your friend is happy because they got the toy they were promised, and you're happy because you made your friend happy!&lt;/p&gt;

&lt;p&gt;In JavaScript, sometimes we have to do things that take some time, like fetching data from the internet or loading images. We use promises just like the promise note you gave your friend. The promise says, "Hey, I'll let you know when I'm done getting the data or image."&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://chat.openai.com/share/96c29e35-09e5-4b02-ab68-61a75f515af6" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--rFvR3gHA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://chat.openai.com/images/chatgpt-share-og.png" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://chat.openai.com/share/96c29e35-09e5-4b02-ab68-61a75f515af6" rel="noopener noreferrer" class="c-link"&gt;
          JS Promises Explained!
        &lt;/a&gt;
      &lt;/h2&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--zb1NT0RH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://chat.openai.com/favicon-32x32.png" width="32" height="32"&gt;
        chat.openai.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h3&gt;
  
  
  Bard
&lt;/h3&gt;

&lt;p&gt;Imagine you're at a restaurant and you want to order a hamburger. You tell the waiter what you want, and they give you a buzzer. The buzzer will buzz when your hamburger is ready.&lt;/p&gt;

&lt;p&gt;The buzzer is a promise. It's a way of saying, "I'll let you know when your hamburger is ready."&lt;/p&gt;

&lt;p&gt;In JavaScript, promises are objects that represent the eventual completion or failure of an asynchronous operation. An asynchronous operation is something that takes time to finish, like loading a web page or making a network request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a promise.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Do something that takes time.&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Resolve the promise with a value.&lt;/span&gt;
    &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your hamburger is ready!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Attach a handler to the promise.&lt;/span&gt;
&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Do something with the value.&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Bing Chat
&lt;/h3&gt;

&lt;p&gt;Imagine you want to climb a tree in the park, but you have to ask your mom for permission first. You don't know if she will say yes or no, so you have to wait for her answer. A promise is like a way of telling your mom: "Please let me know if I can climb the tree or not, and I will do something else depending on your answer." &lt;/p&gt;

&lt;p&gt;For example, you can say: "If you say yes, I will be very happy and go to the park with my friends. If you say no, I will be sad and stay at home and play with my toys." These are the two possible outcomes of your promise: either it is fulfilled (your mom says yes) or it is rejected (your mom says no).&lt;/p&gt;

&lt;p&gt;A promise in JavaScript is similar. It is an object that represents a task that may or may not be completed in the future. It has two functions that are called when the task is either successful or unsuccessful. These functions are called resolve and reject. &lt;/p&gt;

&lt;p&gt;For example, you can write a promise like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;climbTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ask mom for permission&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;permission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;askMom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// if permission is granted, resolve the promise&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;permission&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yay! I can climb the tree!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// if permission is denied, reject the promise&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Oh no! I can't climb the tree!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you can use the promise like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;climbTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this function is called when the promise is resolved&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Yay! I can climb the tree!"&lt;/span&gt;
  &lt;span class="c1"&gt;// do something else when you are happy&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this function is called when the promise is rejected&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Oh no! I can't climb the tree!"&lt;/span&gt;
  &lt;span class="c1"&gt;// do something else when you are sad&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you don't have to wait for your mom's answer before doing something else. You can just tell her what you want to do depending on her answer, and then move on with your life. That's how promises work in JavaScript. They make your code easier to read and manage.&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bot/Quality&lt;/th&gt;
&lt;th&gt;Chat GPT-3.5&lt;/th&gt;
&lt;th&gt;Bard&lt;/th&gt;
&lt;th&gt;Bing Chat&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Explanation&lt;/td&gt;
&lt;td&gt;OK&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Good ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gave code.&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes  ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Relevance&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Somewhat Yes&lt;/td&gt;
&lt;td&gt;Yes ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I overall enjoyed the Bing's answer.&lt;/p&gt;

&lt;p&gt;Peace 🕊&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>creativity</category>
    </item>
    <item>
      <title>The Strong World of Developers: Trying, Catching, and Moving On</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Thu, 06 Jul 2023 06:44:33 +0000</pubDate>
      <link>https://forem.com/shrihari/the-strong-world-of-developers-trying-catching-and-moving-on-4po9</link>
      <guid>https://forem.com/shrihari/the-strong-world-of-developers-trying-catching-and-moving-on-4po9</guid>
      <description>&lt;p&gt;Rejection is a part of life, and for developers, it's no exception. However, these strong individuals have their own unique way of coping with rejection. &lt;/p&gt;

&lt;p&gt;In this article, we delve into the world of developers and explore how they handle setbacks by employing their programming skills. So, fasten your seatbelts and prepare to discover how they try, catch their feelings, and move on!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---8-1XHNM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njzejvscleeug3t1cwfr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---8-1XHNM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njzejvscleeug3t1cwfr.jpeg" alt="Thinking with Try and Catch Curly Braces" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Try/Catch Mindset
&lt;/h2&gt;

&lt;p&gt;Developers are well-versed in the concept of error handling through try/catch blocks. In the realm of programming, errors are expected, and handling them gracefully is crucial.&lt;/p&gt;

&lt;p&gt;Similarly, when faced with rejection, developers adopt a similar mindset. They embrace the challenge, acknowledging that not every attempt will yield success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying with Determination:
&lt;/h2&gt;

&lt;p&gt;Developers possess a tenacious spirit. They understand that perseverance and continuous effort are essential for growth and success. &lt;/p&gt;

&lt;p&gt;When faced with rejection, they approach it as an opportunity to learn and improve. They don't let errors define them but instead use them as stepping stones for future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Catching Their Feelings:
&lt;/h2&gt;

&lt;p&gt;Just as a try/catch block catches errors, Developers employ a similar mechanism to catch their feelings. They understand that rejection can evoke a range of emotions, from disappointment to self-doubt. &lt;/p&gt;

&lt;p&gt;Instead of dwelling on these negative emotions, they acknowledge them, process them, and then move forward. By catching their feelings, they maintain a healthy emotional state while avoiding being consumed by negativity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging and Self-Reflection:
&lt;/h2&gt;

&lt;p&gt;Developers are skilled in debugging code to identify and resolve issues. Likewise, They analyze their actions, seek feedback, and identify areas for improvement. By debugging their approach, they can make adjustments and increase their chances of success in future endeavors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving On:
&lt;/h2&gt;

&lt;p&gt;One of the core principles of development is efficiency. Developers optimize code, seeking ways to make it faster and more efficient. &lt;/p&gt;

&lt;p&gt;Similarly, when confronted with rejection, developers don't linger on what didn't work out. They swiftly adapt, make necessary adjustments, and move on to new opportunities. &lt;/p&gt;

&lt;p&gt;They understand that dwelling on past failures hinders progress and prevents them from seizing new possibilities.&lt;/p&gt;

&lt;p&gt;Please Add &lt;code&gt;finally&lt;/code&gt; in the comments. How you like to &lt;code&gt;try / catch&lt;/code&gt; end with &lt;code&gt;finally&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🕊 peace&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;If you are here it means you may have found this blog helpful. Just follow me &lt;a class="mentioned-user" href="https://dev.to/shrihari"&gt;@shrihari&lt;/a&gt; which will motivate to write more. You can make a &lt;a href="https://www.buymeacoffee.com/shriharimohan"&gt;Buttermilk 🥛&lt;/a&gt;. Small support comes a long way!&lt;/p&gt;

&lt;p&gt;Subscribe If you want to receive these blogs in your mail from @&lt;a href="https://medium.com/@shriharimohan"&gt;Medium&lt;/a&gt; for free!&lt;/p&gt;

&lt;h2&gt;
  
  
  More things from me
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyaTN21p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--IYwCeY9Q--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/693354/d92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/efficiently-manage-repeated-requests-in-angular-with-interceptors-4amn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Cancel repeated requests in Angular with interceptors&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Apr 16&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyaTN21p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--IYwCeY9Q--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/693354/d92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/how-i-built-a-chrome-extension-that-finds-ghost-css-ghost-css-detector-4aj0" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I Built a chrome extension that finds Ghost CSS : Ghost-CSS-Detector&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Jan 11&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyaTN21p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--IYwCeY9Q--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/693354/d92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/beyond-coding-the-devops-tasks-i-do-as-a-web-dev-311f" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Beyond Coding : The DevOps Tasks I do as a web dev.&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Mar 26&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>story</category>
      <category>funny</category>
      <category>philosophy</category>
      <category>humour</category>
    </item>
    <item>
      <title>Cancel repeated requests in Angular with interceptors</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 16 Apr 2023 17:33:04 +0000</pubDate>
      <link>https://forem.com/shrihari/efficiently-manage-repeated-requests-in-angular-with-interceptors-4amn</link>
      <guid>https://forem.com/shrihari/efficiently-manage-repeated-requests-in-angular-with-interceptors-4amn</guid>
      <description>&lt;p&gt;By using interceptors, you can &lt;strong&gt;intercept&lt;/strong&gt; and &lt;strong&gt;modify&lt;/strong&gt; &lt;code&gt;HTTP&lt;/code&gt; requests and responses globally across your entire application.&lt;/p&gt;

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

&lt;p&gt;In this we're going to create a &lt;code&gt;component&lt;/code&gt; ,  &lt;code&gt;service&lt;/code&gt; and &lt;code&gt;interceptor&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;In &lt;code&gt;src/app/cancel-repeated-apis/cancel-repeated-apis.html&lt;/code&gt; &lt;/p&gt;

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

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-screen gap-4 flex items-center justify-center bg-black"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-3 bg-cyan-400  rounded-lg"&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"handleClick(1)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    API 1
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"p-3 bg-red-400 rounded-lg"&lt;/span&gt; &lt;span class="na"&gt;(click)=&lt;/span&gt;&lt;span class="s"&gt;"handleClick(2)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    API 2
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;we're using &lt;code&gt;tailwind&lt;/code&gt; along with it. Nothing serious , just 2 buttons with different colors.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/app/cancel-repeated-apis/cancel-repeated-apis.ts&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApiService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/api.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-cancel-repeated-apis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cancel-repeated-apis.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./cancel-repeated-apis.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CancelRepeatedApisComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Takes an number and calls a sample api using that&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://dummyjson.com/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🔥 ~ handleClick ~ res:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🔥 ~ handleClick ~ err:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



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

&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;/src/app/services/api.service.ts&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApiService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// get request using http , Make sure to import in modules&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;/src/app/interceptors/cancel-same-apis.interceptor.ts&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;takeUntil&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CancelSameApisInterceptor&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Only cancel GET requests&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// if you want to check params as well then use request.urlWithParams.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// check if the request is already cached&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cachedResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// cancel any previous requests&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cachedResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cachedResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cancelRequests$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// cache the new request , so that we can cancel it if needed.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cancelRequests$&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

      &lt;span class="c1"&gt;// cancel the request if a same request comes in.&lt;/span&gt;
      &lt;span class="nf"&gt;takeUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cancelRequests$&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

      &lt;span class="c1"&gt;// complete the subject when the request completes.&lt;/span&gt;
      &lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Don't forget to add this interceptor in the provider in &lt;code&gt;app.module.ts&lt;/code&gt; or your respective modules.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

  &lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTTP_INTERCEPTORS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;useClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CancelSameApisInterceptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;multi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;We have a map that holds &lt;code&gt;url&lt;/code&gt; as &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;cancelRequest$&lt;/code&gt; as &lt;code&gt;value&lt;/code&gt;. &lt;br&gt;
We always check the &lt;code&gt;cache&lt;/code&gt; before request. If &lt;code&gt;cache&lt;/code&gt; exists we cancel previous requests using the &lt;code&gt;value&lt;/code&gt; which is &lt;code&gt;observable&lt;/code&gt; that is passed in the &lt;code&gt;takeUntil&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;takeUntil&lt;/code&gt; - &lt;code&gt;takeUntil&lt;/code&gt;subscribes and begins mirroring the source &lt;code&gt;Observable&lt;/code&gt;. It also monitors a second Observable, &lt;code&gt;notifier&lt;/code&gt; that you provide. If the notifier emits a value, the output &lt;code&gt;Observable&lt;/code&gt; stops mirroring the source Observable and completes. If the &lt;code&gt;notifier&lt;/code&gt; doesn't emit any value and completes then &lt;code&gt;takeUntil&lt;/code&gt; will pass all values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🕊 peace&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;If you are here it means you may have found this blog helpful. Just follow me &lt;a class="mentioned-user" href="https://dev.to/shrihari"&gt;@shrihari&lt;/a&gt; which will motivate to write more. You can make a &lt;a href="https://www.buymeacoffee.com/shriharimohan" rel="noopener noreferrer"&gt;Buttermilk 🥛&lt;/a&gt;. Small support comes a long way!&lt;/p&gt;

&lt;p&gt;Subscribe If you want to receive these blogs in your mail from @&lt;a href="https://medium.com/@shriharimohan" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; for free!&lt;/p&gt;
&lt;h2&gt;
  
  
  More things from me
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/redis-bull-easy-background-jobs-in-nodejs-50le" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Redis + 🐂 Bull = Easy Background Jobs in nodeJs&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Apr 15 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;




&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/how-i-built-a-chrome-extension-that-finds-ghost-css-ghost-css-detector-4aj0" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I Built a chrome extension that finds Ghost CSS : Ghost-CSS-Detector&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Jan 11 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/nodejs-cron-handling-overlapping-tasks-like-a-noob-c32" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Node.js Cron: Handling Overlapping Tasks Like a Noob&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Apr 6 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>angular</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Redis + 🐂 Bull = Easy Background Jobs in nodeJs</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sat, 15 Apr 2023 10:49:15 +0000</pubDate>
      <link>https://forem.com/shrihari/redis-bull-easy-background-jobs-in-nodejs-50le</link>
      <guid>https://forem.com/shrihari/redis-bull-easy-background-jobs-in-nodejs-50le</guid>
      <description>&lt;p&gt;Real world use cases why you should use redis in your apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job processing&lt;/strong&gt;: You could use Redis and Bull to process image uploads, generate PDFs, send emails in background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task scheduling&lt;/strong&gt;: Just like crons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;: cache slow running queries and also api responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-time updates&lt;/strong&gt;: Redis can be used to publish and subscribe to messages, making it a great tool for implementing real-time updates in Node.js applications. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate limiting&lt;/strong&gt;: You could use Redis to limit the number of API requests a user can make in a given time period.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up redis
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;For windows&lt;/strong&gt;&lt;br&gt;
you can directly &lt;a href="https://drive.google.com/drive/folders/1vk-zr_w9hb2IpOsRNtm8xwnIP4GFaz8B?usp=share_link" rel="noopener noreferrer"&gt;Download&lt;/a&gt; this and run the &lt;code&gt;redis-server&lt;/code&gt; inside &lt;code&gt;bin&lt;/code&gt; folder or use of &lt;code&gt;wsl2&lt;/code&gt; the &lt;a href="https://redis.io/docs/getting-started/installation/install-redis-on-windows/" rel="noopener noreferrer"&gt;Official way&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Linux&lt;/strong&gt;&lt;br&gt;
If your linux supports &lt;code&gt;snap&lt;/code&gt; then its simple Or follow these simple steps from &lt;a href="https://redis.io/docs/getting-started/installation/install-redis-on-linux/" rel="noopener noreferrer"&gt;Offical Docs&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;For mac&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;redis
redis-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want to know &lt;a href="https://redis.io/docs/getting-started/installation/install-redis-on-mac-os/" rel="noopener noreferrer"&gt;more&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default the redis will start in &lt;code&gt;redis://localhost:6379&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up NodeJs
&lt;/h2&gt;

&lt;p&gt;Hope you have a sample nodeJs template&lt;br&gt;
Add &lt;code&gt;bull&lt;/code&gt; to the dependenceis.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;bull
yarn add bull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create Jobs.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test-queue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;redis://localhost:6379&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Add jobs to the queue&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;myQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Example app listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// process jobs from the queue &lt;/span&gt;
&lt;span class="nx"&gt;myQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing job &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with data `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;Thats it you are done. All you have to do is hit the apis to schedule a job and &lt;code&gt;myQueue&lt;/code&gt; will keep on logging.&lt;/p&gt;

&lt;p&gt;Make sure your redis is up and running , redis url is connect.&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Peace 🕊&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;If you are here it means you may have found this blog helpful. Just follow me &lt;a class="mentioned-user" href="https://dev.to/shrihari"&gt;@shrihari&lt;/a&gt; which will motivate to write more. You can make a &lt;a href="https://www.buymeacoffee.com/shriharimohan" rel="noopener noreferrer"&gt;Buttermilk 🥛&lt;/a&gt;. Small support comes a long way!&lt;/p&gt;

&lt;p&gt;Subscribe If you want to receive these blogs in your mail from @&lt;a href="https://medium.com/@shriharimohan" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; for free!&lt;/p&gt;
&lt;h2&gt;
  
  
  More things from me
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/how-i-built-a-chrome-extension-that-finds-ghost-css-ghost-css-detector-4aj0" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I Built a chrome extension that finds Ghost CSS : Ghost-CSS-Detector&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Jan 11 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;




&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/two-things-that-make-my-terminal-experience-awesome-in-mac-3eie" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Two things that make my Terminal experience awesome 🚀 in Mac/Linux&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Sep 18 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#linux&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F693354%2Fd92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/angular-ng-templates-crafting-reusable-templates-with-ease-2dap" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🚀 Angular ng-templates: Crafting Reusable templates with Ease&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Feb 14 '23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Node.js Cron: Handling Overlapping Tasks Like a Noob</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Thu, 06 Apr 2023 18:08:01 +0000</pubDate>
      <link>https://forem.com/shrihari/nodejs-cron-handling-overlapping-tasks-like-a-noob-c32</link>
      <guid>https://forem.com/shrihari/nodejs-cron-handling-overlapping-tasks-like-a-noob-c32</guid>
      <description>&lt;p&gt;One common cron problem is when a &lt;strong&gt;cron job takes longer to complete&lt;/strong&gt; than the &lt;strong&gt;interval between two consecutive runs&lt;/strong&gt;. In this case, the second instance of the job will start before the first one has finished, leading to overlaps and potentially unexpected behavior such as duplicates.&lt;/p&gt;




&lt;p&gt;The script consists of a job that is run every 5 seconds using the &lt;code&gt;CronJob&lt;/code&gt; library, and a &lt;code&gt;delay&lt;/code&gt; function that simulates a long running task. &lt;/p&gt;

&lt;p&gt;The script uses a simple flag &lt;code&gt;isJobRunning&lt;/code&gt; to prevent overlapping runs of the job, and a &lt;code&gt;jobSkippedCount&lt;/code&gt; variable to keep track of how many times the job has been skipped due to overlapping.&lt;/p&gt;

&lt;p&gt;We're going to use &lt;code&gt;nanoid&lt;/code&gt; to know job ids and &lt;code&gt;cron&lt;/code&gt; to schedule jobs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;nanoid
npm &lt;span class="nb"&gt;install &lt;/span&gt;cron
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's dive into the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CronJob&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cron&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nanoid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nanoid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isJobRunning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;jobSkippedCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CronJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*/5 * * * * *&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isJobRunning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;jobSkippedCount&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__ JOB SKIPPED COUNT __ &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jobSkippedCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobSkippedCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="cm"&gt;/* If a job takes more than 15 seconds 
         to complete we can stop this job, 
         throw a error and start a new job */&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__ TIMEOUT __&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;jobSkippedCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
      &lt;span class="nx"&gt;isJobRunning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;isJobRunning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;nanoid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;__ JOB RUNNING __ &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

      &lt;span class="cm"&gt;/* Your  functionality goes here 
    I have used a delay function to 
    simulate a long running job */&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;isJobRunning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="nx"&gt;jobSkippedCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;__ JOB COMPLETED __ &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are 3 scenarios that happen with this our cycle is 5 seconds once and max skip count is 2&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Everything is smooth
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;delay(2000)&lt;/code&gt;  - The cron job executes and finishes its task &lt;strong&gt;before the next cycle&lt;/strong&gt;, producing the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;__ JOB RUNNING   __  EC6MqpB4FG 2023-04-06T17:53:35.004Z
__ JOB COMPLETED __  EC6MqpB4FG 2023-04-06T17:53:37.017Z
__ JOB RUNNING   __  6nutPdea6_ 2023-04-06T17:53:40.004Z
__ JOB COMPLETED __  6nutPdea6_ 2023-04-06T17:53:42.005Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Skipped a job but no TIMEOUT
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;delay(7000)&lt;/code&gt; - The cron job executes and finishes its task by &lt;strong&gt;skipping one cycle&lt;/strong&gt;, producing the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;__ JOB RUNNING   __  soR8V3YrQp 2023-04-06T17:54:15.006Z
__ JOB SKIPPED COUNT __  1
__ JOB COMPLETED __  soR8V3YrQp 2023-04-06T17:54:22.019Z
__ JOB RUNNING   __  8-LBtb85Jq 2023-04-06T17:54:25.002Z
__ JOB SKIPPED COUNT __  1
__ JOB COMPLETED __  8-LBtb85Jq 2023-04-06T17:54:32.004Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Reaches Timeout
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;delay(17000)&lt;/code&gt; - The cron job fails to complete within timeout so a new job starts: Regardless whether the previous job completed or not. We will start the job after timeout. &lt;/p&gt;

&lt;p&gt;You may need to kill your logic using event emitters in order to stop the function execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;__ JOB RUNNING   __  lrMOLDgtzm 2023-04-06T18:00:05.004Z
__ JOB SKIPPED COUNT __  1
__ JOB SKIPPED COUNT __  2
__ JOB SKIPPED COUNT __  3
__ TIMEOUT __
__ JOB COMPLETED __  lrMOLDgtzm 2023-04-06T18:00:22.015Z
__ JOB RUNNING   __  qPK1lQ8QuV 2023-04-06T18:00:25.003Z
__ JOB SKIPPED COUNT __  1
__ JOB SKIPPED COUNT __  2
__ JOB SKIPPED COUNT __  3
__ TIMEOUT __
__ JOB COMPLETED __  qPK1lQ8QuV 2023-04-06T18:00:42.003Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;isJobRunning&lt;/code&gt;&lt;/strong&gt; -  is a flag that indicates whether the job is currently running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;jobSkippedCount&lt;/code&gt;&lt;/strong&gt; is a counter that keeps track of how many times the job has been skipped due to overlaps. This also helps &lt;code&gt;**TIMEOUT**&lt;/code&gt; , We can set a maximum number of skips allowed like 5. Then if the job is skipped for 5th time then it will reset and start a new job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;delay()&lt;/code&gt;&lt;/strong&gt; - A function that returns a promise that resolves after a given number of milliseconds, Typically your logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is more like a temporary hack to avoid overlaps , these timeout scenarios are so dangerous.
&lt;/h2&gt;

&lt;p&gt;A more scalable approach is to use a queueing system to manage the jobs. This can allow multiple instances of the job to be queued up and executed in sequence, without overlaps or duplicates. Popular queueing systems for Node.js include &lt;a href="https://www.npmjs.com/package/bull" rel="noopener noreferrer"&gt;Bull&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/bee-queue" rel="noopener noreferrer"&gt;Bee-Queue&lt;/a&gt;, and &lt;a href="https://www.npmjs.com/package/agenda" rel="noopener noreferrer"&gt;Agenda&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading&lt;br&gt;
 🕊 &lt;code&gt;Peace&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Try Our new product for free!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docsai.app/" rel="noopener noreferrer"&gt;DocsAI&lt;/a&gt; - Create AI support agents with your documents in the most affordable price, starts at &lt;strong&gt;0$&lt;/strong&gt;. Don't need a bot , but need ai help on your docs just upload and start chating !&lt;/p&gt;

&lt;p&gt;Using for a company ? &lt;a href="https://docsai.app/pricing" rel="noopener noreferrer"&gt;Check out our pricing&lt;/a&gt; Just contact me for personalized pricing !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fshrihari-personal-storage.appspot.com%2Fo%2Fbanner-docs-jpeg.jpeg%3Falt%3Dmedia%26token%3D45c47666-de2a-4e02-8881-beb6e43ce581" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fshrihari-personal-storage.appspot.com%2Fo%2Fbanner-docs-jpeg.jpeg%3Falt%3Dmedia%26token%3D45c47666-de2a-4e02-8881-beb6e43ce581" alt="docsAi"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Beyond Coding : The DevOps Tasks I do as a web dev.</title>
      <dc:creator>Shrihari Mohan</dc:creator>
      <pubDate>Sun, 26 Mar 2023 06:21:12 +0000</pubDate>
      <link>https://forem.com/shrihari/beyond-coding-the-devops-tasks-i-do-as-a-web-dev-311f</link>
      <guid>https://forem.com/shrihari/beyond-coding-the-devops-tasks-i-do-as-a-web-dev-311f</guid>
      <description>&lt;h2&gt;
  
  
  1. Using &lt;code&gt;SSH&lt;/code&gt; collaboration across &lt;code&gt;Dev Tools&lt;/code&gt;.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As a developer, you may have found yourself needing to verify code changes or perform hotfixes on production servers. &lt;strong&gt;Visual Studio Code's SSH&lt;/strong&gt; extension allows you to directly connect to remote folders, simplifying the debugging process and . You can navigate through systems as if you're on the server itself, without interfaces or multiple logins. &lt;em&gt;(NeoVim is also good alternative if you know the shortcuts)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connect to SQL servers behind a bastion host with ease using DBeaver and local tunneling. &lt;a href="https://dev.to/shrihari/dbeaver-ssh-bastion-host-google-authenticator-how-to-connect-lph"&gt;Here's how you can do it.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Controlling workflow with Git CLI and SSH. I started on command line then moved to Github Desktop and then back to CLI .I had inconsistencies with fetch and getting latest commits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Going through server logs.
&lt;/h2&gt;

&lt;p&gt;Getting to know the linux commands really comes handy when gazing. The combinations of &lt;code&gt;less&lt;/code&gt; and &lt;code&gt;grep&lt;/code&gt; brings great deal of analytics and easy problem solving.&lt;/p&gt;

&lt;p&gt;Commands I use regularly.&lt;br&gt;
&lt;code&gt;less&lt;/code&gt; - view file contents page by page with navigation&lt;br&gt;
&lt;code&gt;tail&lt;/code&gt; - view the end of a file or live stream of log data&lt;br&gt;
&lt;code&gt;cat&lt;/code&gt; - view a file&lt;br&gt;
&lt;code&gt;grep&lt;/code&gt; - search for a specific pattern in a file&lt;/p&gt;

&lt;p&gt;I also set up &lt;code&gt;oh-my-zsh&lt;/code&gt; that covers most of the terminal enhancements one could have.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Using docker for local setups
&lt;/h2&gt;

&lt;p&gt;Streamlining my local development process has never been easier since I started using &lt;code&gt;Docker&lt;/code&gt; - now I can effortlessly set up &lt;code&gt;MySQL&lt;/code&gt;, &lt;code&gt;MongoDB&lt;/code&gt;, and even the operating system, without the hassle of configuring each service individually on my machine.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Peace 🕊&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;If you are here it means you may have found this blog helpful. Just follow me &lt;a class="mentioned-user" href="https://dev.to/shrihari"&gt;@shrihari&lt;/a&gt; which will motivate to write more. You can make a &lt;a href="https://www.buymeacoffee.com/shriharimohan"&gt;Buttermilk 🥛&lt;/a&gt;. Small support comes a long way!&lt;/p&gt;

&lt;p&gt;Subscribe If you want to receive these blogs in your mail from @&lt;a href="https://medium.com/@shriharimohan"&gt;Medium&lt;/a&gt; for free!&lt;/p&gt;
&lt;h2&gt;
  
  
  Try Our new product for free!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docsai.app/"&gt;DocsAI&lt;/a&gt; - Create AI support agents with your documents in the most affordable price, starts at &lt;strong&gt;0$&lt;/strong&gt;. Don't need a bot , but need ai help on your docs just upload and start chating !&lt;/p&gt;

&lt;p&gt;Using for a company ? &lt;a href="https://docsai.app/pricing"&gt;Check out our pricing&lt;/a&gt; Just contact me for personalized pricing !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i2yl_xPB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://firebasestorage.googleapis.com/v0/b/shrihari-personal-storage.appspot.com/o/banner-docs-jpeg.jpeg%3Falt%3Dmedia%26token%3D45c47666-de2a-4e02-8881-beb6e43ce581" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i2yl_xPB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://firebasestorage.googleapis.com/v0/b/shrihari-personal-storage.appspot.com/o/banner-docs-jpeg.jpeg%3Falt%3Dmedia%26token%3D45c47666-de2a-4e02-8881-beb6e43ce581" alt="docsAi" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  More things from me
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyaTN21p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--IYwCeY9Q--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/693354/d92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/how-i-built-a-chrome-extension-that-finds-ghost-css-ghost-css-detector-4aj0" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I Built a chrome extension that finds Ghost CSS : Ghost-CSS-Detector&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Jan 11&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyaTN21p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--IYwCeY9Q--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/693354/d92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/two-things-that-make-my-terminal-experience-awesome-in-mac-3eie" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Two things that make my Terminal experience awesome 🚀 in Mac/Linux&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Sep 18 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#linux&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/shrihari" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyaTN21p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/practicaldev/image/fetch/s--IYwCeY9Q--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/693354/d92a0fbc-978c-4086-b5e9-4189e5eb23af.jpg" alt="shrihari"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/shrihari/angular-ng-templates-crafting-reusable-templates-with-ease-2dap" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🚀 Angular ng-templates: Crafting Reusable templates with Ease&lt;/h2&gt;
      &lt;h3&gt;Shrihari Mohan ・ Feb 14&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#angular&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
