<?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>DEV Community: Niladri</title>
    <description>The latest articles on DEV Community by Niladri (@royniladri).</description>
    <link>https://dev.to/royniladri</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%2F518724%2Ffc3d363d-14c6-408b-a154-ac17e14c63cc.png</url>
      <title>DEV Community: Niladri</title>
      <link>https://dev.to/royniladri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/royniladri"/>
    <language>en</language>
    <item>
      <title>Turbocharge your Jekyll Website</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Fri, 09 Jul 2021 19:01:20 +0000</pubDate>
      <link>https://dev.to/royniladri/turbocharge-your-jekyll-website-2f09</link>
      <guid>https://dev.to/royniladri/turbocharge-your-jekyll-website-2f09</guid>
      <description>&lt;p&gt;Jekyll is a static site generator based on Ruby. It is a popular option for creating simple blogs with more focus on the content.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625845427759%2FHZhjEL8TK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625845427759%2FHZhjEL8TK.png" alt="Jekyll"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;From &lt;a href="https://jekyllrb.com/" rel="noopener noreferrer"&gt;https://jekyllrb.com/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of simple templates available to jumpstart, and they are compatible with GitHub Pages. You just start writing &lt;code&gt;Markdown&lt;/code&gt; files and you can have a site up and running in no time! But oftentimes, it will not be optimized. Here is a list of things that are often not part of a free template:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Google Analytics&lt;/li&gt;
&lt;li&gt;Sitemaps&lt;/li&gt;
&lt;li&gt;RSS/ATOM feed&lt;/li&gt;
&lt;li&gt;E-mail Subscription&lt;/li&gt;
&lt;li&gt;Comments&lt;/li&gt;
&lt;li&gt;Progressive Web App (PWA)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All these results in a suboptimal experience for the users. With some simple enhancements, we can boost up the &lt;a href="https://developers.google.com/web/tools/lighthouse/" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; score of our site a lot.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625846125743%2FhoERq61rW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625846125743%2FhoERq61rW.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Site Score on Lighthouse&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Excellence/Perfection is not a destination; it is a continuous journey that never ends. - Brian Tracy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;TLDR: &lt;a href="https://github.com/royNiladri/omscs-journey" rel="noopener noreferrer"&gt;Show me the code&lt;/a&gt; &lt;a href="https://omscs.royniladri.dev/" rel="noopener noreferrer"&gt;Show me the site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠ &lt;strong&gt;Prerequisite Alert&lt;/strong&gt;: This article will assume you have a basic understanding of how a Jekyll site works. Refer to the &lt;a href="https://jekyllrb.com/docs/structure/" rel="noopener noreferrer"&gt;Folder Structure&lt;/a&gt; for a quick overview of the project resources.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding Google Analytics 📈
&lt;/h2&gt;

&lt;p&gt;Head over to &lt;a href="http://analytics.google.com/" rel="noopener noreferrer"&gt;Google Analytics&lt;/a&gt; and click &lt;code&gt;Start Measuring&lt;/code&gt;. You can follow the steps to enlist your webpage. If you want a step-by-step guide for the same, check the &lt;a href="https://support.google.com/analytics/answer/9304153#zippy=%2Cweb" rel="noopener noreferrer"&gt;official doc&lt;/a&gt;. Once that is done, head over to the Jekyll project and add the GA property id in &lt;code&gt;_config.yml&lt;/code&gt; as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;google_analytics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UA-XXXXX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You would probably want analytics to run on all thee pages, and hence need to add the script at the base layout. For most projects it should be at &lt;code&gt;_layouts/default.html&lt;/code&gt;. Add the following in the head section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{% if site.google_analytics %}
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.googletagmanager.com/gtag/js?id={{ site.google_analytics }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config&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;{{ site.google_analytics }}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
{% endif %}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this you can use in all your future project templates. This will not be rendered when you do not specify the &lt;code&gt;google_analytics&lt;/code&gt; key in  &lt;code&gt;_config.yml&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sitemap 🗺
&lt;/h2&gt;

&lt;p&gt;Sitemaps are documents (can be .txt, or .XML) that list the locations in the webpage. They help search engine crawlers to crawl all the pages of your site for better search results. This can be easily added using a Jekyll plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- Jekyll-sitemap&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should generate a page at the root level &lt;code&gt;/sitemap.xml&lt;/code&gt;. You can now add this to &lt;a href="https://search.google.com/" rel="noopener noreferrer"&gt;Google Search Console&lt;/a&gt; and enjoy indexing benefits!&lt;/p&gt;

&lt;h2&gt;
  
  
  RSS/ATOM Feed  🔔
&lt;/h2&gt;

&lt;p&gt;There is again an easy way out with the &lt;a href="https://github.com/jekyll/jekyll-feed" rel="noopener noreferrer"&gt;jekyll-feed&lt;/a&gt; plugin. Add the plugin, do a bundle install and the feed should start appearing at &lt;code&gt;/feed.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- Jekyll-feed&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your users can subscribe to the feed to get notified when you write a post!&lt;/p&gt;

&lt;h2&gt;
  
  
  E-mail Subscription 💌
&lt;/h2&gt;

&lt;p&gt;If you want to give your users a way to be contacted when you want to announce something, you can set up an email subscription. One popular option is to use &lt;a href="https://mailchimp.com/" rel="noopener noreferrer"&gt;MailChimp&lt;/a&gt;. There is a free tier that should be sufficient for most starting bloggers.&lt;br&gt;
Once you set up an account there, Click on &lt;code&gt;Create&lt;/code&gt; &amp;gt; &lt;code&gt;Signup Forms&lt;/code&gt; &amp;gt; &lt;code&gt;Embedded form&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625848713424%2FXsZIM5Tyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625848713424%2FXsZIM5Tyq.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
Now you can copy the code given and paste it under _includes. You can modify the HTML and CSS to make it look and feel in tune with your existing theme. Assuming you created a partial called &lt;code&gt;mailchimp.html&lt;/code&gt;, you can include it in different &lt;code&gt;layouts&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625849109603%2F1-18syJYK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625849109603%2F1-18syJYK.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
After adding my customizations, it looks like this. Much better right?&lt;/p&gt;
&lt;h2&gt;
  
  
  Comments 💬
&lt;/h2&gt;

&lt;p&gt;There are some options in this space. Some have privacy concerns, while other need hosting. So a hacky way is to use GitHub issues as comments. Some wrappers make it easy. One such example is &lt;a href="https://utteranc.es/" rel="noopener noreferrer"&gt;Utterances&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625849811267%2Fn1Ssti5kP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625849811267%2Fn1Ssti5kP.png" alt="Utterences"&gt;&lt;/a&gt;&lt;br&gt;
It is simple and easy to set up. Just add permissions to the repository and add a small script in the layouts that require comments. Ensure to add &lt;code&gt;async&lt;/code&gt; to ensure it does not impact load time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Progressive Web App (PWA) 📱
&lt;/h2&gt;

&lt;p&gt;Enhancing a web app to a PWA has certain benefits. It will take more than a series to explore the nitty-gritty details of PWA (I'll keep adding articles). For a brief introduction, you can check my post on &lt;a href="https://ones-zeros.royniladri.dev/js-service-workers-an-introduction" rel="noopener noreferrer"&gt;JS Service Workers&lt;/a&gt;. In this section, we will enable the PWA feature with a basic &lt;code&gt;manifest.json&lt;/code&gt; and install a service worker that caches the pages when you visit them so that you can still use the site when offline. For this, I have mostly followed the tutorial from &lt;a href="https://alokprateek.in/articles/jekyll-pwa/" rel="noopener noreferrer"&gt;Meteoric Teachings&lt;/a&gt; by &lt;em&gt;Alok Prateek&lt;/em&gt;. After you are done with the changes, Lighthouse (Chrome inspector tab) nags about a few things. You can read the details about those by checking the reference links in the Lighthouse tab. Let us fix those!&lt;/p&gt;
&lt;h3&gt;
  
  
  Custom Splash Screen
&lt;/h3&gt;

&lt;p&gt;Add an icon asset to the manifest.json file that is at least 512x512.&lt;/p&gt;
&lt;h3&gt;
  
  
  Maskable icon
&lt;/h3&gt;

&lt;p&gt;Add a maskable icon in the manifest.json file which is at least 192x192.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/assets/images/gt-logo-maskable.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sizes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"240x240"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"purpose"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"maskable"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can turn an image to its maskable format using the &lt;a href="https://maskable.app/editor" rel="noopener noreferrer"&gt;Maskable.app Editor&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Apple touch icon
&lt;/h3&gt;

&lt;p&gt;Add a link tag in the &lt;code&gt;head&lt;/code&gt; of the default layout.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="apple-touch-icon" href="/assets/images/logo.png"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus SEO optimizations 🧪
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add description and title to all the pages/posts&lt;/li&gt;
&lt;li&gt;Add thumbnails for social media share
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta property="og:image" content="{{site.url}}{{site.baseurl}}/assets/images/page-img.jpg"&amp;gt;
&amp;lt;meta property="twitter:image:src" content="{{site.url}}{{site.baseurl}}/assets/images/page-img.jpg"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/turbocharge-your-jekyll-website" rel="noopener noreferrer"&gt;https://ones-zeros.royniladri.dev/turbocharge-your-jekyll-website&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-blue.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jekyll</category>
      <category>seo</category>
      <category>performance</category>
    </item>
    <item>
      <title>Taking Back Privacy in 2021</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Fri, 15 Jan 2021 17:21:09 +0000</pubDate>
      <link>https://dev.to/royniladri/taking-back-privacy-in-2021-1fc2</link>
      <guid>https://dev.to/royniladri/taking-back-privacy-in-2021-1fc2</guid>
      <description>&lt;p&gt;The Social Dilemma opened our eyes to the way social networks operate. While many can argue they do not have anything to hide, giving machines power to understand and predict you better is something I am not comfortable with. I get irked when I see advertisements for Marvel T-shirts moments after I discuss getting a T-shirt around my phone. I made a couple of changes to my online life. Next up is the Whatsapp agreement. Yes, WhatsApp still cannot read your chats with friends and family, but they can tap into conversations with business accounts, and share that data with 3rd party. So what do we do now? Here's my list of online changes that I follow and would recommend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web browser and search engine
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jMzaFFtT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610694514140/jEKkCQs7l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jMzaFFtT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610694514140/jEKkCQs7l.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://duckduckgo.com/"&gt;DuckDuckGo&lt;/a&gt; is a private search engine and also has a mobile app. It does not track user queries. What this means is that you will stop getting all the customized results you saw on Google, which in turn translates to you spending a few more seconds to find your result. Does it replace Google? No. There are times I have a hard time finding a result, in which case I try Google. But now I give Google maybe 1 in 20 searches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser extension
&lt;/h2&gt;

&lt;p&gt;I already used to have &lt;a href="https://adblockplus.org/"&gt;AdBlockPlus&lt;/a&gt;, and it is great at removing advertisements from sites, but it was not enough. I came across &lt;a href="https://privacybadger.org/"&gt;Privacy Badger&lt;/a&gt;, an extension that disables popular trackers.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zbQlKW----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610694849673/8DDtXyj2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zbQlKW----/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610694849673/8DDtXyj2y.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Social Media
&lt;/h2&gt;

&lt;p&gt;Well, this one is tricky. You cannot just ditch Facebook/Instagram/LinkedIn/Twitter because you have all your friends and family there. So the next best thing you can do is time-bound those apps. Most smartphones come with a screen time limiter. Set the timer to say 30 minutes for Instagram and Facebook. Increase/decrease the time to your preference. Another thing to consider is getting polarised. You will often come across socially or politically charged posts and depending on how you engage with it, the platform will keep feeding you posts that mirror your belief system. An in-depth analysis is required before you take a drastic stand. Always listen to the other side of the story, check your sources, and do not recirculate "news" without validating authenticity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Messaging
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AmclHQCD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610695573586/jumoKHMRB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AmclHQCD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610695573586/jumoKHMRB.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
Lastly, addressing the elephant in the room, private chats. I had used &lt;a href="https://telegram.org/"&gt;Telegram&lt;/a&gt;, and it is quite functional. Due to the lack of group video calling feature, I switched to &lt;a href="https://signal.org/"&gt;Signal&lt;/a&gt;. and its privacy features are amazing. Of course, it is end to end encrypted. All the messages are saved locally on your device, backup, if enabled is encrypted, photos, or files you send are encrypted and stripped of metadata. The list goes on. It is open-source and runs on donations.&lt;/p&gt;

&lt;h2&gt;
  
  
  eMail
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8glpkVH3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610697253342/cUMfvxbGw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8glpkVH3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1610697253342/cUMfvxbGw.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
I am still in the process of exploration and might add more to this. I encountered &lt;a href="https://protonmail.com"&gt;ProtonMail&lt;/a&gt; and think it will suit my needs for now. The free plan has 500MB of storage and the monthly plans are a tad expensive. &lt;/p&gt;

&lt;h2&gt;
  
  
  Government's role
&lt;/h2&gt;

&lt;p&gt;Most companies have a separate set of rules when it comes to European countries. If you are a developer in a company that processes European data, you'll have encountered compliance training dedicated to GDPR (General Data Protection Regulation). The Government has taken stringent measures to ensure data about its people is not misused. More countries should take a stand and make a legal barrier against the monetization of private data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Individual's role
&lt;/h2&gt;

&lt;p&gt;Be aware of the applications you use. Glance through the data privacy section of terms and conditions. Know your biases, and take important decisions addressing those. Finally, shout out and contribute to open source projects that value data privacy. You as an individual have an important role in keeping the open-source community thriving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transition Summary (TLDR)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Google -&amp;gt; DuckDuckGo&lt;/li&gt;
&lt;li&gt;Chrome (Mobile Browser) -&amp;gt; DuckDuckGo (Mobile Browser)&lt;/li&gt;
&lt;li&gt;AdBlockPlus -&amp;gt; AdBlockPlus + Privacy Badger&lt;/li&gt;
&lt;li&gt;Social Media -&amp;gt; Limit Time, Research sources&lt;/li&gt;
&lt;li&gt;WhatsApp -&amp;gt; Telegram, Signal&lt;/li&gt;
&lt;li&gt;Gmail -&amp;gt; ProtonMail&lt;/li&gt;
&lt;li&gt;Encourage the Government to take privacy seriously&lt;/li&gt;
&lt;li&gt;Contribute to privacy champions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[Cover Photo courtesy: Photo by &lt;a href="https://unsplash.com/@tobiastu?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Tobias Tullius&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/privacy?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;]&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/taking-back-privacy-in-2021"&gt;https://ones-zeros.royniladri.dev/taking-back-privacy-in-2021&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y61HrVIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>dataprivacy</category>
      <category>lifestyle</category>
    </item>
    <item>
      <title>Time Management and Productivity Tools for Developers</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Tue, 05 Jan 2021 16:01:23 +0000</pubDate>
      <link>https://dev.to/royniladri/time-management-and-productivity-tools-for-developers-13oc</link>
      <guid>https://dev.to/royniladri/time-management-and-productivity-tools-for-developers-13oc</guid>
      <description>&lt;p&gt;Don't you love the rush of dopamine when you check off a task on a to-do list? It instills in us a sense of accomplishment apart from reaching the goal. Having a well-maintained to-do list also helps us keep on track. Hence, a few years ago, I started using Todoist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Todoist
&lt;/h2&gt;

&lt;p&gt;It is a great to-do list tracker. The free plan comes with enough organization features. You can group tasks into projects, make sections within a project, and add sub-tasks to a task. It parses natural language to set the deadline and allows recurring tasks. There is a concept of karma points when further gamify task completion. The top features of Todoist are the ease of adding new tasks and the widget for mobile devices for quick access.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yly_yfUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609848485363/CyX3bNoid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yly_yfUx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609848485363/CyX3bNoid.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this served me well for a few years, it does have some drawbacks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no place to add details&lt;/li&gt;
&lt;li&gt;It is easy to miss a deadline&lt;/li&gt;
&lt;li&gt;With a lot of overdue tasks and upcoming tasks, it can be stressful to manage at times (like after a vacation)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  MS Planner, Trello
&lt;/h2&gt;

&lt;p&gt;I tried to use professional project management tools to track my objectives and tasks for a while. While both of these have much richer features than Todoist, they lack simplicity. It takes a couple of clicks to add a task and all the fancy bells and whistles cause distractions. Hence, I moved out of them pretty quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notion
&lt;/h2&gt;

&lt;p&gt;This was a golden find. It is a note-taking application that processes markdown and can have structured data like in a database. With some YouTube hunting, I was able to set up a structure, where I have multiple projects, each containing some epics, and the final action items called tasks. I tweaked the fields to my preference and viola, I had my custom task tracking application. Notion also allows the creation of multiple views and add filters. So I can easily set up a view that showed what my upcoming tasks are for the week. Another fun part is everything in Notion is a block and a block can be linked to a page. So each task can be made into its own page where I can jot down my plans and progress.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qlemu704--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609847735539/YJye2CJw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qlemu704--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609847735539/YJye2CJw1.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;My Notion Dashboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can also create a page that you can share globally. It can be something like the future roadmap of a product or your upcoming content!&lt;/p&gt;

&lt;p&gt;But again, this is not a silver bullet. It's a little slow, and have negligible offline support. (I can add tasks or complete them offline in Todoist) The problem of time management too is not exactly solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Calendar
&lt;/h2&gt;

&lt;p&gt;After watching some more productivity videos I have added Calendar to the mix and it feels complete now. I have marked out times for office and self-care. I then add things like my study and blogging in the gaps, and lo and behold, I spend less time scrolling social media and ingesting adds, and more on developing myself. You can use a calendar of your choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The process
&lt;/h2&gt;

&lt;p&gt;Todoist is still the place where most of it starts. I add a task and a deadline. At some convenient time, I move that over to Notion and add relevant details. Then I check the calendar to ensure I have enough time to deliver it and block some of it. If I find that the deadline is not realistic, I either postpone it or remove its deadline (which implies I'll do it at some point when I get time). I have used this setup since the last quarter of 2020, and honestly, it has paid off. I delivered my tasks at my work, scored an A at college, and started blogging. I still have time to browse Netflix and chat with friends. &lt;/p&gt;

&lt;p&gt;Let me tell you, this is not perfect and by the end of this year I'll probably make some more changes, but it's important to start. Once to explore tools and set up a workflow, you will get to know what works and what does not. There are multiple productivity mantras and some of them might be conflicting. You have to experiment to understand which style suits you and gives you the best returns. And, always be open to change...&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy note
&lt;/h2&gt;

&lt;p&gt;None of the tools I listed are end to end encrypted. The traffic is encrypted on the wire due to HTTPS, but not at rest. Your data can be viewed by employees of the respective companies. So do not put your highly personal information or confidential information from your works place in these.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H_JY3fDa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609849731321/GTr_AWIdU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H_JY3fDa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609849731321/GTr_AWIdU.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Overview of E2E encryption&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links to mentioned apps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://calendar.google.com/calendar/"&gt;Google Calendar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Published content about productivity!&lt;/p&gt;




&lt;p&gt;Love what you see? Follow me or subscribe to the newsletter to stay updated when I post more cool stuff!&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/productivity-tools-for-developers"&gt;https://ones-zeros.royniladri.dev/productivity-tools-for-developers&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y61HrVIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>timemanagement</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My 2020 WFH Setup</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 30 Dec 2020 17:40:07 +0000</pubDate>
      <link>https://dev.to/royniladri/my-2020-wfh-setup-3g03</link>
      <guid>https://dev.to/royniladri/my-2020-wfh-setup-3g03</guid>
      <description>&lt;p&gt;This has been a crazy year. This is the year I realized that I love being out sometimes, even if I am an introvert! I switched my job and started my new position just a week before India went into complete lockdown. I had also started my Masters at Georgia Tech, and effectively was spending most of my awake time with my laptop. The place of work was my comfy bed. After a few weeks of insane poses, my back nudged me to do something about it! Thus the journey began.&lt;/p&gt;

&lt;h2&gt;
  
  
  The desk and chair
&lt;/h2&gt;

&lt;p&gt;I needed a place to keep my laptop and distance myself from the bed, hence a table and a chair. I hopped on to Amazon, got my mind blown by the prices, and procrastinated for a week. Then I headed over to a local shop and was pleasantly surprised by the pricing. I got a study desk with multiple drawers and cabinets and a comfy chair all in under INR 15,000 (~$200)! One heck of a bargain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The monitor
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1W-dJ3gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609346076975/ql2ZdJFex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1W-dJ3gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609346076975/ql2ZdJFex.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Dell P2419H - 24" Full HD LED Monitor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is a piece of beauty and functionality. The display is crystal clear, bot for work and entertainment. It comes with an adjustable stand, that allows changing the height and the tilt. This allows me the flexibility to use either one display on top of the other, or side by side. It has an elegant design and the thin bezels almost disappear into the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  The keyboard
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GXFi5IHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609346413906/dziF2qKkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GXFi5IHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609346413906/dziF2qKkh.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Logitech K375s Multi-Device Keyboard&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This crazy keyboard connects with both my windows laptops and my iPad. While it is true I have never used it with the iPad, but I just love this possibility. It can switch between 3 devices and supports Windows, Mac, Android, and obviously Linux. The only drawback that I found is the switch off button is at the back of the keyboard and hence hard to access. I love the key press feedback, but if you are expecting something mechanical, then this one is not it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mouse
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dUgCqPyv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609346880094/0a-uqfAZ8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dUgCqPyv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609346880094/0a-uqfAZ8.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Logitech B170 Wireless Mouse&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is a very basic wireless mouse. Gets the job done as long as you are on one system, but does not allow multidevice support. I have to manually plug in the receiver to the laptop I want to use. Looking for an upgrade next year.&lt;/p&gt;

&lt;h2&gt;
  
  
  The iPad Pro
&lt;/h2&gt;

&lt;p&gt;That is just for show on the table! I use it for my studies and when I want to be reminded that it takes more than an iPad and an overpriced apple pencil to create digital art. It's a pretty handy entertainment center and reader when on the move.&lt;/p&gt;

&lt;h2&gt;
  
  
  My laptops
&lt;/h2&gt;

&lt;p&gt;My personal laptop is a Dell Inspiron, with i7 7th gen, 16GB RAM, 4GB Radeon Graphics, 2TB HDD. My system runs Windows 10 by default, but I have set up Kubuntu dual boot. Having a dedicated Linux setup helps with my college projects. The laptop I got from my office is Lenovo with i7 8th Gen, 32 GB RAM, 512 GB SSD.&lt;/p&gt;

&lt;p&gt;Here is me with the imaginary teacup. While the laptops are powered by Intel, I am powered by tea!&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lSem1OBR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609347554213/nk5H3_8vp.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lSem1OBR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1609347554213/nk5H3_8vp.jpeg" alt="image.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrades to look forward to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Another display&lt;/li&gt;
&lt;li&gt;A gaming/streaming chair (I do neither, but they are comfy)&lt;/li&gt;
&lt;li&gt;A mouse that supports multi-device&lt;/li&gt;
&lt;li&gt;A cute desk plant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have any suggestions or recommendations, please do share in the comments below!&lt;/p&gt;




&lt;p&gt;Wish you all a very Happy New year! Keep hacking, keep learning.&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/my-2020-wfh-setup"&gt;https://ones-zeros.royniladri.dev/my-2020-wfh-setup&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y61HrVIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>workfromhome</category>
      <category>setup</category>
      <category>homeoffice</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Deploying Static WebApps - A Step by Step Guide</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 10:42:01 +0000</pubDate>
      <link>https://dev.to/royniladri/deploying-static-webapps-a-step-by-step-guide-3a7n</link>
      <guid>https://dev.to/royniladri/deploying-static-webapps-a-step-by-step-guide-3a7n</guid>
      <description>&lt;h4&gt;
  
  
  From index.html to a website on a custom domain
&lt;/h4&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Foreword&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This post assumes you know how to build a static website and merely touches over the options. This is intended as a deployment guide.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a website
&lt;/h2&gt;

&lt;p&gt;There are a lot of options to host static content. While most content creators would prefer the comfort of a service like &lt;a href="https://wordpress.com/" rel="noopener noreferrer"&gt;WordPress&lt;/a&gt;, as a developer, I tend to prefer a little more control. GitHub Pages provides both freedom and version control. The decision tree is just getting started here! You can create a website in GitHub using either of the following two ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Pages template using Jekyll
&lt;/h3&gt;

&lt;p&gt;There are some basic templates provided by GitHub Pages as jumping-off points. You can consider them as some sort of theme, and build based on top of that. The pages can be written in HTML or Markdown, and you can add styles and scripts to enhance functionality and experience. This uses Ruby to build the contents and might need some learning and getting used to before you can properly control it. Find more details about this option at &lt;a href="https://jekyllrb.com/docs/github-pages/" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt;. The benefit of using this option is that GitHub handles the building and rendering the site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a UI framework of your choice
&lt;/h3&gt;

&lt;p&gt;You can use any of the prevalent UI frameworks like Angular, React, Vue, and the sorts to generate a static site. You have to build the artifacts and configure GitHub Pages to render the contents of the &lt;em&gt;build&lt;/em&gt; or &lt;em&gt;dist&lt;/em&gt; folder. More options here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You can build the source code and commit the folder to be served&lt;/li&gt;
&lt;li&gt;  You can set up a build pipeline (I prefer &lt;a href="https://travis-ci.org/" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As Uncle Ben once said, “With great power, comes great responsibility”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Hosting
&lt;/h2&gt;

&lt;p&gt;On your repository, if you visit the setting sections and scroll down to GitHubPages, you’ll find the option to select a branch and root folder. By default, nothing will be selected. See below a basic setting that will create a page with the root folder, and use the README.md or index.html as the starting point. The hosted URL will be of the form:&lt;code&gt;https://&amp;lt;username&amp;gt;.github.io/&amp;lt;repository-name&amp;gt;&lt;/code&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1607161782747%2FY2rhd3jUE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1607161782747%2FY2rhd3jUE.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The site is now hosted on GitHub, using your username as a sub-domain. This is a good place to start and see changes. GitHub Pages is available only for public repositories for free members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Porting to a custom domain
&lt;/h2&gt;

&lt;p&gt;There comes a certain point in life where you want more! So one fine morning, you purchase a domain. There are again a lot of options out there and needs a post of its own. For context, I purchased mine from &lt;a href="https://domains.google/" rel="noopener noreferrer"&gt;Google domains&lt;/a&gt;, and it will cost me about a thousand Indian Rupees per year. As your hairs start greying, you’ll make more websites, which might be related to the same domain. Instead of purchasing multiple domains for a group of things, we can leverage the same one, thus reducing cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bad idea
&lt;/h3&gt;

&lt;p&gt;Set up different subprojects and make folders inside the &lt;em&gt;build&lt;/em&gt; directory. This will work, but the change of themes as the user browses through the same website will baffle them, not to mention that hosting different websites as subfolders will be unprofessional (example, &lt;a href="https://mark.com/facebook" rel="noopener noreferrer"&gt;https://mark.com/facebook&lt;/a&gt;, &lt;a href="https://mark.com/instagram" rel="noopener noreferrer"&gt;https://mark.com/instagram&lt;/a&gt; and so on). [Disclaimer: The author just came up with these links and are not meant to be visited. The author, aka me, will not be responsible for any or all losses incurred in an attempt to navigate to the aforementioned links.]&lt;/p&gt;

&lt;h3&gt;
  
  
  Subdomains to the rescue
&lt;/h3&gt;

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

&lt;p&gt;Yes, &lt;em&gt;www&lt;/em&gt; is a subdomain. The subdomain is an optional part and can be committed (check Medium URL). Generally, the apex domain (medium.com) and subdomain www (&lt;a href="http://www.medium.com" rel="noopener noreferrer"&gt;www.medium.com&lt;/a&gt;) point to the same resource or are redirected. We can use subdomains to host different sites, all under the same domain name. Continuing the example from above, the two sites now will be &lt;a href="https://facebook.mark.com" rel="noopener noreferrer"&gt;https://facebook.mark.com&lt;/a&gt; and &lt;a href="https://instagram.mark.com." rel="noopener noreferrer"&gt;https://instagram.mark.com.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us jump to the configurations now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Setting up A record
&lt;/h3&gt;

&lt;p&gt;You need to configure the A record so that it points to the Github Pages servers. The screenshot below shows the configuration for my domain. The IPs will be the same, but it is better to read some more about this from the &lt;a href="https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/managing-a-custom-domain-for-your-github-pages-site" rel="noopener noreferrer"&gt;GitHub doc&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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1607161842954%2FoYrefSZQS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1607161842954%2FoYrefSZQS.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A record configuration&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Setting up a subdomain
&lt;/h3&gt;

&lt;p&gt;This is the easiest step, as shown below- just add a CNAME record to point to your GitHub URL (remember .github.io). Generally, this takes a while to set up.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Step 3: Configuring GitHub
&lt;/h3&gt;

&lt;p&gt;Back at the GitHub repository settings page, fill in the box for “custom domain” and hit save. It will need some time to take effect. If your domain uses HTTPS, you can enforce HTTPS. This option will be enabled once the other things are set up by GitHub. A file called CNAME will typically be committed to the root of your repository by default. If this file is missing, please add one with the following details:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[subdomain.]domain-name.top-level-domain&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my case, the resulting line is &lt;em&gt;omscs.royniladri.dev&lt;/em&gt; (no protocol or slashes). It should contain just this line and nothing else. The subdomain is in square brackets because it is optional — you can host a GitHub Pages website on the apex domain.&lt;/p&gt;

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

&lt;p&gt;After all the settings are done, check back in an hour to find your newly hosted site. The icing on the cake is the fact that the old URL still works. If you had shared your &lt;em&gt;.github.io&lt;/em&gt; URL, all future requests are automatically forwarded to use the custom domain with no additional setup.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;May the domain be with you! — A curious developer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;[P.S. If you are interested in checking out the site, visit &lt;a href="https://omscs.royniladri.dev/" rel="noopener noreferrer"&gt;OMSCS Journey&lt;/a&gt;.]&lt;/p&gt;




&lt;p&gt;Love what you see? Follow me or subscribe to the newsletter to stay updated when I post more cool stuff!&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://medium.com/ones-zeros/deploying-static-webapps-6eb0f40ecdec" rel="noopener noreferrer"&gt;https://medium.com/ones-zeros/deploying-static-webapps-6eb0f40ecdec&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-blue.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>deployment</category>
      <category>domain</category>
      <category>github</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Date a Tech Bro</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 10:25:43 +0000</pubDate>
      <link>https://dev.to/royniladri/how-to-date-a-tech-bro-2f8a</link>
      <guid>https://dev.to/royniladri/how-to-date-a-tech-bro-2f8a</guid>
      <description>&lt;h1&gt;
  
  
  How to Date a Tech Bro
&lt;/h1&gt;

&lt;p&gt;This post was inspired by Anita Ihuman's  &lt;a href="https://movi.hashnode.dev/how-to-date-a-tech-sis-ckia30auq01b3jts1ep1sat2c" rel="noopener noreferrer"&gt;How to date a tech sis&lt;/a&gt;&lt;br&gt;
In this post, let me walk you over the fundamentals of dating a tech bro!&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep your bags packed
&lt;/h2&gt;

&lt;p&gt;Tech bros in general are travel enthusiasts. They spend most of the time staring at screens (from dual monitors to smartphones) and love the occasional escape to a few days of digital detox. &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%2Fstatic01.nyt.com%2Fimages%2F2015%2F12%2F06%2Fbooks%2Freview%2F1206-BKS-Travel%2F1206-BKS-Travel-articleLarge-v2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic01.nyt.com%2Fimages%2F2015%2F12%2F06%2Fbooks%2Freview%2F1206-BKS-Travel%2F1206-BKS-Travel-articleLarge-v2.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Be creative in your gifts
&lt;/h2&gt;

&lt;p&gt;As a techie, he probably makes enough money. He also loves the thrill of reading through articles and watching hundreds of YouTube reviews before making an informed decision. Do not deprive him of this adrenaline rush! Instead, get to know him and spend some time making something. He loves a personal touch.&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%2Fdata.whicdn.com%2Fimages%2F51239891%2Foriginal.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdata.whicdn.com%2Fimages%2F51239891%2Foriginal.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Be prepared to watch Nerdy movies
&lt;/h2&gt;

&lt;p&gt;Please know the difference between Star Trek, Star Wars, and Guardian of the Galaxy. Be ready to waste weekends with a rerun of the Batman trilogy, or a Marvel marathon! The good part is, he can pause and explain the intricate details if you blink and miss an important part.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/dQtT4S4BDBhcmjrjRb/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/dQtT4S4BDBhcmjrjRb/giphy.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Confide in him
&lt;/h2&gt;

&lt;p&gt;He is a keeper of secrets. So go ahead and make some confessions. Feeling insecure about something? Go ahead and talk to him. He makes a living out of turning bugs into features. He will be more than happy to show you the perfect picture of yourself that he sees!&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%2Fi.pinimg.com%2Foriginals%2F52%2F22%2Ffb%2F5222fb02155a032a609067e85dd879b9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.pinimg.com%2Foriginals%2F52%2F22%2Ffb%2F5222fb02155a032a609067e85dd879b9.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat his pet well
&lt;/h2&gt;

&lt;p&gt;A vast majority of techies own pets, and you better be comfortable with his furry friends or that might be a deal-breaker!&lt;br&gt;
&lt;a href="https://i.giphy.com/media/Kx82Lvb7wcYNO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Kx82Lvb7wcYNO/giphy.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Be explicit
&lt;/h2&gt;

&lt;p&gt;No, they don't understand unspoken words. They are worse than men in general when it comes to picking up social cues. Their evolution was hindered by the amount of &lt;code&gt;console.log&lt;/code&gt; and &lt;code&gt;System.out.println&lt;/code&gt; they frantically typed in! So please speak up and be assured that it will be heard.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/huySh9rd9tsIL4cBGf/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/huySh9rd9tsIL4cBGf/giphy.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't plan anything in the morning
&lt;/h2&gt;

&lt;p&gt;These creatures are night owls and show their worst colors when woke up early! So plan events accordingly; he will most likely not join you in your morning yoga! Going for a post-dinner stroll? Count him in.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/2tN5tQXC4CyURVwuwC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/2tN5tQXC4CyURVwuwC/giphy.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Read and support his blog
&lt;/h2&gt;

&lt;p&gt;Yes please! Blogs are not always tutorials and there are often some gems like these! You don't have to be a techie to show some support. Read them, share them with your friends. Help them get their dose of dopamine.&lt;br&gt;
&lt;a href="https://i.giphy.com/media/RlHVpsV3w8zO9lyE2E/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RlHVpsV3w8zO9lyE2E/giphy.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Go ahead and get that tech bro of yours! While they are relatively low maintenance, be warned they are fragile! So do not drop, knock, or spill coffee (on them or their work). Wish you the best of luck!&lt;br&gt;
&lt;a href="https://i.giphy.com/media/26tn8zNgVmit475RK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26tn8zNgVmit475RK/giphy.gif" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you liked this (highly informative) laughter pill for Saturday, and love staying up to date with technology trends, follow me on my journey! And finally, if you are feeling $3 richer,  help me get my dose of caffeine and L-Theanine.&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/how-to-date-a-tech-bro" rel="noopener noreferrer"&gt;https://ones-zeros.royniladri.dev/how-to-date-a-tech-bro&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-blue.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>humor</category>
      <category>funny</category>
      <category>devlife</category>
      <category>datingadvice</category>
    </item>
    <item>
      <title>TypeWritter Effect - Vanilla JS</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 10:16:31 +0000</pubDate>
      <link>https://dev.to/royniladri/typewritter-effect-vanilla-js-2a4a</link>
      <guid>https://dev.to/royniladri/typewritter-effect-vanilla-js-2a4a</guid>
      <description>&lt;h1&gt;
  
  
  TypeWritter Effect - Vanilla JS
&lt;/h1&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/nilroy/embed/JjXmjmZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;There comes a time when you want to do something cool like a typewriter on a web page. There are multiple ways to accomplish it, but today let me show you the vanilla JS way!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Algorithm
&lt;/h2&gt;

&lt;p&gt;First, we have to initialize a list of strings that we want to type and erase in a loop. The idea is to start from the first character of the first line. We keep adding characters, till we reach the end. Note that we have added &lt;code&gt;+ 5&lt;/code&gt; here to stall for a few more cycles before we start erasing. Then we start removing characters, this time 2 at a time! This creates an effect of slow typing and fast erase. Once we reach the beginning of the string, we reset the direction and move on to the next item in the array. Finally, once we reach the end, we start over from the first item in the array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;I switched to the performance tab and recorded the run for about 10 seconds. The scripting time is approximately 0.002%.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Advantage over CSS
&lt;/h2&gt;

&lt;p&gt;I have seen some CSS based solutions, but they have a dependency on the number of characters and work for only one string. This allows you to work with multiple strings in a loop and independent of the string length. If you want to tinker with the speed, just change the timeout value.&lt;/p&gt;




&lt;p&gt;Love what you see? Follow me or subscribe to the newsletter to stay updated when I post more cool stuff!&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/typewritter-effect-vanilla-js" rel="noopener noreferrer"&gt;https://ones-zeros.royniladri.dev/typewritter-effect-vanilla-js&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.buymeacoffee.com/royniladri" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-blue.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>animation</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Norman Doors - To Push or To Pull?</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 09:14:43 +0000</pubDate>
      <link>https://dev.to/royniladri/norman-doors-to-push-or-to-pull-3lm1</link>
      <guid>https://dev.to/royniladri/norman-doors-to-push-or-to-pull-3lm1</guid>
      <description>&lt;h2&gt;
  
  
  Norman Doors - To Push or To Pull?
&lt;/h2&gt;

&lt;p&gt;Doors are a portal, it allows us to access to buildings and also allows escape! But how many times have you tried to push a door that is meant to be pulled or vice-versa? Sometimes there is a sticker that says,  "Push", and yet you pull. If you feel embarrassed or stupid, worry not my friend, it is not your fault alone, it is a design flaw.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Donald Arthur Norman is an American researcher, professor, and author. Norman is the director of The Design Lab at the University of California, San Diego. He is best known for his books on design, especially The Design of Everyday Things.  &lt;a href="https://en.wikipedia.org/wiki/Don_Norman"&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doors can get even more complicated if you throw in revolving doors, clear glass doors, with no touchpoints. A door is said to be a &lt;strong&gt;Norman door&lt;/strong&gt; if it is not intuitive or self-explanatory. Let us now see how we can fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The push side
&lt;/h2&gt;

&lt;p&gt;If one side of the door is smooth without and handles or knobs, there is only one thing you can do with it. So not attaching anything to this side of the door is one option. But what if someone starts pushing close to the hinge? To deal with this, we need to give a visual clue as to which end of the door should be pushed - maybe in the form of a metal plate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tjn_C3JL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606988850314/X2K1bDTHR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tjn_C3JL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606988850314/X2K1bDTHR.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The pull side
&lt;/h2&gt;

&lt;p&gt;One of the most common things that we spot on a door is a handle. While it is easy to pull, it still allows pushing. The doors of cars are meant for pulling from the outside, but that design will not fit a big door. So, let us get back to handle. Adding a label will make things better, but not by much. We can design the pull handle in a way that makes push much easier than a pull. One such example is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ALREbf0i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606989955689/_zoAeWs2T.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ALREbf0i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606989955689/_zoAeWs2T.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
Do you have any more ideas to make the pull side better?&lt;/p&gt;

&lt;h1&gt;
  
  
  Emergency door
&lt;/h1&gt;

&lt;p&gt;Most emergency doors avoid confusion by not having a handle. There is a bar that affords to push. There are often instructions added, but during times of crisis, time is of the essence, and having a good design is priceless.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fWJ21m_Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606990072818/q_HfqkuKw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fWJ21m_Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606990072818/q_HfqkuKw.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch your steps
&lt;/h2&gt;

&lt;p&gt;While you wander around in this wide wild world, beware of such catastrophic designs!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QQJ3MyHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606990399682/6QaC0exgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QQJ3MyHx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606990399682/6QaC0exgw.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All this to say, good designs matter, not just in the software domain, but in the world out there in general. Next time you are designing something, and focusing on how to make it fancy, bear in mind, it needs to be usable and enjoyable. Design for the intended users!&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/norman-doors-to-push-or-to-pull"&gt;https://ones-zeros.royniladri.dev/norman-doors-to-push-or-to-pull&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/royniladri"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y61HrVIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>design</category>
      <category>userexperience</category>
      <category>normandoor</category>
    </item>
    <item>
      <title>Corporate CI/CD Setup - Introductions and Installations</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 09:07:46 +0000</pubDate>
      <link>https://dev.to/royniladri/corporate-ci-cd-setup-introductions-and-installations-3309</link>
      <guid>https://dev.to/royniladri/corporate-ci-cd-setup-introductions-and-installations-3309</guid>
      <description>&lt;h2&gt;
  
  
  Corporate CI/CD Setup - Introductions and Installations
&lt;/h2&gt;

&lt;p&gt;Welcome to the series. Today I will introduce you to the stack that we are going to use and set up accounts. We will be installing Jenkins and setting up a small backend project to demonstrate the build pipeline. To mock most corporate environments, I will be using Ubuntu 18.04 (Linux) as the working operating system. You can either have that as a dual boot alongside your windows or use a Virtual Machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install Jenkins
&lt;/h2&gt;

&lt;p&gt;The official guide provides detailed instructions on how to set it up on different environments. If you have any other Operating system, check out  &lt;a href="https://www.jenkins.io/doc/book/installing/" rel="noopener noreferrer"&gt;this installation guide&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;wget &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-O&lt;/span&gt; - https://pkg.jenkins.io/debian-stable/jenkins.io.key | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class="nb"&gt;sudo &lt;/span&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'echo deb https://pkg.jenkins.io/debian-stable binary/ &amp;gt; \
    /etc/apt/sources.list.d/jenkins.list'&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that to start Jenkins we need Java 8. If you do not have Java 8 or have a different version, you might see an error 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%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606799502369%2F5wO0u4Twc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606799502369%2F5wO0u4Twc.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
This can be easily rectified by installing the required version as such:&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;apt &lt;span class="nb"&gt;install &lt;/span&gt;openjdk-8-jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then installing Jenkins as before.&lt;/p&gt;

&lt;p&gt;If all works fine, you will not see any errors and will be able to open the Jenkins admin screen on &lt;code&gt;http://localhost:8080/&lt;/code&gt;. The password can be found in the file &lt;code&gt;/var/lib/jenkins/secrets/initialAdminPassword&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Plugins
&lt;/h2&gt;

&lt;p&gt;This is the screen you get when you log in:&lt;/p&gt;

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

&lt;p&gt;Now we have to start customizing Jenkins. We will start with the recommended set of plugins. There are quite a few plugins and this step might take a while to finish.&lt;/p&gt;

&lt;p&gt;Once that is done, it will ask for creating an Admin User.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606810933950%2FzA-ZgRPno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606810933950%2FzA-ZgRPno.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
For privacy concerns, I have not added the email field in the screenshot. Finally, you'll be taken to the Jenkins dashboard&lt;/p&gt;

&lt;p&gt;Time to land on the dashboard!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606811198850%2F5JKFTXxGh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606811198850%2F5JKFTXxGh.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up BitBucket and Jira
&lt;/h2&gt;

&lt;p&gt;We will be using  &lt;a href="https://bitbucket.org/" rel="noopener noreferrer"&gt;BitBucket&lt;/a&gt; as the source code management tool. It uses it as the versioning tool. For Scrum and issue tracking, we will be using  &lt;a href="https://www.atlassian.com/software/jira/free" rel="noopener noreferrer"&gt;Jira&lt;/a&gt;. Note that both of these have free versions and have enough features for our simple use case.&lt;/p&gt;

&lt;p&gt;Once logged in to BitBucket, create a workspace, then a project inside that workspace, and two repositories under the project. My repositories can be found at  &lt;a href="https://bitbucket.org/nilroy/server/src/master/" rel="noopener noreferrer"&gt;Server&lt;/a&gt; and  &lt;a href="https://bitbucket.org/nilroy/ui-app/src/master/" rel="noopener noreferrer"&gt;UI App&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Linking Jira project to Bitbucket project
&lt;/h3&gt;

&lt;p&gt;The first step is to link the workspace. Once done, we can follow along with the onscreen guide to add the relevant repositories.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606806618677%2F7K-RdBQo3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606806618677%2F7K-RdBQo3.png" alt="image.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ideally, you should see the list of repositories to choose from in Jira itself. For me, that was not the case. So I went back to BitBucket and selected the repository, and navigated to the Jira tab.&lt;/p&gt;

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

&lt;p&gt;Click on "Manage Linked projects" on the right top corner. &lt;/p&gt;
&lt;h2&gt;
  
  
  Creating Issues and View in Jira
&lt;/h2&gt;

&lt;p&gt;We can go to the backlog and create Issues (Stories or bugs). If you make a commit with the issue number, we will be able to see the same on Jira. &lt;/p&gt;

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

&lt;p&gt;Time to set up our first Jenkins job. In this step, we just want to get the contents of the repository in the workspace. Since this step interacts with &lt;code&gt;git&lt;/code&gt;, it is crucial that you have git preinstalled on the machine.&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;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's start by creating a Pipeline job:&lt;/p&gt;

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

&lt;p&gt;For the time being, we will jump down to the bottom and click on "Try Sample Pipeline" under Pipeline. We will remove all the unnecessary steps (as of now), and click on the Pipeline Syntax link.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606817394968%2FeFI2umXac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606817394968%2FeFI2umXac.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
You have to add a credential if one does not exist to access the repository.&lt;br&gt;
From here you can generate the line to copy and add it. The final pipeline should something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pipeline {
        agent any

        stages {
            stage('Build') {
                steps {
                    // Get some code from a GitHub repository
                    git credentialsId: 'xxxx-xxx-xxx-xxxx', url: 'https://&amp;lt;username&amp;gt;@bitbucket.org/nilroy/server.git'
                }
            }
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us save this and try to build the job by clicking build now. Lo and behold, our job works:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Basic server code
&lt;/h2&gt;

&lt;p&gt;As a simple example, I have created a maven project and added a class fine and a test file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getFullName&lt;/span&gt;&lt;span class="o"&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.Assert&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.junit.Test&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testFullName&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
        &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;nilroy&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;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Niladri"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Roy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Niladri Roy"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Niladri Roy"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check if everything is working as expected by running a clean install and a test using &lt;code&gt;mvn&lt;/code&gt;. Again if you do not have maven in your local system (or Virtual machine), you can add it using &lt;code&gt;sudo apt install maven&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build and Test
&lt;/h2&gt;

&lt;p&gt;Time to add the last bits of our skeleton pipeline, a stage that builds and a stage that tests. The final pipeline should look like this, with a shell running the maven for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pipeline {
        agent any

        stages {
            stage('Checkout') {
                steps {
                    // Get some code from a GitHub repository
                    git credentialsId: 'xxxx-xxxx-xxxxx', url: 'https://&amp;lt;username&amp;gt;@bitbucket.org/nilroy/server.git'
                }
            }
            stage('Build'){
                steps {
                    sh 'mvn -DskipTests clean install'
                }
            }
            stage('Test'){
                steps {
                    sh 'mvn test'
                }
            }
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now save it and run the job. If everything goes well, we will see a green field!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Why I used pipeline
&lt;/h2&gt;

&lt;p&gt;There is an easier way to configure Jenkins had we chosen an empty project. But creating a pipeline has a couple of advantages.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The results are much more clear and appealing&lt;/li&gt;
&lt;li&gt;The logs are chunked and we can focus on logs only when something fails.&lt;/li&gt;
&lt;li&gt;We are developers and prefer to type than click!&lt;/li&gt;
&lt;li&gt;You can easily set this up as a project file and version it.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;This is just the tip of an iceberg, and we have a lot to cover ahead. Stay tuned. To keep getting notified when I post, follow me or subscribe to the newsletter!&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://ones-zeros.royniladri.dev/corporate-cicd-setup-introductions-and-installations" rel="noopener noreferrer"&gt;https://ones-zeros.royniladri.dev/corporate-cicd-setup-introductions-and-installations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/royniladri" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-blue.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>jenkins</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>JS Service Workers — An Introduction</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 09:03:43 +0000</pubDate>
      <link>https://dev.to/royniladri/js-service-workers-an-introduction-39p4</link>
      <guid>https://dev.to/royniladri/js-service-workers-an-introduction-39p4</guid>
      <description>&lt;h2&gt;
  
  
  JS Service Workers — An Introduction
&lt;/h2&gt;

&lt;h4&gt;
  
  
  A journey towards taking your web application offline
&lt;/h4&gt;

&lt;h2&gt;
  
  
  The Why
&lt;/h2&gt;

&lt;p&gt;You have created an awesome website and ready to host it for everyone to find. You have taken the pain of making it responsive and it looks great on all standard devices. Let us walk through a hypothetical Developer vs Product Manager conversation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;PM:&lt;/em&gt;&lt;/strong&gt; Is this application responsive?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Dev:&lt;/em&gt;&lt;/strong&gt; Yes boss!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;PM:&lt;/em&gt;&lt;/strong&gt; Does it work when he is on a slow internet?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Dev:&lt;/em&gt;&lt;/strong&gt; Well, I have minimized the assets, serving them up gzipped, so its optimised, but might take a while to load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;PM:&lt;/em&gt;&lt;/strong&gt; What if he goes offline?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Dev:&lt;/em&gt;&lt;/strong&gt; (Dumbfounded)Web… Web application? Why would someone use a web application offline? We need to create apps if we want to provide offline capabilities!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next part of the conversation might not be very pleasant, so let us skip that. &lt;strong&gt;&lt;em&gt;What if I told you your web app can be taken offline? What if I told you that your app can act like a native application in multiple platforms and be pinned to the Start screen for easy access?&lt;/em&gt;&lt;/strong&gt; Welcome to PWA, welcome to the future (not really, it has been around for a while. While &lt;a href="https://youtu.be/MyQ8mtR9WxI" rel="noopener noreferrer"&gt;Google introduced PWA&lt;/a&gt; in 2015, &lt;a href="https://youtu.be/ZlE7dzoD6GA" rel="noopener noreferrer"&gt;Steve Jobs conceptualized it&lt;/a&gt; back in 2007!)&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it take?
&lt;/h2&gt;

&lt;p&gt;One word: &lt;em&gt;JavaScript&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you are a front end developer, you are already aware of JS, and its nitty-gritty details. You don’t have to learn Java, you don’t have to download software to develop an android app, and yet another for iOS. You don’t have to take the trouble of publishing it across multiple stores. You simply build upon your already existing awesome webpage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Lighthouse
&lt;/h2&gt;

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

&lt;p&gt;Have you seen the &lt;em&gt;lighthouse&lt;/em&gt; tab (it would come as an &lt;em&gt;audit&lt;/em&gt; on older versions) on Chrome developer tools? Go to any site and run it. You see a couple of metrics — how well does the site perform, does it take into account accessibility, does it follow best practices, and finally &lt;strong&gt;does it have what it takes to be a PWA&lt;/strong&gt;? This report then has details on how to improve upon the site and is a great place to start enhancing your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Service Worker
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don’t need a web page or user interaction. — &lt;a href="https://developers.google.com/web/resources/contributors/mattgaunt" rel="noopener noreferrer"&gt;Matt Gaunt&lt;/a&gt; on &lt;a href="https://developers.google.com/web/fundamentals" rel="noopener noreferrer"&gt;Web Fundamentals&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606737952102%2Fsk9mstkLl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606737952102%2Fsk9mstkLl.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Service Worker Overview from &lt;a href="https://docs.google.com/presentation/d/1bFVDRa71JK0ilr6lS6y9Twqp9gy8jzV1O8FFbG4A3qk/edit#slide=id.p9" rel="noopener noreferrer"&gt;Introduction to Service Workers&lt;/a&gt; by Google&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let us now dissect the definition:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A service worker is a script&lt;/em&gt; — It is composed of &lt;strong&gt;JavaScript.&lt;/strong&gt; Also note, it is a worker and hence cannot access DOM elements [No more &lt;em&gt;alert(“hello!”)&lt;/em&gt;], but has to communicate using messages.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Runs in the background —&lt;/em&gt; It is run on a &lt;strong&gt;different thread&lt;/strong&gt; than the main JS even loop. Note that it might be terminated when not in use, and restarted when required, hence using global variables is a very bad idea.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Opening the door to features —&lt;/em&gt; It is a programmable network proxy and can intercept requests, respond on behalf of server and cache resources.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Don’t need a web page or user interaction —&lt;/em&gt; Push notifications, background sync, payment updates — service works bring a lot of handy features to the web platform.&lt;/p&gt;
&lt;h2&gt;
  
  
  Service Worker Life Cycle
&lt;/h2&gt;

&lt;p&gt;The lifecycle of a service worker is not coupled with the web page. It starts with the first load of the page but persists long after the browser tab is closed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606738002464%2F6jy7oByZ-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606738002464%2F6jy7oByZ-.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Service Worker Life Cycle by &lt;a href="https://developers.google.com/web/resources/contributors/mattgaunt" rel="noopener noreferrer"&gt;Matt Gaunt&lt;/a&gt; on &lt;a href="https://developers.google.com/web/fundamentals" rel="noopener noreferrer"&gt;Web Fundamentals&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first step of registering a service worker is the install step. &lt;em&gt;Typically, assets are downloaded and cached in this step&lt;/em&gt;. If all goes well, it moves to the activated step, else moves to the error state. Once activated, it is ready to intercept requests and process messages. &lt;em&gt;Typically, old caches are invalidated here&lt;/em&gt;. When there is no activity, it remains idle, and after a few seconds of idling, is terminated. No need to be alarmed, it is brought back to life when a new event occurs, like a request or message. Note that since the worker can be terminated at any point, using global variables is heavily discouraged. IndexedDB can be used to persist data, including cache. The service worker is terminated after some seconds of inactivity to ensure that they don’t live in memory, draining resources.&lt;/p&gt;

&lt;p&gt;Service workers are extensively asynchronous and use Promises. No blocking actions are allowed in the worker, failing which it will be stopped.&lt;/p&gt;
&lt;h2&gt;
  
  
  Can I use Service Workers?
&lt;/h2&gt;

&lt;p&gt;Web developers have lost a lot of their hairs owing to browsers deviating from web standards, it is only natural to have this question at the back of your head while reading through this article. The short answer is no. While some do not support it all together, some allow limited features. The amount of storage also varies from platform to platform and from browser to browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606738020731%2Fp9GEWXoYS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1606738020731%2Fp9GEWXoYS.png" alt="image.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Browser compatibility of Service Worker, screenshot from &lt;a href="https://caniuse.com/?search=serviceworker" rel="noopener noreferrer"&gt;caniuse.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hence it is a good practice to do a feature test before installing a service worker. We should not have core functionalities in service workers as it might be executed in an incompatible platform-browser combination.&lt;/p&gt;

&lt;p&gt;Another factor to keep in mind is that Service Workers can be used only on &lt;strong&gt;HTTPS&lt;/strong&gt;-enabled websites. While it works on HTTP through &lt;em&gt;localhost&lt;/em&gt;, it will not work in an insecure site. Service workers are powerful, and “&lt;em&gt;with great power, comes great responsibility&lt;/em&gt;”. HTTPS ensures that the source of the script is the hosted site and protects against man-in-the-middle attacks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Time to Code
&lt;/h2&gt;

&lt;p&gt;Time to whip up some throwaway code! We will start with a simple HTML file with some script. We have a div with an id that we will change. We first check if we can rester a service worker, and if we can, go ahead to register it. Once it is registered, the DOM is updated. We also have logging of errors and meaningful messages to the DOM if something fails.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;index.html&lt;/em&gt;&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="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;First Service Worker&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Service Worker Test&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"response"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// chcek if the browser supports service workers&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serviceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;serviceworker.js&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="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="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;registration&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;// registration is an handle of the worker.&lt;/span&gt;
            &lt;span class="c1"&gt;// More event listeners can be attached or messages can be sent to this.&lt;/span&gt;
            &lt;span class="c1"&gt;// For this example, we just change the DOM to display message&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Service Worker registered properly&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="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;error&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;// Update DOM and log error in case resgistration fails&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Service Worker NOT registered&lt;/span&gt;&lt;span class="dl"&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;error&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// UPdate DOM to reflect service workers cannot be used&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Service Worker NOT available&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;serviceworker.js&lt;/em&gt;&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;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;We are a service worker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This is called once the worker is installed&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;install&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Install event&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;// This is called once the worker becomes active&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Activate event&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;serviceworker.js&lt;/em&gt; file is a barebone for now. We have logs to illustrate the flow. First, it is installed and then activated.&lt;/p&gt;

&lt;p&gt;Let me walk you through on how to run this. You can get both the files from the above &lt;em&gt;gist&lt;/em&gt;, but if you open the file in a browser it will not work. You’ll need to serve up the contents. The easiest way is to use the npm package called “&lt;em&gt;serve”&lt;/em&gt; (assuming you have &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;NodeJS&lt;/a&gt; development environment setup). You can navigate to the folder where you have these files and execute the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; serve
serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start serving the contents of the folder at port 5000. If you click on the link &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt; you’ll see the service worker is registered properly. If you click the network link (the one below local), the service worker will not work (remember HTTPS). In the debugger, you can see the details, as shown below, in the application tab. When you are developing, ensure that “Update on reload” is checked so that changes that you make to your worker are picked up. By default, a service worker once installed will always remain installed (but more on this later).&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Coming up
&lt;/h2&gt;

&lt;p&gt;This is the first of the series. More on service workers would be posted in the coming weeks. In the meantime, this piece sites a lot of resources that you can explore. Stay tuned to keep learning!&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://medium.com/ones-zeros/js-service-workers-an-introduction-12aabeea1a2b" rel="noopener noreferrer"&gt;https://medium.com/ones-zeros/js-service-workers-an-introduction-12aabeea1a2b&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/royniladri" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-blue.png" alt="Buy Me A Coffee"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>progressivewebapp</category>
      <category>serviceworkers</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React App and GitHub Actions</title>
      <dc:creator>Niladri</dc:creator>
      <pubDate>Wed, 23 Dec 2020 08:29:36 +0000</pubDate>
      <link>https://dev.to/royniladri/react-app-and-github-actions-1ne5</link>
      <guid>https://dev.to/royniladri/react-app-and-github-actions-1ne5</guid>
      <description>&lt;h2&gt;
  
  
  React App and GitHub Actions
&lt;/h2&gt;

&lt;h4&gt;
  
  
  From development to go-live in under 2 minutes
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oqneDKww--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606712595427/DQw_ikO8q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oqneDKww--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606712595427/DQw_ikO8q.png" alt="Who are we"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As developers, we are often guilty of doing this. The problem statement is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have a React application and want it deployed on GitHub Pages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The simplest way to achieve this is to locally build it, and push the build directory to “&lt;em&gt;gh-pages”&lt;/em&gt; branch and viola. Then I introduced &lt;a href="https://travis-ci.org/"&gt;Travis CI&lt;/a&gt; to achieve this and recently switched to GitHub Actions.&lt;/p&gt;

&lt;p&gt;I have already spent more hours setting this up than I probably would have spent doing it manually, so let me first try to justify my actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/features/actions"&gt;GitHub Action&lt;/a&gt; is a new kid in town, and as developers, it is our responsibility to become early (debatable at this point) adopters&lt;/li&gt;
&lt;li&gt;  It has inherent support — I don’t have to share keys and secrets with another third party.&lt;/li&gt;
&lt;li&gt;  It has a vibrant ecosystem that will only get better with time. For instance, it is just 2 lines to set up a Linux machine with NodeJs.&lt;/li&gt;
&lt;li&gt;  As a corporate employee who used Jenkins, the setup process feels welcoming.&lt;/li&gt;
&lt;li&gt;  It supports parallelly running multiple jobs! You can let everything run parallel, or create dependencies. It promises to be quite versatile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although my current problem statement does not require much of the aforementioned features, it is easier to get my hands dirty with a simpler project.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get started?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PVYBbYWD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606712637414/iQe_hvJKb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PVYBbYWD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606712637414/iQe_hvJKb.png" alt="GitHub Actions Home"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The simplest way to start a workflow is to go to the “Actions” tab on your repository and click “set up a workflow yourself”. This will create a file called &lt;em&gt;main.yml&lt;/em&gt; with some basic workflow. There is a structure to this YAML file to understand which we need to understand the components of GitHub actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Components of GitHub Actions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rl1uUqe7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606712685414/PQvQSr38S.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rl1uUqe7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606712685414/PQvQSr38S.png" alt="Components of GitHub Actions"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Components of GitHub Actions, from &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/introduction-to-github-actions#the-components-of-github-actions"&gt;GitHub Docs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GitHub events (push, pull requests, and so on) trigger one or more jobs. Each job is run on a server that is called Runner instance (Virtual machines or Docker instances). Each job comprises one or more steps and each step performs some actions, ranging from echo on a bash terminal to a complicated action developed by the GitHub community that does some heavy lifting. To know more about the components check out the &lt;a href="https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/introduction-to-github-actions#the-components-of-github-actions"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan of Action
&lt;/h2&gt;

&lt;p&gt;Now that we are equipped with the understanding of GitHub workflows, it is time to break our task at hand into smaller workable units.&lt;/p&gt;

&lt;p&gt;We will be starting with a Ubuntu server, and get the latest NodeJS environment setup. We will have to check out the code and install dependencies. Then we can build and finally publish to GitHub Pages.&lt;/p&gt;

&lt;p&gt;And at what point do I want to do this? To answer that, I need to talk briefly about the workflow I follow. I have a &lt;em&gt;development&lt;/em&gt; branch on which I work. I make frequent commits and often I do not want to publish changes after each commit. Once I feel I have reached a stable point, I create a pull request on the &lt;em&gt;master&lt;/em&gt; branch (this repository existed before they renamed &lt;em&gt;master&lt;/em&gt; to &lt;em&gt;main&lt;/em&gt;). So I want my action to kick in at a push on &lt;em&gt;master&lt;/em&gt;. Note that if I trigger it on pull-request, it will be triggered when the request is created, and I want it to trigger after it is merged. If you have multiple developers, you’ll need to control who can commit on &lt;em&gt;master&lt;/em&gt;/&lt;em&gt;main&lt;/em&gt; directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code of Action
&lt;/h2&gt;



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

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

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;12.x'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn --frozen-lockfile&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;peaceiris/actions-gh-pages@v3.7.3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;github_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;publish_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./build&lt;/span&gt;
          &lt;span class="na"&gt;cname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;domain_name&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;enable_jekyll&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;user_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;github-actions[bot]'&lt;/span&gt;
          &lt;span class="na"&gt;user_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;github-actions[bot]@users.noreply.github.com'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let us go over the steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The action has a name!&lt;/li&gt;
&lt;li&gt; We run it on a push to master.&lt;/li&gt;
&lt;li&gt; The job uses a Ubuntu server&lt;/li&gt;
&lt;li&gt; Check out code&lt;/li&gt;
&lt;li&gt; Setup NodeJS environment. We can specify the version(s), and yarn comes preinstalled.&lt;/li&gt;
&lt;li&gt; We install the dependencies and ensure the lock file is not changed in the process.&lt;/li&gt;
&lt;li&gt; We create an optimized production build.&lt;/li&gt;
&lt;li&gt; We use an action from the GitHub community to push the changes to the specific branch. We can make customization by setting certain parameters. (Since I have a custom domain, I set that here with &lt;em&gt;cname&lt;/em&gt;.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And that is all. You are all set to harness the goodness of GitHub Actions!&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;Apart from this, I have another action that runs the build job on every push to &lt;em&gt;development&lt;/em&gt; branch. This ensures I am not breaking anything that will prevent the build when I merge a pull request. Here is how it looks on my repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JJcrlyN9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606713498986/SYbPbB2Dl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JJcrlyN9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1606713498986/SYbPbB2Dl.png" alt="GitHub Actions in action.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;GitHub Actions in action, Niladri Roy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The failing build on my development branch helped me correct my mistake and once that started passing, I opened a pull request and merged it. This triggered the “&lt;em&gt;build_deploy CI&lt;/em&gt;” workflow, deploying my changes to my website, all in about a minute and a half! How cool is that?&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://medium.com/ones-zeros/react-app-and-github-actions-96c9f5444963"&gt;https://medium.com/ones-zeros/react-app-and-github-actions-96c9f5444963&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/royniladri"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y61HrVIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>react</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
