<?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: Gourav</title>
    <description>The latest articles on DEV Community by Gourav (@gorvgoyl).</description>
    <link>https://dev.to/gorvgoyl</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%2F92647%2F769eece3-31b3-4907-96a9-a01f0ec2f683.png</url>
      <title>DEV Community: Gourav</title>
      <link>https://dev.to/gorvgoyl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gorvgoyl"/>
    <language>en</language>
    <item>
      <title>The Journey of Migrating Our Browser Extension from Plasmo to WXT Framework</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Fri, 27 Sep 2024 15:35:42 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/the-journey-of-migrating-our-browser-extension-from-plasmo-to-wxt-framework-2c83</link>
      <guid>https://dev.to/gorvgoyl/the-journey-of-migrating-our-browser-extension-from-plasmo-to-wxt-framework-2c83</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally written at &lt;a href="https://chatgptwriter.ai/blog/migrate-plasmo-to-wxt" rel="noopener noreferrer"&gt;https://chatgptwriter.ai/blog/migrate-plasmo-to-wxt&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m excited to share that we've successfully migrated our &lt;a href="https://chatgptwriter.ai/" rel="noopener noreferrer"&gt;browser extension (ChatGPT Writer)&lt;/a&gt; from &lt;a href="https://www.plasmo.com/" rel="noopener noreferrer"&gt;Plasmo Framework&lt;/a&gt; to &lt;a href="https://wxt.dev/" rel="noopener noreferrer"&gt;WXT Framework&lt;/a&gt;. Both browser extension frameworks are top-notch for developing browser extensions, each with their own set of pros and cons. If you're curious about how they stack up against each other, &lt;a href="https://wxt.dev/get-started/compare.html#compare" rel="noopener noreferrer"&gt;this comparison&lt;/a&gt; offers a great overview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Decided to Migrate from Plasmo to WXT
&lt;/h2&gt;

&lt;p&gt;When OpenAI’s ChatGPT first launched, I decided to build a Chrome extension (in December 2022) that would integrate with Gmail and use ChatGPT to draft email replies. The next task was to choose the right tools, so I started researching the best options. Unlike JS, there weren’t many frameworks for building Chrome extensions. I knew Webpack was an option because I had previously built another browser extension (&lt;a href="https://github.com/GorvGoyl/Notion-Boost-browser-extension" rel="noopener noreferrer"&gt;Notion Boost&lt;/a&gt;) using it, but it had its own drawbacks. During my research, I stumbled upon the Plasmo framework, and it felt like the right choice at that time.  Plasmo handled code bundling, splitting, minification, and other tasks. It significantly sped up development, and I’m grateful to the authors for developing the library.&lt;/p&gt;

&lt;p&gt;While Plasmo has been a fantastic tool for us, it started to feel like it wasn’t the perfect fit anymore. Our browser extension has grown far beyond just drafting replies on Gmail. We noticed that our development progress—and our ability to roll out new features—was being slowed down.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any change would take more than 7 seconds to rebuild the extension on my M1 Mac. It was even slower on Windows.&lt;/li&gt;
&lt;li&gt;We also encountered odd issues where updated code wouldn’t reflect in the extension, and we had to restart the Plasmo server a couple of times to make it work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We were managing with these issues, but we had to draw the line when we were improving our extension’s UI to add support for Markdown and syntax highlighting and ran into significant hurdles. The issue was Plasmo's use of an &lt;strong&gt;outdated Parcel bundler&lt;/strong&gt;, which caused compatibility issues with Markdown and syntax highlighting packages that require a more up-to-date bundler. When we discussed this concern with the author about updating the Parcel version, we learned that the author is no longer actively working on the framework (which, by the way, I fully understand and respect), so there was little hope the issue would be resolved anytime soon.&lt;/p&gt;

&lt;p&gt;At this point, we wanted to rely less on &lt;em&gt;meta-frameworks&lt;/em&gt; and initially decided to use only the build tool &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; while writing the browser extension-specific configuration ourselves to minimize dependencies. We had seen great reviews of Vite from various developer communities online, so it seemed like the right choice.&lt;/p&gt;

&lt;p&gt;During our research, we also came across WXT, another meta-framework but built on top of Vite. After evaluating the pros and cons of using Vite versus WXT, we decided to go with WXT. Here’s why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vite is a general-purpose build tool, and we weren't sure how long it would take to write custom configurations to make it fully functional for browser extensions and to include all the features we had become accustomed to with Plasmo. WXT handles all of that for us, saving a lot of time.&lt;/li&gt;
&lt;li&gt;Since WXT is built on top of Vite, it benefits from Vite’s advantages. Additionally, if WXT is no longer maintained in the future, it would require less effort to switch to using Vite directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am happy with our decision to go with WXT at this time. Not only did WXT resolve our existing issues, but we also noticed a much smaller extension build size. When building the extension with Plasmo, the output ZIP file was 700 KB, but with WXT, it’s 400 KB.&lt;/p&gt;

&lt;p&gt;If you're interested in the discussions that influenced our decision, you can check out this &lt;a href="https://github.com/wxt-dev/wxt/discussions/782" rel="noopener noreferrer"&gt;thread on Github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Migration Process
&lt;/h2&gt;

&lt;p&gt;Migrating any project from one framework to another is rarely straightforward, and our transition from Plasmo to WXT was no exception. While WXT offers a brief migration guide in their documentation (&lt;a href="https://wxt.dev/get-started/migrate-to-wxt.html#plasmo" rel="noopener noreferrer"&gt;you can check it out here&lt;/a&gt;), that are sufficient for only basic extensions.&lt;/p&gt;

&lt;p&gt;If you're working on a complex browser extension like ours, you'll likely face a host of challenges that aren't covered in the official guide—from configuration conflicts to managing cross-context communication between background scripts and content scripts.&lt;/p&gt;

&lt;p&gt;We're here to share the changes and adjustments we had to make during our migration process. These insights might help you navigate similar issues you could encounter.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Organizing Entrypoints in WXT
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Differences in Entrypoint Management:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Plasmo, creating components like content scripts, background scripts, and popup was straightforward—you could simply define them at the root of your project, and they would work as expected. &lt;/p&gt;

&lt;p&gt;However, WXT handles entrypoints differently. In WXT, you need to place these files inside a specific directory called &lt;code&gt;entrypoints&lt;/code&gt; to ensure they are recognized and function properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create an&lt;/strong&gt; &lt;code&gt;entrypoints&lt;/code&gt; &lt;strong&gt;Directory:&lt;/strong&gt; Organize your entrypoint files by creating an &lt;code&gt;entrypoints&lt;/code&gt; directory at the root of your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move Your Entrypoint Files:&lt;/strong&gt; Place your content scripts, background scripts, injected scripts, and popup HTML files into this directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's how your project structure should look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;rootDir&amp;gt;&lt;/span&gt;
└─ entrypoints/
   ├─ background.ts
   ├─ content.ts
   ├─ injected.ts
   └─ popup.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Adding a Post-Install Command for WXT Preparation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why This is Necessary:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After setting up your entrypoints, WXT requires a &lt;code&gt;.wxt&lt;/code&gt; directory in your project. This directory contains essential type definitions, a &lt;code&gt;tsconfig&lt;/code&gt; file, and other global configurations necessary for your extension to function correctly during development and builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add a &lt;code&gt;postinstall&lt;/code&gt; script to your &lt;code&gt;package.json&lt;/code&gt; to automatically generate the &lt;code&gt;.wxt&lt;/code&gt; directory whenever you install dependencies using &lt;code&gt;npm install&lt;/code&gt;. This ensures WXT's configurations are always up-to-date.&lt;br&gt;
Here's how to add it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In your package.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ... other configurations&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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;// ... other scripts&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postinstall&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wxt prepare&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;By including this &lt;code&gt;postinstall&lt;/code&gt; command, you automate the setup process required by WXT, preventing potential issues related to missing configurations during development.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Config Adjustments
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;TypeScript Configuration Conflicts:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;During the migration to WXT, you may encounter conflicts arising from TypeScript configurations. WXT introduces its own TypeScript configuration file located inside the &lt;code&gt;.wxt&lt;/code&gt; directory. This can conflict with your existing &lt;code&gt;tsconfig.json&lt;/code&gt; file, leading to type-checking errors, broken import aliases, and other frustrating issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Instead of overwriting WXT's configuration, extend it within your own &lt;code&gt;.tsconfig&lt;/code&gt; file to allow both configurations to coexist smoothly. Additionally, you'll need to adjust some compiler options to prevent any conflicts and ensure smooth integration. Here's how you can do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;extends&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./.wxt/tsconfig.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compilerOptions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;....&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Managing Path Aliases:&lt;/strong&gt;  You might also face path conflicts due to differences in how WXT handles module resolution. We resolved this by following WXT's default path rules, which simplified the process and prevented import issues. &lt;/p&gt;

&lt;p&gt;Alternatively, you can define your own custom paths in &lt;code&gt;wxt.config.js&lt;/code&gt; if your project structure requires it. For more details on setting up custom path aliases, refer to &lt;a href="https://wxt.dev/api/reference/wxt/interfaces/InlineConfig.html#alias" rel="noopener noreferrer"&gt;this section&lt;/a&gt; in the WXT documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Environment Variable Issues
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Differences in Handling Environment Variables:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;WXT uses Vite under the hood, which manages environment variables differently than Plasmo. This means that environment variables that worked in Plasmo might become &lt;code&gt;undefined&lt;/code&gt; after migrating to WXT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You'll need to adapt to Vite’s method of handling environment variables. This involves prefixing your variables with &lt;code&gt;VITE_&lt;/code&gt; and accessing them using &lt;code&gt;import.meta.env&lt;/code&gt;. Here's a quick example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Defining an environment variable (using VITE_ as a prefix)&lt;/span&gt;
&lt;span class="nx"&gt;VITE_SOME_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;XXX&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieving the value of the environment variable (using import.meta.env)&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_SOME_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By making this change, you ensure that your environment variables are correctly recognized in the WXT environment. If you're unfamiliar with Vite's setup, the &lt;a href="https://vitejs.dev/guide/env-and-mode" rel="noopener noreferrer"&gt;Vite Environment Variables Guide&lt;/a&gt; is a helpful resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Migrating Manifest Configuration to &lt;strong&gt;&lt;code&gt;wxt.config.ts&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Differences in Manifest Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Plasmo, you might have defined your extension's manifest configuration directly within the &lt;code&gt;package.json&lt;/code&gt; file. However, WXT handles manifest settings differently. In WXT, you need to specify your manifest configuration inside a separate file called &lt;code&gt;wxt.config.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You'll need to migrate your manifest configuration from &lt;code&gt;package.json&lt;/code&gt; to &lt;code&gt;wxt.config.ts&lt;/code&gt;. Here's how you can set it up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create a&lt;/strong&gt; &lt;code&gt;wxt.config.ts&lt;/code&gt; &lt;strong&gt;File:&lt;/strong&gt; Start by creating a new file named &lt;code&gt;wxt.config.ts&lt;/code&gt; at the root of your project. This file will serve as the main configuration file for WXT.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migrate Your Manifest Configuration:&lt;/strong&gt; Move your existing manifest settings from &lt;code&gt;package.json&lt;/code&gt; into the &lt;code&gt;manifest&lt;/code&gt; field within &lt;code&gt;wxt.config.ts&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's how you can set it up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Inside wxt.config.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wxt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;manifestVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... your manifest configurations&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Adjusting Icon Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Differences in Icon Handling:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Plasmo, one of the convenient features is that it automatically generates smaller resolution versions of your icon for the build. This means you only need to provide a high-resolution version of your icon, and Plasmo handles the rest. Additionally, in development mode, Plasmo converts the icon to grayscale to help distinguish it from the production bundle.&lt;/p&gt;

&lt;p&gt;In contrast, WXT requires you to manually create icon files for each required resolution (e.g., 16×16, 48×48, 128×128). You'll need to place these icons inside the &lt;code&gt;public&lt;/code&gt; directory and explicitly define them in your manifest configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create Icons of Required Sizes:&lt;/strong&gt; Manually create your extension icons in all the necessary resolutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Place Icons in the Public Directory:&lt;/strong&gt; Store these icon files in your project's &lt;code&gt;public&lt;/code&gt; directory so they are accessible during the build process.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Define Icons in Manifest Configuration:&lt;/strong&gt; Update your &lt;code&gt;wxt.config.ts&lt;/code&gt; file to specify the icons in the manifest configuration. Here's how you can set it up:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;icons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/extension-icon-16.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/extension-icon-24.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/extension-icon-48.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/extension-icon-96.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/extension-icon-128.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We later learned that WXT provides &lt;a href="https://github.com/wxt-dev/wxt/tree/main/packages/auto-icons" rel="noopener noreferrer"&gt;auto-icons plugin&lt;/a&gt; that takes care of icons.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Handling Inline Asset Imports
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Differences in Asset Importing Between Plasmo and WXT:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Plasmo, when you want to import images or other assets inline, you use the &lt;code&gt;data-base64&lt;/code&gt; scheme. This method inlines the asset as base64-encoded data directly into your extension's bundle. &lt;/p&gt;

&lt;p&gt;In WXT, you don't need to use this scheme; you can import assets directly without any special prefixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Update your import statements by removing the &lt;code&gt;data-base64&lt;/code&gt; prefix. Here's how you can adjust your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Plasmo: Using data-base64 scheme&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-base64:~assets/image.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// WXT: Importing directly without data-base64&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Image&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~assets/image.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8. Resolving Port Conflicts in Development (Optional)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Potential Port Conflicts with Next.js:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're using Next.js as your backend server, you might encounter port conflicts during development. Both Next.js and WXT default to using port 3000, which can create issues when you try to run them simultaneously.&lt;/p&gt;

&lt;p&gt;In our experience, we had WXT already running on port 3000. When we attempted to start the Next.js server, it also tried to use port 3000. Surprisingly, even though the port was already occupied by WXT, the Next.js server started without any error messages or warnings about the port conflict. However, we couldn't access our Next.js application at &lt;code&gt;localhost:3000&lt;/code&gt; because WXT was occupying that port.&lt;/p&gt;

&lt;p&gt;This led to confusion because Next.js didn't notify us of the port being in use, and we were left wondering why our application wasn't accessible. On the other hand, WXT is capable of detecting when a port is already occupied and will automatically switch to another available port, preventing such conflicts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To resolve this port conflict, you have a couple of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Assign a Different Port to WXT:&lt;/strong&gt;  You can specify a different port for WXT to use during development. For example, you can start the WXT server on port 9000 by modifying your &lt;code&gt;package.json&lt;/code&gt; scripts or your start command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wxt --mode localhost --port 9000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// it will start the server on port 9000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way, WXT will run on &lt;code&gt;localhost:9000&lt;/code&gt;, leaving port 3000 free for Next.js. You can then access your Next.js application at &lt;code&gt;localhost:3000&lt;/code&gt; and your WXT extension at &lt;code&gt;localhost:9000&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start Next.js Server Before WXT:&lt;/strong&gt; Alternatively, you can start your Next.js server before starting WXT. Since WXT can detect an occupied port and automatically switch to another one, it will adjust itself to use a different port if it finds that port 3000 is already in use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  9. Handling Double Rendering in Development
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;React.StrictMode and Its Effects:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During development, you might notice that components, especially popup, render twice. This is because WXT uses &lt;code&gt;React.StrictMode&lt;/code&gt; by default, which intentionally double-invokes lifecycle methods to help identify potential issues.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&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="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Popup&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our case, we had message-sending logic inside a &lt;code&gt;useEffect&lt;/code&gt; hook, and the double rendering caused messages to be sent twice—once for each render. This led to unintended side effects in our extension's behavior during development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Be mindful that side effects (like API calls or message dispatches) inside &lt;code&gt;useEffect&lt;/code&gt; or other lifecycle methods might execute twice. To handle this gracefully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimize Side Effects:&lt;/strong&gt; Ensure that your side-effect logic can handle multiple invocations without causing unintended consequences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional Logic:&lt;/strong&gt; Implement checks to prevent duplicate actions if necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand It's a Development-Only Behavior:&lt;/strong&gt; Remember that this double rendering only occurs in development mode due to &lt;code&gt;React.StrictMode&lt;/code&gt;. Your production build won't have this issue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By adjusting your code to account for &lt;code&gt;React.StrictMode&lt;/code&gt;, you can prevent unwanted side effects during development without compromising your production code.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Managing Shadow DOM Implementation (Optional)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Differences in Shadow DOM Handling:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both Plasmo and WXT offer built-in methods for handling Shadow DOM functionality in browser extensions. When migrating to WXT, you have a couple of options for implementing Shadow DOM in your extension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use WXT's Built-in Shadow DOM Handling:&lt;/strong&gt; If you prefer to adopt WXT's approach, you can utilize their built-in methods for managing Shadow DOM. WXT provides a straightforward way to implement Shadow DOM. You can find detailed instructions in the WXT documentation: &lt;a href="https://wxt.dev/guide/key-concepts/content-script-ui.html#shadow-root" rel="noopener noreferrer"&gt;WXT Shadow Root Guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement a Framework-Independent Shadow DOM:&lt;/strong&gt; Alternatively, you might choose to implement Shadow DOM in a &lt;strong&gt;framework-independent&lt;/strong&gt; manner, as we did. This approach allows you to maintain consistency in your codebase and avoid adjustments during the migration process. By not relying on framework-specific methods, you make future migrations or updates more straightforward. If you're interested in adopting this method, I've detailed our approach in a &lt;a href="https://gourav.io/blog/render-react" rel="noopener noreferrer"&gt;Guide: Render React element inside shadow DOM&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  11. Avoid Cross-Context Code Sharing (Good to know)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Understanding Context Isolation in Extensions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Browser extensions run different parts of their code (like background scripts, content scripts, and popup) in separate contexts. Sharing code directly between these contexts can lead to errors because they don't share the same execution environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Might Need to Do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Messaging APIs for Communication:&lt;/strong&gt; Instead of sharing functions or variables directly between contexts, use messaging APIs (e.g., &lt;code&gt;chrome.runtime.sendMessage&lt;/code&gt;) to facilitate communication.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use a Shared Directory:&lt;/strong&gt; Organize reusable, context-independent code in a dedicated &lt;code&gt;shared&lt;/code&gt; directory. This allows you to import common functions or utilities without causing context conflicts.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;rootDir&amp;gt;&lt;/span&gt;
├─ entrypoints/
│  ├─ background.ts
│  ├─ content.ts
│  └─ popup.tsx
└─ shared/
   ├─ utils.ts
   └─ constants.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid Context-Specific Code in Shared Modules:&lt;/strong&gt; Ensure that the code in the &lt;code&gt;shared&lt;/code&gt; directory doesn't rely on context-specific APIs like &lt;code&gt;document&lt;/code&gt; or &lt;code&gt;window&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Migrating from Plasmo to WXT was a significant step that allowed us to overcome development hurdles and align our extension with our growing needs. While the process had its challenges, we hope that sharing our experiences and solutions will help others navigate their own migrations more smoothly.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>extensions</category>
      <category>vite</category>
      <category>react</category>
    </item>
    <item>
      <title>How to implement GPT4 API with internet access?</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Sun, 03 Dec 2023 05:55:04 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/how-to-implement-gpt4-api-with-internet-access-412f</link>
      <guid>https://dev.to/gorvgoyl/how-to-implement-gpt4-api-with-internet-access-412f</guid>
      <description>&lt;p&gt;As the question said what are some easy and economical ways to implement Internet access in GPT4 API  to get the latest information about world events?&lt;br&gt;
Would prefer a node.js solution if possible.&lt;br&gt;
PS: Internet access is not yet provided via API. Web ChatGPT version does this by crawling Bing.&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>webdev</category>
      <category>node</category>
      <category>discuss</category>
    </item>
    <item>
      <title>10+ ways to find blog post ideas as a developer</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Wed, 31 Aug 2022 14:12:27 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/10-ways-to-find-blog-post-ideas-as-a-developer-nni</link>
      <guid>https://dev.to/gorvgoyl/10-ways-to-find-blog-post-ideas-as-a-developer-nni</guid>
      <description>&lt;p&gt;When I first learned that writing online could make my resume stand out and even lend me a cushy job, I got excited and opened a notepad, but immediately hit a roadblock. I didn’t know what to write about in the first place. I felt like everything had been written and published online, and I had nothing new or interesting to write about. Newsflash: I couldn’t have been more wrong!&lt;/p&gt;

&lt;p&gt;Over the past few years, I’ve written many articles on different platforms that have been collectively read by 500k+ people. Some &lt;a href="https://gourav.io/blog/first-donation-on-open-source-side-project" rel="noopener noreferrer"&gt;of&lt;/a&gt; &lt;a href="https://gourav.io/blog/my-simple-github-project-went-viral" rel="noopener noreferrer"&gt;them&lt;/a&gt; even landed on the first page of HackerNews! I got approached for jobs by many companies, including the one (&lt;a href="https://monadical.com/" rel="noopener noreferrer"&gt;Monadical&lt;/a&gt;) I’m currently working for 😁.&lt;/p&gt;

&lt;p&gt;So, how do I come up with blog ideas? Well, whenever I hit writer’s block, I explore these four areas. They’ve never failed to help me find ideas for my next article. They are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw inspiration from within yourself&lt;/li&gt;
&lt;li&gt;Content research tools and tech communities&lt;/li&gt;
&lt;li&gt;Inspiration from other people’s tech blogs&lt;/li&gt;
&lt;li&gt;Summarise concepts from long-form content&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This guide is a summarised version of a longer one I wrote at &lt;a href="https://monadical.com/posts/blog-ideas-for-developers.html" rel="noopener noreferrer"&gt;https://monadical.com/posts/blog-ideas-for-developers.html&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Draw inspiration from within yourself&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Share your experience working on a project or technology&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Write about your overall experience on a particular project or technology. Some important points that readers find useful are key takeaway lessons, and how to avoid common pitfalls when working on a similar project. Many devs might find it surprising, but one of the most viewed &lt;a href="https://stackoverflow.com/questions/1783405/how-do-i-check-out-a-remote-git-branch" rel="noopener noreferrer"&gt;questions&lt;/a&gt; (7M views) on StackOverflow is simply “How to check out a remote Git branch?”. But there’s a reason for that. Even things that you think are obvious can be insightful to people who are new to this or don’t have your experience.&lt;/p&gt;

&lt;p&gt;Blog post examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I worked on the framework X for Y period, and here’s my experience so far&lt;/li&gt;
&lt;li&gt;What I learned from building X App using Y language/tech stack/framework&lt;/li&gt;
&lt;li&gt;How to resolve X issue in Y framework&lt;/li&gt;
&lt;li&gt;How to build an API server using X framework&lt;/li&gt;
&lt;li&gt;The best software company I have ever worked for, and what I learned&lt;/li&gt;
&lt;li&gt;Most difficult concepts to learn about language X&lt;/li&gt;
&lt;li&gt;Pros and Cons of using X database/library&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Take notes about what you’re learning or have recently learned, and share with others&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s suppose you’re learning something new, like a database you’ve never worked on or the latest hip JS framework from last week. You quickly discover that all the information you need to learn that thing is not available in one place. You browse the documentation, blogs, StackOverflow, and GitHub discussions, and (if you’re the bold type) maybe even ask for help in subreddits, Discord servers, etc. What you’ve just done is gold! Precious, precious gold, especially if the official documentation isn’t super dev-friendly (e.g., lacks code examples and explanations). Don’t throw your gold away; share it with the rest of us!&lt;/p&gt;

&lt;p&gt;As you work, quickly jot down these important basics, resources, better code samples, cheat sheets, etc., so that future learners don’t end up painstakingly crawling through the same scattered docs, chat rooms, and forums.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An intro to setting up an API server using Deno&lt;/li&gt;
&lt;li&gt;Async programming in Javascript vs Python&lt;/li&gt;
&lt;li&gt;How to see all running Amazon EC2 instances across all regions&lt;/li&gt;
&lt;li&gt;X best approaches for learning a programming language&lt;/li&gt;
&lt;li&gt;How to add authentication to X Framework&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Share your opinions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you work in an industry or community for a long time, you gain unique insights, start to see trends, and naturally form opinions. People love hearing strong opinions – whether they agree with them or not – and weighing in with their own take. Your thoughts are valuable! Don’t be afraid to sing them out.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I work in the Fintech industry, and too many regulations have crippled innovation&lt;/li&gt;
&lt;li&gt;Why do so many developers love Rust?&lt;/li&gt;
&lt;li&gt;Will Chrome’s dominance dictate the future of javascript and web?&lt;/li&gt;
&lt;li&gt;How to choose the right software architecture for an eCommerce platform&lt;/li&gt;
&lt;li&gt;How to collaborate with other developers&lt;/li&gt;
&lt;li&gt;How to be productive as a developer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Share what you’re passionate about&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Think of a topic you might discuss with your friends or bring up on a team call or a mentor meeting. What do you spend your time reading about when you should be sleeping? What can’t you stop reading about on the internet? Do you have any tips or tricks that help you stay motivated at work or in life? Any intriguing hobbies that are even a little bit tech-related? If you’re interested in it, then other people are too!&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ultimate guide to a pro gaming setup&lt;/li&gt;
&lt;li&gt;How to setup Kali Linux for penetration testing&lt;/li&gt;
&lt;li&gt;How to set up a crypto cold storage wallet for enhanced security&lt;/li&gt;
&lt;li&gt;Getting into open source and how to be a good contributor&lt;/li&gt;
&lt;li&gt;How I stay up to date in the tech industry&lt;/li&gt;
&lt;li&gt;What it was like when I first started blogging/YouTube as an introvert&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Get ideas from the internet&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can also utilize content research tools or dive into various online tech communities to get inspiration for your blog article ideas.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="https://answerthepublic.com/" rel="noopener noreferrer"&gt;answerthepublic.com&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Answerthepublic.com is a free site where you type a keyword and it generates a list of the most popular questions people have been asking on Google about it!&lt;/p&gt;

&lt;p&gt;For example: if you type “reactjs”, you’ll get these results:&lt;/p&gt;

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

&lt;p&gt;Pick a question that you feel comfortable answering, and start writing about it.&lt;/p&gt;

&lt;p&gt;Note: These are the &lt;strong&gt;top&lt;/strong&gt; questions about “reactjs” from Google search, so you imagine the volume your article would get if it landed on the first page!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="http://ubersuggest.org/" rel="noopener noreferrer"&gt;ubersuggest.org&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://ubersuggest.org/" rel="noopener noreferrer"&gt;ubersuggest.org&lt;/a&gt; is a freemium tool to generate keyword suggestions and content ideas.&lt;/p&gt;

&lt;p&gt;Here’s the screenshot of the top keywords and content ideas for “typescript”.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="http://reddit.com/" rel="noopener noreferrer"&gt;reddit.com&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are lots of programming-related subreddits which you can surf through to find interesting content to write about. Here’s a simple trick to see what others have been asking about a topic so that you can write about it.&lt;/p&gt;

&lt;p&gt;First, you need to find a subreddit for a language/framework/tool. Type a keyword in the search box at the top and select “Communities”. For example, here are the top subreddits for reactjs. The first subreddit in the list &lt;a href="https://www.reddit.com/r/reactjs" rel="noopener noreferrer"&gt;reactjs&lt;/a&gt; has around 300k+ members!&lt;/p&gt;

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

&lt;p&gt;Next, go to one of these subreddits and type “how” in the search box to see all questions that members asked. You can further sort these questions by week/month/year/all time to filter the most popular questions. Browse through these highest-voted questions and see if you could answer any of these in the form of an article.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="http://quora.com/" rel="noopener noreferrer"&gt;quora.com&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Get inspiration from people asking questions on a topic you know about. Type a keyword in a search term and hit enter.&lt;/p&gt;

&lt;p&gt;The below image shows what people have been asking about the &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;NextJS&lt;/a&gt; framework.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;dev.to&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can browse &lt;a href="https://dev.to/tags"&gt;various tags&lt;/a&gt; and see what people have been discussing to get inspiration.&lt;/p&gt;

&lt;p&gt;Here are the top monthly posts for tag #django:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  &lt;strong&gt;Using content research tools&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Many professional bloggers use content research tools like &lt;a href="https://ahrefs.com/content-explorer" rel="noopener noreferrer"&gt;Ahrefs&lt;/a&gt; or &lt;a href="https://buzzsumo.com/content-discovery/" rel="noopener noreferrer"&gt;BuzzSumo&lt;/a&gt; to get a streamlined flow of hot and trending topics to write about.&lt;/p&gt;

&lt;p&gt;These tools can help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discover the words and phrases your audience is searching for&lt;/li&gt;
&lt;li&gt;Find the most popular content in your niche across different platforms&lt;/li&gt;
&lt;li&gt;Access real-time views of viral trends for any topic, domain, or location&lt;/li&gt;
&lt;li&gt;Find low-competition topics to write about&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: these are paid tools and cost around ~$99/month.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Explore trending topics&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;These free tools are useful for discovering broader trending topics over time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://explodingtopics.com/" rel="noopener noreferrer"&gt;explodingtopics.com&lt;/a&gt; - Discover emerging technologies and trending topics by category, pick a topic that interests you, and write about it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://trends.google.com/trends" rel="noopener noreferrer"&gt;Google Trends&lt;/a&gt; - Google Trends is a website by Google that you can use to analyze the popularity of top search queries in Google Search. Enter a keyword and see related topics, top queries, interests over time, demographics, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Get inspiration from other people’s tech blogs&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;From your favourite bloggers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Do you follow any blogger whose articles you find to be quite enjoyable? What topics do they usually write about? If you’re interested in reading about these topics, why not write about them as well?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Discover the best developer blogs for your tech stack for inspiration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you don’t know many tech bloggers, check out this live list of the best and trending developer blogs. &lt;a href="https://bloggingfordevs.com/trends/" rel="noopener noreferrer"&gt;https://bloggingfordevs.com/trends/&lt;/a&gt;  You can filter blogs by tech stack as well. Interestingly this site was built by a tech blogger, &lt;a href="https://monicalent.com/blog/" rel="noopener noreferrer"&gt;Monica Lent&lt;/a&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  &lt;strong&gt;Summarise concepts from long-form content&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The knowledge present in long-form content has much more depth than what you usually find in articles or Youtube videos. So, if you’ve read any book or completed a course that helped you in your career or life, it’s an excellent opportunity for you to put quality content out. You could summarise the main concepts that stick with you and share them in the form of articles.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementing Abstract Factory design pattern in Go&lt;/li&gt;
&lt;li&gt;Data replication strategies on the server&lt;/li&gt;
&lt;li&gt;System design of notification service&lt;/li&gt;
&lt;li&gt;Detecting anomalies using Isolation Trees&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I hope this guide has given you enough resources to help you find inspiration for your next article. Start writing about the topics you’re interested in, or that you think will help others. Sometimes you’ll get multiple ideas, write them down and build your own repository of drafts that you can pick from. It’s okay if you think your content is not that great; just like other skills, you’ll get better the more you write. Remember, &lt;strong&gt;publishing something is still better than publishing nothing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PS: Don’t forget to bookmark this article so that you can quickly revisit it next time you hit writer’s block. I’ll also be adding more resources as I find them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally written at &lt;a href="https://monadical.com/posts/blog-ideas-for-developers.html" rel="noopener noreferrer"&gt;https://monadical.com/posts/blog-ideas-for-developers.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>A list of free &amp; open-source apps I use on Windows</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Tue, 14 Jun 2022 11:27:58 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/a-list-of-free-open-source-apps-i-use-on-windows-4mm</link>
      <guid>https://dev.to/gorvgoyl/a-list-of-free-open-source-apps-i-use-on-windows-4mm</guid>
      <description>&lt;p&gt;I’ve been a Windows power-user for a decade, and throughout the journey, I found tools and apps which made me work more efficiently on Windows.&lt;/p&gt;

&lt;p&gt;There are 40+ apps I mentioned in the below article. All tools are free to use (or freemium with a generous free version), and many of them are open-source (source code links are provided where applicable).&lt;/p&gt;

&lt;p&gt;Some of my favorite tools are Ditto clipboard manager, QuickLook, Clover, ImageGlass, ShareX, and Notepad2-mod.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gourav.io/blog/windows-free-apps" rel="noopener noreferrer"&gt;https://gourav.io/blog/windows-free-apps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;what are your favorite apps for Windows?&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tooling</category>
      <category>opensource</category>
      <category>windows</category>
    </item>
    <item>
      <title>Top AutoHotkey scripts to use Windows like a pro</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Tue, 18 Jan 2022 18:48:35 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/top-autohotkey-scripts-to-use-windows-like-a-pro-3mm4</link>
      <guid>https://dev.to/gorvgoyl/top-autohotkey-scripts-to-use-windows-like-a-pro-3mm4</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on my &lt;a href="https://gourav.io/blog/autohotkey-scripts-windows" rel="noopener noreferrer"&gt;Blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's AutoHotkey
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.autohotkey.com" rel="noopener noreferrer"&gt;AHK&lt;/a&gt; is an &lt;a href="https://github.com/Lexikos/AutoHotkey_L" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; scripting software for Windows that is used to automate repetitive tasks, remap keys, build small utility tools, etc. You create scripts that would do the tasks for you. It's an extremely lightweight app (~ 2MB RAM) and works on old and newer versions of windows.&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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Fautohotkey_ram-ZEZOMYPE.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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Fautohotkey_ram-ZEZOMYPE.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to set up and run
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Download and install main program (one-time step) &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;https://www.autohotkey.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Download a script (&lt;code&gt;.ahk&lt;/code&gt;) or copy-paste script content in a text file and then rename it with &lt;code&gt;.ahk&lt;/code&gt; extension, e.g., &lt;code&gt;my-script.ahk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To run the script: Right-click -&amp;gt; &lt;code&gt;Run script&lt;/code&gt;.
You can also run scripts by double-click or do right-click -&amp;gt;&lt;code&gt;Open with&lt;/code&gt; -&amp;gt; &lt;code&gt;AutoHotkey&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Bonus: you can right-click and &lt;code&gt;Compile script&lt;/code&gt; to make it a standalone &lt;code&gt;.exe&lt;/code&gt; program that would run without installing AutoHotkey software on a computer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Autorun script at startup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open startup folder: open &lt;code&gt;Run&lt;/code&gt; window by &lt;code&gt;Win+R&lt;/code&gt; and then write &lt;code&gt;shell:startup&lt;/code&gt; and enter.&lt;/li&gt;
&lt;li&gt;It'll open explorer at something like this path: &lt;code&gt;C:\Users\{username}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy a script (&lt;code&gt;*.ahk&lt;/code&gt;) -&amp;gt; go to that &lt;code&gt;Startup&lt;/code&gt; folder -&amp;gt; right-click and select &lt;code&gt;Paste shortcut&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Useful Scripts
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You can see all scripts here: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows" rel="noopener noreferrer"&gt;https://github.com/GorvGoyl/Autohotkey-Scripts-Windows&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Look up selected text
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/look_up.ahk" rel="noopener noreferrer"&gt;look_up.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;use &lt;code&gt;alt+g&lt;/code&gt; to open selected text in the browser and do a google search or visit the site (if it's url). It's one of the most frequent scripts I use on a regular basis. Especially to quickly google some error from the terminal when programming. Works everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assign a different shortcut:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To assign a different shortcut, replace &lt;code&gt;!g&lt;/code&gt; (here &lt;code&gt;!&lt;/code&gt; means &lt;code&gt;Alt&lt;/code&gt; so &lt;code&gt;!g&lt;/code&gt; = &lt;code&gt;Alt+G&lt;/code&gt;) in the script with your desired &lt;a href="https://www.autohotkey.com/docs/Hotkeys.htm#Symbols" rel="noopener noreferrer"&gt;key combo&lt;/a&gt; and run again. All running scripts can be found in the Windows tray menu.&lt;/p&gt;

&lt;p&gt;To use a different browser instead of Microsoft Edge, Add its path instead of &lt;code&gt;C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe&lt;/code&gt; in the script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Win key as mouse left-click
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/mouseless.ahk" rel="noopener noreferrer"&gt;mouseless.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This little script has been a game-changer for me. I don't like to carry a mouse around, and my HP laptop touchpad isn't much responsive, so I needed a better alternative to performing left-click. I realized I don't use the left &lt;code&gt;Win&lt;/code&gt; key as much, so I modified its action to do left-click instead (using left-thumb). Once you get the hang of it, I assure you you'll do clicks with godspeed.&lt;/p&gt;

&lt;p&gt;I still needed the &lt;code&gt;Win&lt;/code&gt; key, so I replaced the rarely used &lt;code&gt;right Ctrl&lt;/code&gt; key as &lt;code&gt;Win&lt;/code&gt; key.&lt;/p&gt;

&lt;p&gt;To sum-up:&lt;br&gt;&lt;br&gt;
Win → Mouse Left-click&lt;br&gt;&lt;br&gt;
Right-Ctrl → Win&lt;/p&gt;

&lt;h3&gt;
  
  
  Show notification on low battery or when fully charged
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/battery_alert.ahk" rel="noopener noreferrer"&gt;battery_alert.ahk&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keeping your laptop constantly plugged in shortens the battery life!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the battery is below 30% and the charger is not plugged in, it'll show a silent notification on the bottom-right corner to plug in the charger. Notification will pop up every few minutes until you take action.&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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Fbattery_alert_low-WUVTAXSK.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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Fbattery_alert_low-WUVTAXSK.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, if the laptop is charged and the charger is still plugged in, it'll show a silent notification on the bottom-right corner to remove the charger. Notification will pop up every few minutes until you take action.&lt;/p&gt;

&lt;p&gt;![&lt;a href="https://gourav.io/img/blog/autohotkey-scripts-windows/battery_alert_charged-2PTA3EUI.png" rel="noopener noreferrer"&gt;https://gourav.io/img/blog/autohotkey-scripts-windows/battery_alert_charged-2PTA3EUI.png&lt;/a&gt;]&lt;/p&gt;

&lt;h3&gt;
  
  
  Show popup to transform text
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/ctrl_caps_as_case_change.ahk" rel="noopener noreferrer"&gt;ctrl_caps_as_case_change.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;ctrl+capslock&lt;/code&gt; to invoke a handy transform text menu on selected text e.g., convert text to UPPERCASE/lowercase/Title Case etc. Press &lt;code&gt;esc&lt;/code&gt; to close the menu.&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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Ftransform_text_menu-4XYAPFYU.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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Ftransform_text_menu-4XYAPFYU.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Show Windows switcher with capslock key
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/caps_as_window_switcher.ahk" rel="noopener noreferrer"&gt;caps_as_window_switcher.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't use &lt;code&gt;capslock&lt;/code&gt; key much, you could replace it to show Windows switcher (e.g., Alt + Tab) instead. You'd still be able to turn on/off capslock with &lt;code&gt;shift+capslock&lt;/code&gt; combo.&lt;/p&gt;

&lt;p&gt;To sum-up:&lt;br&gt;&lt;br&gt;
Capslock → Alt+Tab&lt;br&gt;&lt;br&gt;
Shift+Capslock → Capslock&lt;/p&gt;

&lt;h3&gt;
  
  
  Create new text file here
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/create_file_here.ahk" rel="noopener noreferrer"&gt;create_file_here.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Windows has a shortcut (&lt;code&gt;ctrl+shft+n&lt;/code&gt;) to create an empty folder at the current location but not for creating a new file. So, I made a script to do exactly that. Use &lt;code&gt;ctrl+shift+m&lt;/code&gt; to create an empty text file (NewFile.txt) at the current folder location in file explorer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open PowerShell here
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/open_shell_here.ahk" rel="noopener noreferrer"&gt;open_shell_here.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;ctrl+shift+p&lt;/code&gt; to open PowerShell with the current folder path in file explorer.&lt;/p&gt;

&lt;h3&gt;
  
  
  In-line calculator
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/in-line-calculator/in-line%20calculator.ahk" rel="noopener noreferrer"&gt;in-line calculator.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Activate the calculator by &lt;code&gt;=&lt;/code&gt; then write your equation and finally type &lt;code&gt;=&lt;/code&gt; again to get the calculation result. Works everywhere.&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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Fin_line_calculator-FMSVB6T7.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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2Fin_line_calculator-FMSVB6T7.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;#&lt;/code&gt; key at the end instead of &lt;code&gt;=&lt;/code&gt; to keep the equation and the result (output: &lt;code&gt;7*5+5 = 40&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;See more info in &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/in-line-calculator/readme.md" rel="noopener noreferrer"&gt;README file&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drag window without activating it
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/move-inactive-window-alt-leftclick/MoveInactiveWin.ahk" rel="noopener noreferrer"&gt;MoveInactiveWin.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hold &lt;code&gt;alt+right-click&lt;/code&gt; to move a window without activating it.&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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2FMoveInactiveWinScreen-G52KOQFK.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%2Fgourav.io%2Fimg%2Fblog%2Fautohotkey-scripts-windows%2FMoveInactiveWinScreen-G52KOQFK.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Disable zoom when &lt;code&gt;ctrl+scroll&lt;/code&gt; in the browser
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/disable_scroll_zoom_edge.ahk" rel="noopener noreferrer"&gt;disable_scroll_zoom_edge.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Disable zoom when doing ctrl+scroll in Edge browser. To use different application, replace &lt;code&gt;Microsoft Edge&lt;/code&gt; with other application title in the ahk script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hot corner
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/left_edge_as_window_switcher.ahk" rel="noopener noreferrer"&gt;left_edge_as_window_switcher.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trigger &lt;code&gt;Alt+Tab&lt;/code&gt; (Window switcher) when the mouse is on the left edge of the screen. Keep the mouse there to tab through the other windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pin window at the top
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/pin_window.ahk" rel="noopener noreferrer"&gt;pin_window.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;ctrl+alt+p&lt;/code&gt; to pin/unpin current window at top. Super handy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Win key to show taskbar
&lt;/h3&gt;

&lt;p&gt;script: &lt;a href="https://github.com/GorvGoyl/Autohotkey-Scripts-Windows/blob/master/win_key_to_show_taskbar.ahk" rel="noopener noreferrer"&gt;win_key_to_show_taskbar.ahk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It shows the taskbar only when the &lt;code&gt;Win&lt;/code&gt; key is pressed; otherwise, it stays hidden.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👋 Comment below which script did you like the most :)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;Thanks for reading. Connect with me on &lt;a href="https://twitter.com/GorvGoyl" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I made a git cheatsheet of useful commands like reverting commits, work between branches, manage PRs, and much more.</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Tue, 02 Nov 2021 11:07:04 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/i-made-a-git-cheatsheet-of-useful-commands-like-reverting-commits-work-between-branches-manage-prs-and-much-more-379k</link>
      <guid>https://dev.to/gorvgoyl/i-made-a-git-cheatsheet-of-useful-commands-like-reverting-commits-work-between-branches-manage-prs-and-much-more-379k</guid>
      <description>&lt;p&gt;When I collaborate with others using Git, I often have to google to find right git commands for various situations.&lt;/p&gt;

&lt;p&gt;Situations like how to pull changes without committing local files, save uncommitted changes in current branch and switch, add new changed to last commit, reset my local branch to main, revert last commit from local and remote, etc.&lt;/p&gt;

&lt;p&gt;So, I decided to write these down at one place so that it's easier for me (and hopefully others) to recall and use.&lt;/p&gt;

&lt;p&gt;here's the git cheatsheet: &lt;a href="https://gourav.io/blog/git-cheatsheet" rel="noopener noreferrer"&gt;https://gourav.io/blog/git-cheatsheet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's an &lt;a href="https://github.com/GorvGoyl/Personal-Site-Gourav.io/blob/main/content/blog/git-cheatsheet/index.md" rel="noopener noreferrer"&gt;open-source cheatsheet&lt;/a&gt; so contributions are more than welcome to improve it and add more useful commands 🙏.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>git</category>
      <category>github</category>
    </item>
    <item>
      <title>I made a cheatsheet for Next.js to add debugging, dev url, Tailwind, SEO, ESLint with Typescript, analytics, sitemap, etc.</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Thu, 21 Oct 2021 10:25:41 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/i-made-a-cheatsheet-for-nextjs-to-add-debugging-dev-url-tailwind-seo-eslint-with-typescript-analytics-sitemap-etc-408e</link>
      <guid>https://dev.to/gorvgoyl/i-made-a-cheatsheet-for-nextjs-to-add-debugging-dev-url-tailwind-seo-eslint-with-typescript-analytics-sitemap-etc-408e</guid>
      <description>&lt;p&gt;I've been working on different Next.js projects for sometime and whenever I need to setup a new Next.js project I follow common steps like adding ESLint with Typescript support, debugging, SEO, Tailwind, SCSS support, Sitemap, etc.&lt;/p&gt;

&lt;p&gt;Now I'm sharing that guide to all: &lt;a href="https://gourav.io/blog/nextjs-cheatsheet" rel="noopener noreferrer"&gt;https://gourav.io/blog/nextjs-cheatsheet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's a &lt;a href="https://github.com/GorvGoyl/Personal-Site-Gourav.io/blob/main/content/blog/nextjs-cheatsheet/index.md" rel="noopener noreferrer"&gt;open-source cheatsheet&lt;/a&gt; so contributions are more than welcome to grow this even further 🙏.&lt;/p&gt;

&lt;p&gt;PS. I initially thought of creating a starter template but maintaining that is difficult over time and adds lots of abstraction that hinders learning experience.&lt;/p&gt;




&lt;p&gt;Thanks for reading. Connect with me on &lt;a href="https://twitter.com/GorvGoyl" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>react</category>
    </item>
    <item>
      <title>Why should we care about NFT? Here's why</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Mon, 19 Apr 2021 10:35:07 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/let-s-break-down-nft-for-the-rest-of-us-1eia</link>
      <guid>https://dev.to/gorvgoyl/let-s-break-down-nft-for-the-rest-of-us-1eia</guid>
      <description>&lt;p&gt;NFT has been a hype for few months but its use case is still not clear to many people. I'll try to explain it using a simple example.&lt;/p&gt;

&lt;p&gt;Suppose you made digital art (like painting) and you want to sell it online.&lt;/p&gt;

&lt;p&gt;You upload the image file to an e-comm site like OpenSea. This file now has a fancy term called NFT (non-fungible token). You suddenly upped your game amongst your peers.&lt;/p&gt;

&lt;p&gt;You set its price (in cryptocurrency like Bitcoin). You can also put a bid amount to do an auction, a good approach if you're Banksy's cousin.&lt;/p&gt;

&lt;p&gt;It's listed as a &lt;strong&gt;single&lt;/strong&gt; item on the platform so only one person can buy it. This means he can &lt;strong&gt;download&lt;/strong&gt; the image file after paying in crypto.&lt;/p&gt;

&lt;p&gt;Once sold, you get profit (in cryptocurrency). pop a bottle of champagne.&lt;/p&gt;

&lt;p&gt;Whoever buys it now owns it. That means she/he can now sell it at &lt;strong&gt;higher price&lt;/strong&gt; on the same platform. He can also put it as wallpaper on his Mac.&lt;/p&gt;

&lt;p&gt;He gets profit when somebody else buys it. He pops a bottle of champagne now.&lt;/p&gt;

&lt;p&gt;This trading cycle continues.&lt;/p&gt;

&lt;p&gt;Few points to remember: &lt;br&gt;
&lt;strong&gt;Everyone&lt;/strong&gt; can see the entire purchase history (sold price, date, buyer, etc) of this image file (aka NFT). &lt;strong&gt;Nobody&lt;/strong&gt; can modify the purchase history. This open purchase history is called Public Ledger. Tech behind this public ledger is called Blockchain.&lt;/p&gt;

&lt;p&gt;It's not limited to image files. you can sell any digital content (audio, video, pdf, etc).&lt;/p&gt;

&lt;p&gt;Copies of content behind NFT can be distributed off-platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now, why would someone buy an NFT?
&lt;/h3&gt;

&lt;p&gt;I could think of 2 main reasons for someone to buy/sell something as an NFT.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Suppose, a person named Rick saw an NFT and looked at the purchase history. He noticed that it's going up for ex: $100 -&amp;gt; $200 -&amp;gt; $500 -&amp;gt; $700. He predicts that this would go further up so he buys it at the current price of $700 and puts a selling price of $1000 hoping someone else would buy. Here, the value is not in the file content but the attached &lt;strong&gt;immutable&lt;/strong&gt; price history (aka blockchain). In nutshell, the purpose is trading. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Suppose, Morty is a super-fan of Billie Eilish, she uploads her latest album cover as NFT and tweets this is the original. Morty being a nerd bought this NFT asap and gives proof to his other nerd friends by showing the purchase history. The purpose could be to financially support the creator, have (authentic) digital collectibles, etc.&lt;br&gt;
Kings of Leon sold their latest album as NFT and made over $2 million.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This covers the basics of NFT.  I hope you enjoyed reading. Connect with me on &lt;a href="https://twitter.com/GorvGoyl" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/gorvgoyl/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>nft</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>My simple Github project went Viral 🚀</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Tue, 13 Apr 2021 16:03:15 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/my-simple-github-project-went-viral-5g7c</link>
      <guid>https://dev.to/gorvgoyl/my-simple-github-project-went-viral-5g7c</guid>
      <description>&lt;p&gt;Last month (Mar'21), I made a simple project which got spread in various tech communities and social media. On Github, It reached from 0 to 4k+ stars and 200+ forks within 7 days. Github featured it in &lt;em&gt;Trending repositories of day&lt;/em&gt; section for straight 5 days or so.&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F1.jpg" 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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F1.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
Trending on Github - 13 Mar'21



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Clone Wars&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
70+ open-source clones or alternatives of popular sites like Airbnb, Amazon, Instagram, Netflix, Tiktok, etc. List contains source code, demo links, tech stack, and, GitHub stars count.  &lt;/p&gt;

&lt;p&gt;Project link: &lt;a href="https://gourav.io/clone-wars" rel="noopener noreferrer"&gt;https://gourav.io/clone-wars&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Github link: &lt;a href="https://github.com/gorvgoyl/clone-wars" rel="noopener noreferrer"&gt;https://github.com/gorvgoyl/clone-wars&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Motivation behind this project
&lt;/h2&gt;

&lt;p&gt;I'm a techie and many a time I lurk in popular programming communities on Reddit like r/webdev, r/reactjs, etc. to see what other devs are building or if any new JS framework is popping up. I noticed many devs were making clones of popular sites like Instagram, Trello, Spotify, etc. as part of their learning purpose, and they were sharing it with others to get feedback in terms of code quality and best practices.&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F11.jpg" 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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F11.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
devs sharing their projects in r/reactjs



&lt;p&gt;These clones were scattered all over the communities. So, I thought why not create a single list of all these clones which people can bookmark and revisit later for whatever purpose they need it for. Honestly, I wasn't entirely sure at that time whether it would provide any good value to others or not. So, there was a way to find out that is to build it myself!&lt;/p&gt;

&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Scrapping Reddit
&lt;/h3&gt;

&lt;p&gt;I wanted to get all posts that contain the "clone" keyword. I initially did it with default reddit search &lt;code&gt;reddit.com/r/reactjs/search/?q=clone&amp;amp;source=recent&amp;amp;restrict_sr=1&amp;amp;sort=new&lt;/code&gt;, (means &lt;em&gt;look for all posts in &lt;code&gt;reactjs&lt;/code&gt; subreddit with "clone" keyword and sort by new&lt;/em&gt;). It returned all posts, but that also included low-quality posts with 0 upvotes, questions on how to build a specific clone, etc. It would be a headache figuring out good clone projects from that dump. So, I used &lt;a href="https://redditsearch.io/" rel="noopener noreferrer"&gt;redditsearch.io&lt;/a&gt; instead, which provides advanced Reddit filtering like return posts that have at least 10 upvotes, posted during a specific timeline, etc.&lt;/p&gt;

&lt;p&gt;Next, I made a list of all these clones, their Github repo, demo links, tech stack. It was manual work.&lt;/p&gt;

&lt;p&gt;Additionally, I googled "open-source alternatives" and found some fully-functional clones of Slack, Airtable, Bit.ly, Evernote, Google analytics, etc. I added these to the list.&lt;/p&gt;

&lt;p&gt;So, now there are 2 kinds of projects on the list. The first ones look quite similar (UI-wise) but aren't fully-functional and the other ones which are fully-functional but UI is different (to avoid copyright issues, etc).&lt;/p&gt;

&lt;p&gt;BTW, I named my project after Star Wars 2008 TV Series: "The Clone Wars" and also kept the similar color scheme of OG image.&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F2.jpg" 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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F2.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
Star Wars 2008 TV Series: The Clone Wars



&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F3.jpg" 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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F3.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
Clone Wars: Github project



&lt;h3&gt;
  
  
  2. Pretty view of table
&lt;/h3&gt;

&lt;p&gt;I've worked with markdown before, but it was the first time I was working with markdown table and realized table view sucks on Github project page. Especially, if it's a long table with multiple columns. I needed to make it look better (sticky header) which meant I needed to deploy this project somewhere else. I still needed it to be on Github so that others can collaborate easily. I decided to host it on my personal site &lt;a href="https://gourav.io/" rel="noopener noreferrer"&gt;https://gourav.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My site is built using NextJS, and I was already using markdown (mdx) to write blog posts, so it was just a matter of copy-pasting markdown file from my Github project to new page &lt;a href="https://gourav.io/clone-wars" rel="noopener noreferrer"&gt;https://gourav.io/clone-wars&lt;/a&gt;. And on top of it, I use Tailwind CSS with "typography" plugin which makes tables pleasing to read along with other text.&lt;/p&gt;

&lt;p&gt;I thought of automating it to the next level i.e. if any change happens to the Github project or someone's PR gets merged, update the same on my site &lt;a href="https://gourav.io/clone-wars" rel="noopener noreferrer"&gt;https://gourav.io/clone-wars&lt;/a&gt;. But, decided not to over-engineer it as changes weren't that frequent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it Viral
&lt;/h2&gt;

&lt;p&gt;I posted in 2-3 subreddits, &lt;a href="https://dev.to/gorvgoyl/i-made-a-list-of-70-open-source-clones-of-sites-like-airbnb-tiktok-netflix-spotify-etc-great-for-learning-purpose-3oel"&gt;dev.to&lt;/a&gt; and it took off 🚀&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F4.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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F4.png"&gt;&lt;/a&gt;&lt;/p&gt;
reddit.com/r/reactjs



&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F5.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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F5.png"&gt;&lt;/a&gt;&lt;/p&gt;
reddit.com/r/webdev



&lt;h2&gt;
  
  
  After effects
&lt;/h2&gt;

&lt;p&gt;Once the project gained some popularity many developers started raising PR to add their clone projects to the list. When I started it had around ~75 clones, but now it's more than 120+ and I still get new PR every now and then.&lt;/p&gt;

&lt;p&gt;I got to know from a friend that it was picked by &lt;em&gt;React Newsletter&lt;/em&gt;. Such a serendipitous moment.&lt;/p&gt;

&lt;p&gt;People were tweeting about &lt;em&gt;Clone Wars&lt;/em&gt;. @nickbulljs tweeted a neat idea for devs who are looking to get hired.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1373573194846765061-458" src="https://platform.twitter.com/embed/Tweet.html?id=1373573194846765061"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1373573194846765061-458');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1373573194846765061&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I got 150+ new followers after this tweet :o&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And one person donated $5 from &lt;em&gt;BuyMeACoffee&lt;/em&gt; link I put on the project. Love you stranger.&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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F6.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%2Fgourav.io%2F_next%2Fstatic%2Fmedia%2Fpages%2Fblog%2Fmy-simple-github-project-went-viral%2F6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Within 30 days of launch, 40k+ people came to my personal site and viewed my project (80k+ views).&lt;/p&gt;

&lt;p&gt;You can see users insights at the end of the &lt;a href="https://gourav.io/blog/my-simple-github-project-went-viral" rel="noopener noreferrer"&gt;article on my blog&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Thanks for reading. Connect with me on &lt;a href="https://twitter.com/GorvGoyl" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/gorvgoyl/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>I made a list of 70+ open-source clones of sites like Airbnb, Tiktok, Netflix, Spotify, etc. Great for learning purpose!</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Tue, 09 Mar 2021 12:17:25 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/i-made-a-list-of-70-open-source-clones-of-sites-like-airbnb-tiktok-netflix-spotify-etc-great-for-learning-purpose-3oel</link>
      <guid>https://dev.to/gorvgoyl/i-made-a-list-of-70-open-source-clones-of-sites-like-airbnb-tiktok-netflix-spotify-etc-great-for-learning-purpose-3oel</guid>
      <description>&lt;p&gt;I curated a list of 70+ open-source clones of popular sites like Airbnb, Amazon, Instagram, Netflix, Tiktok, Spotify, Trello, WhatsApp, YouTube, etc. &lt;br&gt;
List contains source code, demo links, tech stack, and, GitHub stars count. Great for learning purpose!&lt;/p&gt;

&lt;p&gt;More open-source contributions are welcome to grow this list.&lt;/p&gt;

&lt;p&gt;GitHub link: &lt;a href="https://github.com/GorvGoyl/Clone-Wars" rel="noopener noreferrer"&gt;https://github.com/GorvGoyl/Clone-Wars&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pretty view: &lt;a href="https://gourav.io/clone-wars" rel="noopener noreferrer"&gt;https://gourav.io/clone-wars&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was building this list for a while... Please share it with others 🙏&lt;/p&gt;

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




&lt;p&gt;I share my learnings about startups, tech, and life on Twitter &lt;a href="https://twitter.com/GorvGoyl" rel="noopener noreferrer"&gt;@GorvGoyl&lt;/a&gt; &lt;/p&gt;

</description>
      <category>react</category>
      <category>node</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I received first donation on my open-source side project and it felt great 😍</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Sat, 28 Nov 2020 11:40:06 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/i-received-first-donation-on-my-open-source-side-project-and-it-felt-great-5g4f</link>
      <guid>https://dev.to/gorvgoyl/i-received-first-donation-on-my-open-source-side-project-and-it-felt-great-5g4f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;You can read the updated version on &lt;a href="https://gourav.io/blog/first-donation-on-open-source-side-project" rel="noopener noreferrer"&gt;https://gourav.io/blog/first-donation-on-open-source-side-project&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I made a plugin for VS Code a while back (3 yrs) for my own use. Other people started using it so I recently decided to put a donate button in plugin description and see what happens. And guess what somebody donated 5$.&lt;/p&gt;

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

&lt;p&gt;I know I know it's not a big amount but somebody put an effort to make that transaction means he cares about it and found it useful.&lt;/p&gt;

&lt;p&gt;This is the plugin I'm talking about. It adds new toolbar buttons to VSCode: &lt;a href="https://github.com/GorvGoyl/Shortcut-Menu-Bar-VSCode-Extension" rel="noopener noreferrer"&gt;https://github.com/GorvGoyl/Shortcut-Menu-Bar-VSCode-Extension&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Thank you for reading, I would love to connect with you on Twitter &lt;a href="https://twitter.com/intent/follow?user_id=325435736" rel="noopener noreferrer"&gt;@GorvGoyl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>showdev</category>
      <category>vscode</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Quickest way to open any Github repo in Codesandbox</title>
      <dc:creator>Gourav</dc:creator>
      <pubDate>Wed, 22 Apr 2020 11:48:22 +0000</pubDate>
      <link>https://dev.to/gorvgoyl/quickest-way-to-open-any-github-repo-in-codesandbox-2jjp</link>
      <guid>https://dev.to/gorvgoyl/quickest-way-to-open-any-github-repo-in-codesandbox-2jjp</guid>
      <description>&lt;p&gt;Quickly open any Github repo in Codesandbox:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to a repo on GitHub.com&lt;/li&gt;
&lt;li&gt;Replace url github.com with url githubbox.com&lt;/li&gt;
&lt;li&gt;There's no step three!&lt;/li&gt;
&lt;/ol&gt;

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




&lt;p&gt;Thank you for reading, I would love to connect with you on Twitter &lt;a href="https://twitter.com/intent/follow?user_id=325435736" rel="noopener noreferrer"&gt;@GorvGoyl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>codesandbox</category>
    </item>
  </channel>
</rss>
