<?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: Muhammad Aqib Bin Azam</title>
    <description>The latest articles on DEV Community by Muhammad Aqib Bin Azam (@muhammadaqib86).</description>
    <link>https://dev.to/muhammadaqib86</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%2F2757553%2F982a36b4-970b-4ae9-a7da-ebd63bb009fd.jpg</url>
      <title>DEV Community: Muhammad Aqib Bin Azam</title>
      <link>https://dev.to/muhammadaqib86</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muhammadaqib86"/>
    <language>en</language>
    <item>
      <title>Lost Your Private Key for Your SSL Certificate? Here is How to Fix It in 10 Minutes</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Fri, 10 Apr 2026 17:31:04 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/lost-your-private-key-for-your-ssl-certificate-here-is-how-to-fix-it-in-10-minutes-onc</link>
      <guid>https://dev.to/muhammadaqib86/lost-your-private-key-for-your-ssl-certificate-here-is-how-to-fix-it-in-10-minutes-onc</guid>
      <description>&lt;h2&gt;
  
  
  🔥 The Situation
&lt;/h2&gt;

&lt;p&gt;You bought an SSL certificate. You downloaded the &lt;code&gt;.crt&lt;/code&gt; file. You are ready to install it.&lt;/p&gt;

&lt;p&gt;Then you hit the wall.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Where is the private key?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You check the zip file. No key.&lt;br&gt;
You check the CA portal. No download button.&lt;br&gt;
You check your emails. Nothing.&lt;/p&gt;

&lt;p&gt;Panic starts to creep in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here is the truth:&lt;/strong&gt; Your Certificate Authority (CA) never had your private key. And they never will.&lt;/p&gt;

&lt;p&gt;But do not worry. You do not need to buy a new certificate. You do not need to call support. You just need &lt;strong&gt;10 minutes&lt;/strong&gt; and this guide.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 The Mindset Shift
&lt;/h2&gt;

&lt;p&gt;Here is what most people get wrong:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you think&lt;/th&gt;
&lt;th&gt;What is actually true&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The CA gives me the private key&lt;/td&gt;
&lt;td&gt;The CA only gives the public certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I can download the key from the portal&lt;/td&gt;
&lt;td&gt;The key is generated on YOUR server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I lost the key = I buy a new cert&lt;/td&gt;
&lt;td&gt;You can REKEY the existing cert&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The private key is like the key to your house. The CA is just the locksmith who certifies that the lock works. The locksmith never keeps a copy of your key.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you understand this, the fix is simple.&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠️ What You Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Access to your CA account (where you bought the SSL)&lt;/li&gt;
&lt;li&gt;OpenSSL (5 seconds to check: run &lt;code&gt;openssl version&lt;/code&gt; in your terminal)&lt;/li&gt;
&lt;li&gt;10 minutes&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  📋 The Fix in 4 Steps
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Generate a New Key and CSR on Your Machine
&lt;/h3&gt;

&lt;p&gt;Open your terminal and run these two commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl genrsa &lt;span class="nt"&gt;-out&lt;/span&gt; yourdomain.key 2048
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; yourdomain.key &lt;span class="nt"&gt;-out&lt;/span&gt; yourdomain.csr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second command will ask you a few questions. Here is the cheat sheet:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Your answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Common Name (CN)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;yourdomain.com&lt;/code&gt; (exact domain)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Country&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;US&lt;/code&gt; (or your 2-letter code)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State&lt;/td&gt;
&lt;td&gt;Your state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;City&lt;/td&gt;
&lt;td&gt;Your city&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Organization&lt;/td&gt;
&lt;td&gt;Your company name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything else&lt;/td&gt;
&lt;td&gt;Just press Enter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Boom.&lt;/strong&gt; You now have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;yourdomain.key&lt;/code&gt; → Your brand new private key (GUARD THIS WITH YOUR LIFE)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yourdomain.csr&lt;/code&gt; → The request you will send to your CA&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Step 2: Copy Your CSR
&lt;/h3&gt;

&lt;p&gt;Run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;yourdomain.csr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy everything from &lt;code&gt;-----BEGIN CERTIFICATE REQUEST-----&lt;/code&gt; to &lt;code&gt;-----END CERTIFICATE REQUEST-----&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Rekey Your Certificate with Your CA
&lt;/h3&gt;

&lt;p&gt;Log into your CA account.&lt;/p&gt;

&lt;p&gt;Look for one of these buttons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Rekey"&lt;/strong&gt; (GoDaddy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Reissue"&lt;/strong&gt; (DigiCert, Comodo)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Regenerate"&lt;/strong&gt; (Others)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Paste your CSR into the box. Submit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait 5–10 minutes.&lt;/strong&gt; Check your email. Your new certificate is ready.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Download and Combine
&lt;/h3&gt;

&lt;p&gt;Download the new certificate files from your CA. You will get something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;yourdomain.crt&lt;/code&gt; (your certificate)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ca_bundle.crt&lt;/code&gt; or &lt;code&gt;intermediate.crt&lt;/code&gt; (the chain)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now run the magic command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs12 &lt;span class="nt"&gt;-export&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; yourdomain.pfx &lt;span class="nt"&gt;-inkey&lt;/span&gt; yourdomain.key &lt;span class="nt"&gt;-in&lt;/span&gt; yourdomain.crt &lt;span class="nt"&gt;-certfile&lt;/span&gt; ca_bundle.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will ask for a password. &lt;strong&gt;Set one. Remember it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Done.&lt;/strong&gt; You now have your PFX file with your private key inside.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Verify It Worked
&lt;/h2&gt;

&lt;p&gt;Run this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs12 &lt;span class="nt"&gt;-info&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; yourdomain.pfx &lt;span class="nt"&gt;-noout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enter your password. If you see certificate details without errors, you are golden.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❓ But What If...
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "I have a .p7b file instead of a bundle?"
&lt;/h3&gt;

&lt;p&gt;Convert it first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs7 &lt;span class="nt"&gt;-in&lt;/span&gt; yourdomain.p7b &lt;span class="nt"&gt;-print_certs&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; bundle.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use &lt;code&gt;bundle.crt&lt;/code&gt; as your &lt;code&gt;-certfile&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  "I have multiple domains (UCC/SAN certificate)?"
&lt;/h3&gt;

&lt;p&gt;When you rekey in your CA portal, look for a section called &lt;strong&gt;"Subject Alternative Names"&lt;/strong&gt; or &lt;strong&gt;"SANs"&lt;/strong&gt;. Add all your domains there:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;api.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;portal.yourdomain.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "My CA rejected my CSR?"
&lt;/h3&gt;

&lt;p&gt;Make sure your &lt;strong&gt;Common Name (CN)&lt;/strong&gt; exactly matches your domain. No &lt;code&gt;www.&lt;/code&gt; unless that is the exact domain you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  "I lost the private key I just generated?"
&lt;/h3&gt;

&lt;p&gt;You cannot recover it. Just run Step 1 again and rekey one more time.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚫 What NOT to Do
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Don't&lt;/th&gt;
&lt;th&gt;✅ Do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Buy a new certificate&lt;/td&gt;
&lt;td&gt;Rekey your existing one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask your CA for the private key&lt;/td&gt;
&lt;td&gt;Generate your own key pair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ignore the bundle file&lt;/td&gt;
&lt;td&gt;Include it in your PFX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Share your &lt;code&gt;.key&lt;/code&gt; file with anyone&lt;/td&gt;
&lt;td&gt;Keep it secret, keep it safe&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📦 Files Cheat Sheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Can you share it?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourdomain.key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your private key&lt;/td&gt;
&lt;td&gt;🔴 &lt;strong&gt;NEVER&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourdomain.csr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The request you send to CA&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourdomain.crt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your public certificate&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ca_bundle.crt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Intermediate certificates&lt;/td&gt;
&lt;td&gt;🟢 Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourdomain.pfx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Key + cert combined&lt;/td&gt;
&lt;td&gt;🟡 Only if password protected&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🎯 The Bottom Line
&lt;/h2&gt;

&lt;p&gt;You did not lose your private key.&lt;/p&gt;

&lt;p&gt;You never had it from your CA.&lt;/p&gt;

&lt;p&gt;And that is actually a &lt;strong&gt;good thing&lt;/strong&gt; for security.&lt;/p&gt;

&lt;p&gt;The fix is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate a new key + CSR&lt;/li&gt;
&lt;li&gt;Rekey your certificate with your CA&lt;/li&gt;
&lt;li&gt;Download the new cert&lt;/li&gt;
&lt;li&gt;Combine into a PFX&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total time: 10 minutes.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 The Last Word
&lt;/h2&gt;

&lt;p&gt;Every developer hits this wall at least once. The first time, it feels like a disaster. The second time, it is a 10-minute task.&lt;/p&gt;

&lt;p&gt;Now you know.&lt;/p&gt;

&lt;p&gt;Save this guide. Share it with your team. And the next time someone says &lt;em&gt;"I lost my private key"&lt;/em&gt;, you can send them here and look like a hero.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Did this save your day?&lt;/strong&gt; Drop a comment. ❤️&lt;/p&gt;

</description>
      <category>ssl</category>
      <category>openssl</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building an Enterprise-Grade Tags Input Component with ShadCN UI + React</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Wed, 03 Sep 2025 09:58:54 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/building-an-enterprise-grade-tags-input-component-with-shadcn-ui-react-39la</link>
      <guid>https://dev.to/muhammadaqib86/building-an-enterprise-grade-tags-input-component-with-shadcn-ui-react-39la</guid>
      <description>&lt;p&gt;Managing tags (skills, categories, labels, etc.) is a &lt;strong&gt;common requirement&lt;/strong&gt; in modern web apps. But most tags input components out there are either too simple or lack flexibility for &lt;strong&gt;enterprise-grade use cases&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, I built a &lt;strong&gt;ShadCN UI Tags Input Component&lt;/strong&gt; — a fully customizable, accessible, and TypeScript-first tags input built on top of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚛️ &lt;strong&gt;React 18+&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;TypeScript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;React Hook Form&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🎞 &lt;strong&gt;Framer Motion&lt;/strong&gt; (smooth animations)&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;ShadCN/UI + TailwindCSS&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post walks you through &lt;strong&gt;why and how&lt;/strong&gt; to use it in your own projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Why Another Tags Input?
&lt;/h2&gt;

&lt;p&gt;The goals were simple:&lt;/p&gt;

&lt;p&gt;✅ Enterprise-grade validation (with React Hook Form)&lt;br&gt;&lt;br&gt;
✅ Seamless keyboard support (Enter/Backspace navigation)&lt;br&gt;&lt;br&gt;
✅ Smooth animations with Framer Motion&lt;br&gt;&lt;br&gt;
✅ ShadCN/UI compatibility out of the box&lt;br&gt;&lt;br&gt;
✅ Fully accessible (ARIA-compliant)  &lt;/p&gt;


&lt;h2&gt;
  
  
  🛠 Installation
&lt;/h2&gt;

&lt;p&gt;You’ll need a few peer dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install lucide-react class-variance-authority clsx tailwind-merge cmdk framer-motion react-hook-form
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add required ShadCN components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx shadcn@latest add form input badge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, copy the Tags Input component into your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp components/tags-input-field.tsx your-project/src/components/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💻 Usage Example
&lt;/h2&gt;

&lt;p&gt;Here’s a minimal setup using &lt;strong&gt;React Hook Form&lt;/strong&gt; + the &lt;code&gt;TagsInputField&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TagsInputField&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/tags-input-field&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-hook-form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;defaultValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FormProvider&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="si"&gt;}&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="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&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;TagsInputField&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"skills"&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Skills"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter your skills"&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="nt"&gt;form&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;FormProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it — you now have a &lt;strong&gt;fully functional tags input&lt;/strong&gt; with validation, ARIA support, and customization options.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Features Breakdown
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Variants &amp;amp; Themes&lt;/strong&gt; – Change size, colors, and layout easily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt; – Built-in error messages via React Hook Form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard Support&lt;/strong&gt; – Add/remove tags with Enter/Backspace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt; – Works natively with ShadCN form, input, and badge components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable&lt;/strong&gt; – Set max tags, prevent duplicates, enable suggestions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt; – ARIA-compliant for screen readers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📚 Full Documentation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://shadcn-tags-input.vercel.app/" rel="noopener noreferrer"&gt;Live Documentation &amp;amp; Demos&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 Wrap Up
&lt;/h2&gt;

&lt;p&gt;If you’re using &lt;strong&gt;ShadCN/UI&lt;/strong&gt; in your React app and need a &lt;strong&gt;production-ready tags input&lt;/strong&gt;, this component will save you tons of boilerplate.&lt;/p&gt;

&lt;p&gt;💡 I’d love feedback and contributions! Check out the GitHub repo here:&lt;br&gt;
🔗 &lt;a href="https://github.com/muhammada86/shadcn-tags-input" rel="noopener noreferrer"&gt;GitHub: ShadCN UI Tags Input&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🔥 Next steps: I’m considering adding &lt;strong&gt;autocomplete suggestions&lt;/strong&gt; and &lt;strong&gt;drag-and-drop reordering&lt;/strong&gt;.&lt;br&gt;
Would that be useful for your use case?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>react</category>
      <category>tailwindcss</category>
      <category>shadcn</category>
    </item>
    <item>
      <title>How to Install Fastlane on macOS for iOS Development</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Sat, 03 May 2025 18:53:49 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/how-to-install-fastlane-on-macos-for-ios-development-5g3f</link>
      <guid>https://dev.to/muhammadaqib86/how-to-install-fastlane-on-macos-for-ios-development-5g3f</guid>
      <description>&lt;p&gt;Fastlane is a powerful open-source tool that simplifies and automates the process of building, testing, and deploying iOS and Android apps. If you're an iOS developer looking to streamline your app deployment workflow, &lt;strong&gt;Fastlane&lt;/strong&gt; is a must-have.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through installing Fastlane on macOS based on the official &lt;a href="https://docs.fastlane.tools/getting-started/ios/setup/" rel="noopener noreferrer"&gt;Fastlane iOS setup docs&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ A Mac running macOS&lt;/li&gt;
&lt;li&gt;✅ Xcode installed with command line tools&lt;/li&gt;
&lt;li&gt;✅ Terminal and command-line basics&lt;/li&gt;
&lt;li&gt;✅ A paid Apple Developer account (required for App Store deployment)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠 Step-by-Step Installation Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🥇 Step 1: Install Xcode Command Line Tools
&lt;/h3&gt;

&lt;p&gt;Fastlane relies on Xcode's CLI tools for building/signing apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcode-select &lt;span class="nt"&gt;--install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If already installed, you'll see a message. To confirm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcode-select &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;span class="c"&gt;# /Applications/Xcode.app/Contents/Developer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🥈 Step 2: Install Fastlane
&lt;/h3&gt;

&lt;p&gt;There are two common methods:&lt;/p&gt;

&lt;h4&gt;
  
  
  Option 1: Using RubyGems (Recommended)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;fastlane &lt;span class="nt"&gt;-NV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sudo&lt;/code&gt;: For admin privileges
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-NV&lt;/code&gt;: Skips documentation for faster install&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Pro Tip:&lt;/strong&gt; Use a &lt;code&gt;Gemfile&lt;/code&gt; with Bundler for team projects:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"https://rubygems.org"&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s2"&gt;"fastlane"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Option 2: Using Homebrew
&lt;/h4&gt;

&lt;p&gt;If you prefer Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;fastlane
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Homebrew may lag behind RubyGems in version updates.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ✅ Step 3: Verify the Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fastlane &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# fastlane 2.x.x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⚙️ Step 4: Initialize Fastlane in Your iOS Project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/your/project
fastlane init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose an option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Option 2: Automate beta deployment to TestFlight
&lt;/li&gt;
&lt;li&gt;Option 4: Manual setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fastlane creates a &lt;code&gt;fastlane/&lt;/code&gt; directory with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Appfile&lt;/code&gt;: Global config (e.g. Apple ID)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Fastfile&lt;/code&gt;: Automation workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Prefer Swift? You can also use &lt;code&gt;Fastlane.swift&lt;/code&gt; (still in beta).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🌐 Step 5: Configure Environment Variables (Optional)
&lt;/h3&gt;

&lt;p&gt;For CI or locale issues, add this to your &lt;code&gt;.zshrc&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LC_ALL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;en_US.UTF-8
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;en_US.UTF-8

&lt;span class="c"&gt;# Then reload:&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧯 Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Permission Errors&lt;/strong&gt;: Use &lt;code&gt;sudo&lt;/code&gt; when needed
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing CLI Tools&lt;/strong&gt;: Run &lt;code&gt;xcode-select --install&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wrong Ruby Version&lt;/strong&gt;: Use &lt;code&gt;rbenv&lt;/code&gt; or &lt;code&gt;rvm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outdated Fastlane&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;RubyGems: &lt;code&gt;sudo gem update fastlane&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Homebrew: &lt;code&gt;brew upgrade fastlane&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 Why Use Fastlane?
&lt;/h2&gt;

&lt;p&gt;Fastlane automates tedious iOS tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📸 Screenshots (&lt;code&gt;snapshot&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🔐 Code signing (&lt;code&gt;match&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🚀 TestFlight/App Store uploads (&lt;code&gt;upload_to_testflight&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🧪 CI/CD integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example Lane
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:beta&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;increment_build_number&lt;/span&gt;
  &lt;span class="n"&gt;build_app&lt;/span&gt;
  &lt;span class="n"&gt;upload_to_testflight&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fastlane beta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📚 Next Steps
&lt;/h2&gt;

&lt;p&gt;Now that you're set up, explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automate screenshots&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;match&lt;/code&gt; for signing&lt;/li&gt;
&lt;li&gt;Configure TestFlight deployments&lt;/li&gt;
&lt;li&gt;Connect Fastlane with GitHub Actions, Jenkins, etc.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;💬 Got questions or tips? Share them in the comments!&lt;/p&gt;

&lt;p&gt;📎 Official docs: &lt;a href="https://docs.fastlane.tools" rel="noopener noreferrer"&gt;https://docs.fastlane.tools&lt;/a&gt;&lt;/p&gt;

</description>
      <category>fastlane</category>
      <category>programming</category>
      <category>automation</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>How to Set the Default Node Version Using NVM in Mac or Windows (with in 60 Seconds)</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Fri, 02 May 2025 15:07:54 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/how-to-set-the-default-node-version-using-nvm-in-mac-or-windows-with-in-60-seconds-2fl7</link>
      <guid>https://dev.to/muhammadaqib86/how-to-set-the-default-node-version-using-nvm-in-mac-or-windows-with-in-60-seconds-2fl7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Ignored by many experienced devs&lt;/strong&gt; — using the wrong Node.js version can silently wreck your app's performance, mess up your builds, or break compatibility with key tooling (like Vite, Webpack, or Next.js). Let’s fix that &lt;em&gt;once and for all&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you're on &lt;strong&gt;macOS&lt;/strong&gt; or &lt;strong&gt;Windows&lt;/strong&gt;, this guide will show you how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a &lt;strong&gt;default Node.js version&lt;/strong&gt; globally using NVM (Node Version Manager)&lt;/li&gt;
&lt;li&gt;Avoid painful bugs caused by version mismatches&lt;/li&gt;
&lt;li&gt;Boost dev workflow consistency across teams and CI&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Why This Matters for Performance
&lt;/h2&gt;

&lt;p&gt;Modern JavaScript tools often rely on specific Node features — like native ESM support, improved garbage collection, or new compression algorithms (e.g. Brotli).&lt;/p&gt;

&lt;p&gt;Using an older or incorrect version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slows down &lt;strong&gt;builds and transpilation&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Causes &lt;strong&gt;unexpected memory leaks&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Breaks &lt;strong&gt;code splitting&lt;/strong&gt; and async imports&lt;/li&gt;
&lt;li&gt;Creates &lt;strong&gt;"works on my machine"&lt;/strong&gt; chaos&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠 Setting the Default Node Version with NVM
&lt;/h2&gt;

&lt;p&gt;Let’s set the default Node version so your system always uses the right one — even across terminals, shells, or reboots.&lt;/p&gt;

&lt;h3&gt;
  
  
  📦 On macOS (using &lt;code&gt;nvm&lt;/code&gt;)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Check installed versions:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Install or use a specific version:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;18
nvm use 18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Set it as default:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;alias &lt;/span&gt;default 18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Now every new shell session will automatically use Node v18.&lt;/p&gt;




&lt;h3&gt;
  
  
  🪟 On Windows (using &lt;code&gt;nvm-windows&lt;/code&gt;)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install from here: &lt;a href="https://github.com/coreybutler/nvm-windows" rel="noopener noreferrer"&gt;https://github.com/coreybutler/nvm-windows&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;List versions:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install and set default:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;18.18.2
nvm use 18.18.2
nvm &lt;span class="nb"&gt;alias &lt;/span&gt;default 18.18.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎯 That’s it. No more accidental upgrades or mysterious toolchain bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Pro Tip: Pin Node Version Per Project
&lt;/h2&gt;

&lt;p&gt;Add a &lt;code&gt;.nvmrc&lt;/code&gt; file to your repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm use
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better yet, add this to your &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; .nvmrc &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; nvm use &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👊 This ensures your terminal always respects the version per project — especially useful in monorepos.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ Common Gotchas
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nvm: command not found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ensure it's loaded in &lt;code&gt;.bash_profile&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong version used in VS Code terminal&lt;/td&gt;
&lt;td&gt;Restart VS Code or point it to your login shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD builds using wrong Node&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;.nvmrc&lt;/code&gt; + &lt;code&gt;nvm install&lt;/code&gt; step in pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🚀 Wrap Up
&lt;/h2&gt;

&lt;p&gt;Setting a consistent, default Node version isn’t just about avoiding bugs — it’s a &lt;strong&gt;performance optimization&lt;/strong&gt;. Your tooling runs faster, your builds stay lean, and your team avoids costly surprises.&lt;/p&gt;

&lt;p&gt;🔁 &lt;strong&gt;Set it once, benefit forever.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Got a Node workflow tip? Share it in the comments — let’s help each other&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>npm</category>
      <category>webdev</category>
      <category>node</category>
    </item>
    <item>
      <title>Integrating PayTabs Payment Gateway with Next.js: A Scalable Approach</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Tue, 29 Apr 2025 12:24:21 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/integrating-paytabs-payment-gateway-with-nextjs-a-scalable-approach-1ka0</link>
      <guid>https://dev.to/muhammadaqib86/integrating-paytabs-payment-gateway-with-nextjs-a-scalable-approach-1ka0</guid>
      <description>&lt;p&gt;This guide will help you implement PayTabs in a &lt;strong&gt;production-ready&lt;/strong&gt; way using:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14+&lt;/strong&gt; (App Router)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; for type safety
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Query&lt;/strong&gt; for API state management
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design Patterns&lt;/strong&gt; (Facade, Adapter, Observer) for clean architecture
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before diving in, ensure you have:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;PayTabs merchant account&lt;/strong&gt; (&lt;a href="https://www.paytabs.com/" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt;)

&lt;ul&gt;
&lt;li&gt;Get your &lt;strong&gt;Profile ID, Server Key, and Region&lt;/strong&gt; from the dashboard
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Next.js 14+&lt;/strong&gt; project with TypeScript
&lt;/li&gt;
&lt;li&gt;Node.js (v18+) installed
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Install required dependencies:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Set up environment variables (&lt;code&gt;.env.local&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PAYTABS_PROFILE_ID=your_profile_id  
PAYTABS_SERVER_KEY=your_server_key  
PAYTABS_REGION=EGY  # Adjust based on your region  
NEXT_PUBLIC_BASE_URL=http://localhost:3000  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 1: Create the PayTabs Service (Backend)
&lt;/h2&gt;

&lt;p&gt;This service acts as a &lt;strong&gt;facade&lt;/strong&gt; over the PayTabs SDK, providing a clean interface for transactions and webhook verification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/services/PayTabsService.ts  &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;paytabs&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;paytabs_pt2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PaymentResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TransactionRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/types/paytabs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayTabsService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;profileID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PAYTABS_PROFILE_ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PAYTABS_SERVER_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PAYTABS_REGION&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;paytabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;profileID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serverKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TransactionRequest&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PaymentResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PaymentResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nx"&gt;paytabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
          &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
        &lt;span class="p"&gt;});&lt;/span&gt;  
      &lt;span class="p"&gt;});&lt;/span&gt;  

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redirect_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Missing redirect_url in PayTabs response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="p"&gt;}&lt;/span&gt;  

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Payment failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  

  &lt;span class="nf"&gt;verifyWebhookSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="c1"&gt;// Implement HMAC-SHA256 verification  &lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Simplified for example  &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;Type Definitions:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// types/paytabs.ts  &lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TransactionRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;cart_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;cart_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;cart_currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;cart_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;return_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;callback_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;customer_details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;street1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nl"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;};&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PaymentResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nl"&gt;tran_ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;redirect_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔄 Step 2: API Route for Transaction Initiation
&lt;/h2&gt;

&lt;p&gt;Create a Next.js API route to handle payment requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/paytabs/create-transaction/route.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;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PayTabsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/lib/services/PayTabsService&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;cart_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`order_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;cart_description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Online Purchase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;cart_currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;cart_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;return_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/payment/success`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;callback_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api/paytabs/webhook`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;customer_details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;};&lt;/span&gt;  

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payTabsService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PayTabsService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;redirect_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tran_ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;payTabsService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;redirect_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tran_ref&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment initiation failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&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;h2&gt;
  
  
  📩 Step 3: Webhook Handling
&lt;/h2&gt;

&lt;p&gt;Set up a webhook endpoint to process real-time payment updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/paytabs/webhook/route.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;NextResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PayTabsService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/lib/services/PayTabsService&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-paytabs-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payTabsService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PayTabsService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payTabsService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verifyWebhookSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  

  &lt;span class="c1"&gt;// Update your database here  &lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Payment status:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payment_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response_status&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Pro Tip:&lt;/strong&gt; Use &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; to test webhooks locally!  &lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Step 4: Frontend Payment Form
&lt;/h2&gt;

&lt;p&gt;Build a React component to initiate payments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/PaymentForm.tsx  &lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMutation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PaymentForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="na"&gt;mutationFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  
      &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/paytabs/create-transaction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;  
    &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redirect_url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Redirect to PayTabs  &lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;john@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="c1"&gt;// ...other fields  &lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
  &lt;span class="p"&gt;};&lt;/span&gt;  

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Processing...&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;Pay Now&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Best Practices for Production
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never expose API keys in client-side code
&lt;/li&gt;
&lt;li&gt;Validate webhook signatures
&lt;/li&gt;
&lt;li&gt;Use HTTPS everywhere
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache API responses with Redis
&lt;/li&gt;
&lt;li&gt;Deploy on Vercel's edge network
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitoring&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log errors with Sentry
&lt;/li&gt;
&lt;li&gt;Track transactions with Datadog
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use PayTabs test cards (&lt;code&gt;4111 1111 1111 1111&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Simulate failed payments
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🔗 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.paytabs.com/en/developers/" rel="noopener noreferrer"&gt;PayTabs API Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/docs/app/building-your-application/routing/route-handlers" rel="noopener noreferrer"&gt;Next.js API Routes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;React Query&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Have questions? Drop them in the comments below!  &lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>paytabs</category>
      <category>paymentintegration</category>
      <category>programming</category>
    </item>
    <item>
      <title>JavaScript Memory Leaks: The Silent Killers and How to Fix Them</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Fri, 25 Apr 2025 17:37:33 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/javascript-memory-leaks-the-silent-killers-and-how-to-fix-them-ik2</link>
      <guid>https://dev.to/muhammadaqib86/javascript-memory-leaks-the-silent-killers-and-how-to-fix-them-ik2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Memory leaks in JavaScript are like slow poison—they creep up unnoticed, degrade performance, and eventually crash your app.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;If your web app gets slower over time, consumes too much RAM, or crashes unexpectedly, you might be dealing with memory leaks. The worst part? They’re often invisible until it’s too late.  &lt;/p&gt;

&lt;p&gt;In this post, we’ll uncover:&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;What causes memory leaks in JS?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;How to detect them using Chrome DevTools&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Common leak patterns (and how to fix them)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Best practices to prevent leaks&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Let’s dive in!  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;What is a Memory Leak?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A memory leak happens when your app &lt;strong&gt;unintentionally retains objects&lt;/strong&gt; that are no longer needed, preventing garbage collection. Over time, this fills up memory, slowing down (or crashing) your app.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Top 4 Memory Leak Culprits in JavaScript&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Forgotten Timers &amp;amp; Intervals&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Leak! setInterval keeps running even if component unmounts  &lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Still running...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="c1"&gt;// Fix: Always clear intervals  &lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;intervalId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;intervalId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Running...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stopTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalId&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;Gotcha:&lt;/strong&gt; Unmounted React components with active timers leak memory.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Stray Event Listeners&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Leak! Listener remains attached even if element is removed  &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;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="c1"&gt;// Fix: Remove listener when done  &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&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;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="c1"&gt;// Later...  &lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&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;Pro Tip:&lt;/strong&gt; In React, always clean up listeners in &lt;code&gt;useEffect&lt;/code&gt;’s return function.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Closures Holding References&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Leak! `bigData` is retained because of closure  &lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bigData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;💾&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Still holding bigData in memory!&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leakedFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;processData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
&lt;span class="c1"&gt;// `bigData` can't be GC'd as long as `leakedFn` exists  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 &lt;strong&gt;Fix:&lt;/strong&gt; Explicitly nullify large variables when done.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4. Detached DOM Nodes&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Leak! Removed DOM node still referenced in JS  &lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;detachedNode&lt;/span&gt; &lt;span class="o"&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;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;detachedNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="c1"&gt;// Later...  &lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;detachedNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="c1"&gt;// But `detachedNode` still exists in memory!  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Solution:&lt;/strong&gt; Set &lt;code&gt;detachedNode = null&lt;/code&gt; after removal.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How to Detect Memory Leaks?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;Chrome DevTools&lt;/strong&gt; → &lt;strong&gt;Memory tab&lt;/strong&gt;:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Take a Heap Snapshot&lt;/strong&gt; (Compare before/after actions)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Record Allocation Timeline&lt;/strong&gt; (Find retained objects)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check Performance Monitor&lt;/strong&gt; (Watch JS Heap size)
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices to Avoid Leaks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;🔹 &lt;strong&gt;Always clean up:&lt;/strong&gt; Timers, event listeners, subscriptions.&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Avoid global variables:&lt;/strong&gt; They never get garbage collected.&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Use WeakMap/WeakSet&lt;/strong&gt; for caches (auto-clears unused refs).&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Test with DevTools&lt;/strong&gt; in long-running sessions.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Memory leaks are sneaky but preventable. &lt;strong&gt;Always question:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
❓ &lt;em&gt;Is this object still needed?&lt;/em&gt;&lt;br&gt;&lt;br&gt;
❓ &lt;em&gt;Did I clean up all references?&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Catch them early, and your app will thank you!&lt;/strong&gt;  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What’s your worst memory leak story?&lt;/strong&gt; Let me know in the comments! 👇&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Liked this? Follow me for more JS deep dives!&lt;/strong&gt;  &lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>programming</category>
      <category>performance</category>
    </item>
    <item>
      <title>🔐 How to Connect Multiple GitHub Accounts via SSH in VS Code (Personal + Work Setup)</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Thu, 24 Apr 2025 18:05:39 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/how-to-connect-multiple-github-accounts-via-ssh-in-vs-code-personal-work-setup-4h2e</link>
      <guid>https://dev.to/muhammadaqib86/how-to-connect-multiple-github-accounts-via-ssh-in-vs-code-personal-work-setup-4h2e</guid>
      <description>&lt;p&gt;If you're juggling multiple GitHub accounts — like a &lt;strong&gt;personal&lt;/strong&gt; and a &lt;strong&gt;work&lt;/strong&gt; account — and using &lt;strong&gt;VS Code&lt;/strong&gt; as your primary editor, setting up SSH correctly will save you &lt;strong&gt;tons of authentication headaches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this guide, you'll learn how to &lt;strong&gt;connect GitHub via SSH in VS Code&lt;/strong&gt; using multiple profiles so you can push, pull, and clone from different GitHub accounts seamlessly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Why Use SSH with GitHub in VS Code?
&lt;/h2&gt;

&lt;p&gt;Using SSH instead of HTTPS allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid entering credentials or PATs every time&lt;/li&gt;
&lt;li&gt;Manage personal and work GitHub accounts side-by-side&lt;/li&gt;
&lt;li&gt;Enable smooth Git integration inside &lt;strong&gt;Visual Studio Code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Easily switch between multiple profiles using SSH config&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Generate SSH Keys for Personal and Work GitHub Accounts
&lt;/h2&gt;

&lt;p&gt;Open your terminal inside &lt;strong&gt;VS Code&lt;/strong&gt; and run:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔐 For personal GitHub:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"yourpersonal@email.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519_personal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔐 For work GitHub:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"yourwork@email.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519_work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates two key pairs, one for each account.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Step 2: Add SSH Keys to SSH Agent in VS Code Terminal
&lt;/h2&gt;

&lt;p&gt;Start the SSH agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ssh-agent &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add both keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add ~/.ssh/id_ed25519_personal
ssh-add ~/.ssh/id_ed25519_work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures VS Code and Git can use these keys for SSH authentication.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Step 3: Configure SSH Profiles for VS Code in &lt;code&gt;~/.ssh/config&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Open or create your SSH config file from VS Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code ~/.ssh/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# Personal GitHub
&lt;/span&gt;&lt;span class="err"&gt;Host&lt;/span&gt; &lt;span class="err"&gt;github-personal&lt;/span&gt;
  &lt;span class="err"&gt;HostName&lt;/span&gt; &lt;span class="err"&gt;github.com&lt;/span&gt;
  &lt;span class="err"&gt;User&lt;/span&gt; &lt;span class="err"&gt;git&lt;/span&gt;
  &lt;span class="err"&gt;IdentityFile&lt;/span&gt; &lt;span class="err"&gt;~/.ssh/id_ed25519_personal&lt;/span&gt;
  &lt;span class="err"&gt;IdentitiesOnly&lt;/span&gt; &lt;span class="err"&gt;yes&lt;/span&gt;

&lt;span class="c"&gt;# Work GitHub
&lt;/span&gt;&lt;span class="err"&gt;Host&lt;/span&gt; &lt;span class="err"&gt;github-work&lt;/span&gt;
  &lt;span class="err"&gt;HostName&lt;/span&gt; &lt;span class="err"&gt;github.com&lt;/span&gt;
  &lt;span class="err"&gt;User&lt;/span&gt; &lt;span class="err"&gt;git&lt;/span&gt;
  &lt;span class="err"&gt;IdentityFile&lt;/span&gt; &lt;span class="err"&gt;~/.ssh/id_ed25519_work&lt;/span&gt;
  &lt;span class="err"&gt;IdentitiesOnly&lt;/span&gt; &lt;span class="err"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔁 This tells Git and VS Code which key to use for which GitHub host.&lt;/p&gt;




&lt;h2&gt;
  
  
  🗝️ Step 4: Add Public Keys to GitHub
&lt;/h2&gt;

&lt;p&gt;Use these commands to get your public keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519_personal.pub
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519_work.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then go to each GitHub account → &lt;strong&gt;Settings → SSH and GPG Keys&lt;/strong&gt; → Add the corresponding key.&lt;/p&gt;

&lt;p&gt;✅ Now each GitHub account will recognize the right SSH identity.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Step 5: Test SSH Profiles in VS Code Terminal
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Personal:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github-personal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Work:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github-work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hi your-username! You've successfully authenticated...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Step 6: Clone Repositories via SSH in VS Code
&lt;/h2&gt;

&lt;p&gt;Inside VS Code:&lt;/p&gt;

&lt;h3&gt;
  
  
  Clone a &lt;strong&gt;personal&lt;/strong&gt; repo:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github-personal:your-username/personal-repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clone a &lt;strong&gt;work&lt;/strong&gt; repo:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github-work:org-name/work-repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VS Code will respect the SSH config and use the correct keys — no more login prompts or permission errors.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 Step 7: Update Existing Git Remotes in VS Code
&lt;/h2&gt;

&lt;p&gt;Already cloned with HTTPS? No worries!&lt;/p&gt;

&lt;p&gt;Use this inside your project terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote set-url origin git@github-work:org-name/work-repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you're fully synced and authenticated via SSH inside VS Code.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Bonus: Smooth Git Experience in VS Code
&lt;/h2&gt;

&lt;p&gt;After this setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can use the &lt;strong&gt;Source Control&lt;/strong&gt; panel in VS Code without any SSH issues&lt;/li&gt;
&lt;li&gt;You can commit, pull, and push with different GitHub accounts easily&lt;/li&gt;
&lt;li&gt;Git logs, diffs, and branches all work without password prompts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Recap: SSH Profiles for GitHub in VS Code
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create key&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ssh-keygen -f ~/.ssh/id_ed25519_name&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Add to agent&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ssh-add ~/.ssh/id_ed25519_name&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configure profile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.ssh/config&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clone&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git clone git@github-profile:org/repo.git&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use in VS Code&lt;/td&gt;
&lt;td&gt;Automatically handled ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;By setting up &lt;strong&gt;SSH keys with profiles&lt;/strong&gt; for personal and work accounts, and using them inside &lt;strong&gt;VS Code&lt;/strong&gt;, you unlock a powerful and smooth Git workflow — no more access issues, no more login fatigue 🔥&lt;/p&gt;




&lt;p&gt;Got stuck? Want help with GitHub SSO or SSH key authorization for organizations?&lt;br&gt;&lt;br&gt;
Drop a comment below — happy to help you get fully connected!&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>github</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Generate a PFX File for Azure App Service or Key Vault</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Tue, 22 Apr 2025 20:11:54 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/how-to-generate-a-pfx-file-for-azure-app-service-or-key-vault-53kk</link>
      <guid>https://dev.to/muhammadaqib86/how-to-generate-a-pfx-file-for-azure-app-service-or-key-vault-53kk</guid>
      <description>&lt;p&gt;If you're deploying a web app on &lt;strong&gt;Azure App Service&lt;/strong&gt; or managing certificates in &lt;strong&gt;Azure Key Vault&lt;/strong&gt;, you’ll likely need a &lt;strong&gt;.pfx file&lt;/strong&gt;—a secure container for your SSL certificate, private key, and optional certificate chain.  &lt;/p&gt;

&lt;p&gt;In this guide, we’ll walk through:&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Verifying your certificate and private key&lt;/strong&gt; (critical for avoiding mismatches)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Creating a .pfx file using OpenSSL&lt;/strong&gt; (with or without a chain)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Uploading to Azure App Service &amp;amp; Key Vault&lt;/strong&gt; (step-by-step)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Troubleshooting common issues&lt;/strong&gt; (like password-protected keys or chain errors)  &lt;/p&gt;

&lt;p&gt;Let’s get started.  &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before generating your &lt;code&gt;.pfx&lt;/code&gt;, ensure you have:  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Certificate file&lt;/strong&gt; (&lt;code&gt;.crt&lt;/code&gt; or &lt;code&gt;.pem&lt;/code&gt;) – Contains &lt;code&gt;-----BEGIN CERTIFICATE-----&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Private key&lt;/strong&gt; (&lt;code&gt;.key&lt;/code&gt; or &lt;code&gt;.txt&lt;/code&gt;) – Contains &lt;code&gt;-----BEGIN PRIVATE KEY-----&lt;/code&gt; or &lt;code&gt;-----BEGIN RSA PRIVATE KEY-----&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Optional chain file&lt;/strong&gt; (&lt;code&gt;.crt&lt;/code&gt; or &lt;code&gt;.pem&lt;/code&gt;) – Contains intermediate/root certificates&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;OpenSSL installed&lt;/strong&gt; (Linux/macOS/WSL or Windows via Git Bash)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Azure access&lt;/strong&gt; (to upload to App Service or Key Vault)  &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Step 1: Verify Your Files&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. Check the Private Key&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl rsa &lt;span class="nt"&gt;-in&lt;/span&gt; private.key &lt;span class="nt"&gt;-check&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RSA key ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see &lt;code&gt;Enter pass phrase&lt;/code&gt;, your key is password-protected—you’ll need it later.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Check the Certificate&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="nt"&gt;-in&lt;/span&gt; certificate.crt &lt;span class="nt"&gt;-text&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Common Name (CN)&lt;/strong&gt; or &lt;strong&gt;Subject Alternative Name (SAN)&lt;/strong&gt; matches your domain&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Expiration date&lt;/strong&gt; is valid  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Check the Certificate Chain (Optional)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="nt"&gt;-in&lt;/span&gt; bundle.crt &lt;span class="nt"&gt;-text&lt;/span&gt; &lt;span class="nt"&gt;-noout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should show multiple certificates (intermediate + root CA).  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Verify Private Key Matches Certificate&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-modulus&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; certificate.crt | openssl md5
openssl rsa &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-modulus&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; private.key | openssl md5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Both hashes must match.&lt;/strong&gt; If they don’t:&lt;br&gt;&lt;br&gt;
❌ Your private key doesn’t belong to this certificate&lt;br&gt;&lt;br&gt;
❌ Regenerate a &lt;strong&gt;CSR&lt;/strong&gt; and request a new certificate  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 2: Create the .pfx File&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Without Certificate Chain&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs12 &lt;span class="nt"&gt;-export&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; certificate.crt &lt;span class="nt"&gt;-inkey&lt;/span&gt; private.key &lt;span class="nt"&gt;-out&lt;/span&gt; certificate.pfx &lt;span class="nt"&gt;-passout&lt;/span&gt; pass:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-passout pass:&lt;/code&gt; → No password (Azure prefers this)
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;With Certificate Chain (Recommended)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs12 &lt;span class="nt"&gt;-export&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; certificate.crt &lt;span class="nt"&gt;-inkey&lt;/span&gt; private.key &lt;span class="nt"&gt;-out&lt;/span&gt; certificate.pfx &lt;span class="nt"&gt;-passout&lt;/span&gt; pass: &lt;span class="nt"&gt;-certfile&lt;/span&gt; bundle.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Includes intermediates for full SSL trust
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;If Private Key is Password-Protected&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs12 &lt;span class="nt"&gt;-export&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; certificate.crt &lt;span class="nt"&gt;-inkey&lt;/span&gt; private.key &lt;span class="nt"&gt;-passin&lt;/span&gt; pass:yourpassword &lt;span class="nt"&gt;-out&lt;/span&gt; certificate.pfx &lt;span class="nt"&gt;-passout&lt;/span&gt; pass:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Verify the .pfx File&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openssl pkcs12 &lt;span class="nt"&gt;-in&lt;/span&gt; certificate.pfx &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-info&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should list:&lt;br&gt;&lt;br&gt;
✔ Certificate&lt;br&gt;&lt;br&gt;
✔ Private key&lt;br&gt;&lt;br&gt;
✔ Chain (if included)  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 3: Upload to Azure App Service&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Go to&lt;/strong&gt; App Service → &lt;strong&gt;TLS/SSL settings&lt;/strong&gt; → &lt;strong&gt;Private Key Certificates&lt;/strong&gt; → &lt;strong&gt;Upload Certificate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Select&lt;/strong&gt; &lt;code&gt;certificate.pfx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave password blank&lt;/strong&gt; (if using &lt;code&gt;-passout pass:&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add SSL Binding&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;TLS/SSL bindings&lt;/strong&gt; → &lt;strong&gt;Add TLS/SSL Binding&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select your domain
&lt;/li&gt;
&lt;li&gt;Choose the uploaded certificate
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;SNI SSL&lt;/strong&gt; (or IP SSL if needed)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 4: Upload to Azure Key Vault (Optional)&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Import Certificate&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az keyvault certificate import &lt;span class="nt"&gt;--vault-name&lt;/span&gt; &lt;span class="s2"&gt;"MyKeyVault"&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"MyCertificate"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; certificate.pfx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;No password needed (if &lt;code&gt;-passout pass:&lt;/code&gt; was used)
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Grant App Service Access&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enable Managed Identity&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;App Service → &lt;strong&gt;Identity&lt;/strong&gt; → &lt;strong&gt;System assigned&lt;/strong&gt; → &lt;strong&gt;On&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grant Key Vault Permissions&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Key Vault → &lt;strong&gt;Access policies&lt;/strong&gt; → &lt;strong&gt;Add&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Get&lt;/strong&gt; for &lt;strong&gt;Secrets&lt;/strong&gt; and &lt;strong&gt;Certificates&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Assign to your App Service identity
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reference in App Service&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;App Service → &lt;strong&gt;TLS/SSL settings&lt;/strong&gt; → &lt;strong&gt;Private Key Certificates&lt;/strong&gt; → &lt;strong&gt;Import Key Vault Certificate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select your Key Vault and certificate
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 5: Verify SSL&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ &lt;strong&gt;Visit&lt;/strong&gt; &lt;code&gt;https://yourdomain.com&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Use&lt;/strong&gt; &lt;a href="https://www.sslshopper.com/ssl-checker.html" rel="noopener noreferrer"&gt;SSL Shopper&lt;/a&gt; to confirm:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certificate validity
&lt;/li&gt;
&lt;li&gt;Chain completeness
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Troubleshooting&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key mismatch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Regenerate CSR and request a new certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Password-protected key&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;-passin pass:yourpassword&lt;/code&gt; in OpenSSL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser SSL warnings&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ensure chain file is included in &lt;code&gt;.pfx&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App Service errors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Confirm CN/SAN matches domain&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Generating a &lt;code&gt;.pfx&lt;/code&gt; file for Azure is straightforward with OpenSSL. Key takeaways:&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Always verify&lt;/strong&gt; certificate + private key match (&lt;code&gt;openssl md5&lt;/code&gt; check)&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;Include the chain&lt;/strong&gt; to avoid browser trust issues&lt;br&gt;&lt;br&gt;
🔹 &lt;strong&gt;No password&lt;/strong&gt; = smoother Azure integration  &lt;/p&gt;

&lt;p&gt;Need help? Drop a comment below! 🚀  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Improve Your Keyboard Typing Speed and Accuracy — A Developer’s Guide</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Tue, 22 Apr 2025 18:04:46 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/how-to-improve-your-keyboard-typing-speed-and-accuracy-a-developers-guide-2nm6</link>
      <guid>https://dev.to/muhammadaqib86/how-to-improve-your-keyboard-typing-speed-and-accuracy-a-developers-guide-2nm6</guid>
      <description>&lt;p&gt;Whether you're a developer, writer, or knowledge worker, typing is one of the most fundamental—yet overlooked—skills in your workflow. Most people never think to improve it, despite the fact that a small increase in speed and accuracy can save hours per week, reduce mental fatigue, and keep you in a state of deep focus.  &lt;/p&gt;

&lt;p&gt;In this post, we’ll break down &lt;strong&gt;evidence-backed techniques, tools, and habits&lt;/strong&gt; to help you type faster, with fewer errors, and without compromising long-term comfort.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Typing Speed Actually Matters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Consider this: If you type &lt;strong&gt;60 words per minute (WPM)&lt;/strong&gt; and increase that to &lt;strong&gt;90 WPM&lt;/strong&gt;, you’re effectively working &lt;strong&gt;50% faster&lt;/strong&gt;—whether you’re writing code, drafting emails, or documenting processes.  &lt;/p&gt;

&lt;p&gt;The benefits compound over time:&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Fewer interruptions&lt;/strong&gt; (less backspacing, fewer corrections)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Better flow state&lt;/strong&gt; (no mental context-switching to fix typos)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Reduced strain&lt;/strong&gt; (efficient typing means less unnecessary movement)  &lt;/p&gt;

&lt;p&gt;If you spend hours at a keyboard daily, even a &lt;strong&gt;10-20% improvement&lt;/strong&gt; can reclaim weeks of productivity per year.  &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;How to Systematically Improve Your Typing&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. Master Touch Typing (If You Haven’t Already)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Touch typing—typing without looking at the keyboard—relies on muscle memory rather than visual feedback.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it’s worth relearning:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps your focus on the screen, not the keys
&lt;/li&gt;
&lt;li&gt;Reduces cognitive load (your fingers "know" where to go)
&lt;/li&gt;
&lt;li&gt;Enables consistent rhythm and speed
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tools to train effectively:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.keybr.com" rel="noopener noreferrer"&gt;Keybr&lt;/a&gt; (adaptive learning)
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.typingclub.com" rel="noopener noreferrer"&gt;TypingClub&lt;/a&gt; (structured lessons)
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ratatype.com" rel="noopener noreferrer"&gt;Ratatype&lt;/a&gt; (good for beginners)
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;2. Optimize Finger Placement&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The standard &lt;strong&gt;home row&lt;/strong&gt; position:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Left hand: A S D F  
Right hand: J K L ;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Thumbs rest on the &lt;strong&gt;spacebar&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Each finger covers specific nearby keys
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key habit:&lt;/strong&gt; Return to home row between words to maintain efficiency.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Practice Deliberately (10-15 Minutes/Day)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Consistency matters more than marathon sessions. Use tools that provide &lt;strong&gt;real-time feedback&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://monkeytype.com" rel="noopener noreferrer"&gt;Monkeytype&lt;/a&gt; (minimalist, customizable, includes &lt;strong&gt;code mode&lt;/strong&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://play.typeracer.com" rel="noopener noreferrer"&gt;TypeRacer&lt;/a&gt; (competitive typing)
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://typing.io" rel="noopener noreferrer"&gt;Typing.io&lt;/a&gt; (practice with real code snippets)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Realistic benchmarks:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;60+ WPM&lt;/strong&gt; → Solid for general work
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;80+ WPM&lt;/strong&gt; → Professional-level efficiency
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100+ WPM&lt;/strong&gt; → Elite speed (useful for transcription, fast-paced workflows)
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4. Train with Real-World Material&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Typing random words isn’t enough—practice with content from your actual work:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt;: Code snippets, CLI commands, documentation
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writers&lt;/strong&gt;: Articles, emails, notes
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;General use&lt;/strong&gt;: Frequently used phrases, industry terms
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Use Monkeytype’s &lt;strong&gt;"Code" mode&lt;/strong&gt; or Typing.io to simulate real work scenarios.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;5. Use the Right Keyboard Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Hardware impacts speed and comfort more than most realize.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key considerations:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Key travel &amp;amp; spacing&lt;/strong&gt; (mechanical keyboards help with tactile feedback)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Wrist posture&lt;/strong&gt; (avoid resting wrists on the desk; float instead)&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Tilt angle&lt;/strong&gt; (slight negative tilt reduces strain)  &lt;/p&gt;

&lt;p&gt;If you type for long hours, consider &lt;strong&gt;ergonomic or split keyboards&lt;/strong&gt;.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;6. Break Bad Habits&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Common inefficiencies:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hunting-and-pecking&lt;/strong&gt; (using only a few fingers)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excessive backspacing&lt;/strong&gt; (due to poor accuracy)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Looking down at the keyboard&lt;/strong&gt; (breaks focus)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Slow down, prioritize &lt;strong&gt;accuracy first&lt;/strong&gt;, then gradually increase speed.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;7. Track Progress to Stay Motivated&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Improvement is easier when you measure it. Tools like:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://keybr.com" rel="noopener noreferrer"&gt;Keybr&lt;/a&gt; (tracks WPM and error rate over time)
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://monkeytype.com" rel="noopener noreferrer"&gt;Monkeytype&lt;/a&gt; (logs session history)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Reduce error rate below &lt;strong&gt;5%&lt;/strong&gt; while steadily increasing speed.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;8. Apply Skills in Real Work&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Practice alone isn’t enough—&lt;strong&gt;integrate better typing into daily tasks&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write emails/docs without looking at the keyboard
&lt;/li&gt;
&lt;li&gt;Force yourself to use correct finger placement while coding
&lt;/li&gt;
&lt;li&gt;Temporarily disable autocomplete for deliberate practice
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to make efficient typing &lt;strong&gt;automatic&lt;/strong&gt;, so your brain can focus on &lt;strong&gt;thinking&lt;/strong&gt;, not typing.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Long-Term Health and Ergonomics&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Typing faster shouldn’t come at the cost of comfort.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best practices:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the &lt;strong&gt;20-20-20 rule&lt;/strong&gt; (every 20 minutes, look 20 feet away for 20 seconds)
&lt;/li&gt;
&lt;li&gt;Stretch hands and wrists regularly
&lt;/li&gt;
&lt;li&gt;Use an ergonomic chair and desk setup
&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;split keyboards&lt;/strong&gt; if you experience strain
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Final Thoughts: A High-ROI Skill&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Unlike many productivity hacks, improving typing speed requires &lt;strong&gt;no subscriptions, no complex systems&lt;/strong&gt;—just &lt;strong&gt;focused practice and better habits&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;The payoff?&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;More efficient workflows&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Less mental fatigue&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Hours saved per week&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;If you spend 4+ hours a day typing, even a &lt;strong&gt;10% improvement&lt;/strong&gt; is worth the effort.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What’s Your Experience?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Do you have a preferred typing tool or technique? Share your thoughts in the comments—let’s discuss what works (and what doesn’t).&lt;/p&gt;

</description>
      <category>keyboard</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>⚡ Typing Hacks for Programmers: Code Faster, Smarter, and with Less Effort</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Tue, 22 Apr 2025 17:46:17 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/typing-hacks-for-programmers-code-faster-smarter-and-with-less-effort-4kd</link>
      <guid>https://dev.to/muhammadaqib86/typing-hacks-for-programmers-code-faster-smarter-and-with-less-effort-4kd</guid>
      <description>&lt;p&gt;As developers, we spend a &lt;strong&gt;huge chunk of our lives typing&lt;/strong&gt; — code, comments, commits, commands, configs... the list goes on.&lt;/p&gt;

&lt;p&gt;Yet, many of us don’t invest in improving the one skill that can &lt;strong&gt;instantly boost productivity, reduce fatigue&lt;/strong&gt;, and help us &lt;strong&gt;flow like a boss&lt;/strong&gt;: efficient typing.&lt;/p&gt;

&lt;p&gt;In this post, let’s dive into some &lt;strong&gt;practical typing hacks for programmers&lt;/strong&gt; — from tooling to habits — that can help you code &lt;strong&gt;faster, smarter, and smoother&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 1. &lt;strong&gt;Master Your IDE Shortcuts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Your code editor or IDE is your second home (or first, let’s be honest). Learning the keyboard shortcuts can literally save you &lt;strong&gt;hours every week&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;✅ Learn these essentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Duplicate line&lt;/strong&gt; – (e.g. &lt;code&gt;Cmd + D&lt;/code&gt; / &lt;code&gt;Ctrl + D&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Move line up/down&lt;/strong&gt; – (e.g. &lt;code&gt;Alt + ↑/↓&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Auto-format code&lt;/strong&gt; – (e.g. &lt;code&gt;Shift + Alt + F&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Quick file search&lt;/strong&gt; – (e.g. &lt;code&gt;Cmd + P&lt;/code&gt; / &lt;code&gt;Ctrl + P&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Command palette&lt;/strong&gt; – (e.g. &lt;code&gt;Cmd + Shift + P&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔗 Bonus: &lt;a href="https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf" rel="noopener noreferrer"&gt;VS Code Keyboard Shortcuts Cheatsheet&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⌨️ 2. &lt;strong&gt;Use a Programmer-Friendly Keyboard Layout&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’re writing code all day, your keyboard layout matters!&lt;/p&gt;

&lt;p&gt;🔁 Consider switching to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Colemak&lt;/strong&gt; – More natural typing flow, less finger movement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dvorak for Programmers&lt;/strong&gt; – Prioritizes symbols like &lt;code&gt;{}&lt;/code&gt;, &lt;code&gt;[]&lt;/code&gt;, &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;=&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QWERTY (but optimized)&lt;/strong&gt; – With remaps for &lt;code&gt;Esc&lt;/code&gt;, &lt;code&gt;CapsLock&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools like &lt;a href="https://karabiner-elements.pqrs.org/" rel="noopener noreferrer"&gt;Karabiner Elements (Mac)&lt;/a&gt; or &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;AutoHotkey (Windows)&lt;/a&gt; help remap keys like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CapsLock → Ctrl or Esc&lt;/li&gt;
&lt;li&gt;Shift + Space → insert &lt;code&gt;=&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 3. &lt;strong&gt;Practice Touch Typing (with a Programming Focus)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Even if you already type decently fast, improving your &lt;strong&gt;accuracy and muscle memory for code&lt;/strong&gt; can be a game-changer.&lt;/p&gt;

&lt;p&gt;🛠️ Use these to level up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.keybr.com/" rel="noopener noreferrer"&gt;Keybr&lt;/a&gt; – great for general typing&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://monkeytype.com/" rel="noopener noreferrer"&gt;monkeytype.com&lt;/a&gt; – includes &lt;strong&gt;programming language modes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://typing.io/" rel="noopener noreferrer"&gt;Typing.io&lt;/a&gt; – real-world code typing in JS, Python, C++, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Target: &lt;strong&gt;70+ WPM&lt;/strong&gt; with 95%+ accuracy while coding&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ✍️ 4. &lt;strong&gt;Snippets Are Your Superpower&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Why type the same code 100 times when you can &lt;strong&gt;auto-expand it in seconds&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;✅ Use &lt;strong&gt;code snippets&lt;/strong&gt; for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Component templates&lt;/li&gt;
&lt;li&gt;Boilerplate code&lt;/li&gt;
&lt;li&gt;Reusable logic blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🧩 Tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code’s built-in snippet manager&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://emmet.io/" rel="noopener noreferrer"&gt;Emmet&lt;/a&gt; – HTML &amp;amp; CSS shortcuts like &lt;code&gt;div.container&amp;gt;ul&amp;gt;li*5&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Trigger: log&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$1&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;h2&gt;
  
  
  🚀 5. &lt;strong&gt;Use Auto-completion and Copilot Wisely&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let your tools &lt;strong&gt;complete your thoughts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🧠 Tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tabnine&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IntelliSense&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Amazon Q&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...can auto-suggest entire lines, functions, or docstrings. But don’t just &lt;strong&gt;tab your way to spaghetti&lt;/strong&gt; — always review what gets inserted.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ 6. &lt;strong&gt;Remap &amp;amp; Streamline&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Remap underused keys:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CapsLock&lt;/code&gt; → &lt;code&gt;Ctrl&lt;/code&gt; (great for Vim or terminal)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Right Alt&lt;/code&gt; → Emoji picker / code symbols&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tab&lt;/code&gt; → Insert arrow functions like &lt;code&gt;()=&amp;gt;{}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create your own key combos:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;With &lt;strong&gt;AutoHotkey&lt;/strong&gt; (Windows) or &lt;strong&gt;Karabiner (Mac)&lt;/strong&gt;, you can map:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Alt + L&lt;/code&gt; → &lt;code&gt;console.log();&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Shift + B&lt;/code&gt; → trigger build command&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧘‍♂️ 7. &lt;strong&gt;Prevent Typing Fatigue&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Typing fast is great — but not at the cost of your hands or wrists.&lt;/p&gt;

&lt;p&gt;✅ Take care of your body:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an &lt;strong&gt;ergonomic keyboard&lt;/strong&gt; (like Kinesis, Moonlander, or split keyboards)&lt;/li&gt;
&lt;li&gt;Use a &lt;strong&gt;vertical mouse&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Keep &lt;strong&gt;good posture&lt;/strong&gt; (arms at 90°, wrists straight)&lt;/li&gt;
&lt;li&gt;Use the &lt;strong&gt;Pomodoro technique&lt;/strong&gt; with short stretch breaks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌐 8. &lt;strong&gt;Use Browser Extensions for Snippets &amp;amp; Shortcuts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you’re a web dev:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Text Blaze (Chrome)&lt;/strong&gt; for auto-expanding text in the browser&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Tampermonkey&lt;/strong&gt; to automate typing or field entry in dev portals&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;!important&lt;/code&gt; browser bookmarks like:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;javascript:document.body.contentEditable='true';document.designMode='on';void 0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✨ 9. &lt;strong&gt;Master the Terminal with Aliases &amp;amp; Autocomplete&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you're a CLI lover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt; aliases like:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git status'&lt;/span&gt;
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;serve&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'npx serve'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable &lt;strong&gt;autocomplete for Git, Docker, etc.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://github.com/junegunn/fzf" rel="noopener noreferrer"&gt;fzf&lt;/a&gt; for fuzzy searching file paths&lt;/li&gt;
&lt;li&gt;Try &lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh My Zsh&lt;/a&gt; for power-boosted shell workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 10. &lt;strong&gt;Bonus: Try a Mechanical Keyboard with Programmable Layers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Mechanical keyboards like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⌨️ Keychron&lt;/li&gt;
&lt;li&gt;⌨️ Ducky&lt;/li&gt;
&lt;li&gt;⌨️ Drop ALT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…allow for &lt;strong&gt;custom layouts&lt;/strong&gt;, macros, and even &lt;strong&gt;per-key RGB triggers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pair them with firmware like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QMK / VIA for remapping&lt;/li&gt;
&lt;li&gt;Tap to insert code blocks, templates, emoji, or even open GitHub!&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Typing isn’t just about words per minute — it’s about &lt;strong&gt;efficiency&lt;/strong&gt;, &lt;strong&gt;comfort&lt;/strong&gt;, and &lt;strong&gt;flow&lt;/strong&gt;. Whether you're building full-stack apps or debugging a pesky issue at 2 AM, these hacks can help you &lt;strong&gt;type less but achieve more&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  💬 What’s Your Favorite Typing Hack?
&lt;/h3&gt;

&lt;p&gt;Got a tool, layout, or ritual that supercharges your typing game? Share it in the comments below 👇&lt;br&gt;&lt;br&gt;
Let’s build a typing toolbox for devs together!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>keyboard</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>🔥 10 Common JavaScript Pitfalls That Even Experienced Developers Fall Into</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Sun, 20 Apr 2025 15:44:40 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/10-common-javascript-pitfalls-that-even-experienced-developers-fall-into-4bb3</link>
      <guid>https://dev.to/muhammadaqib86/10-common-javascript-pitfalls-that-even-experienced-developers-fall-into-4bb3</guid>
      <description>&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; is an incredibly powerful and flexible language — but that flexibility comes with a price: subtle quirks and gotchas that even seasoned developers stumble into.&lt;/p&gt;

&lt;p&gt;Whether you're building enterprise applications or working on your next side project, these are the &lt;strong&gt;10 most common JavaScript pitfalls&lt;/strong&gt; that can cause unexpected behavior, bugs, or even security vulnerabilities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 This post will help you &lt;strong&gt;identify, understand, and avoid&lt;/strong&gt; these common traps, and write cleaner, safer, and more predictable code.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🚫 1. &lt;strong&gt;Confusing &lt;code&gt;==&lt;/code&gt; vs &lt;code&gt;===&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;==&lt;/code&gt; operator performs &lt;strong&gt;type coercion&lt;/strong&gt;, while &lt;code&gt;===&lt;/code&gt; checks for &lt;strong&gt;strict equality&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;   &lt;span class="c1"&gt;// true 😱&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;  &lt;span class="c1"&gt;// false ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Always use &lt;code&gt;===&lt;/code&gt; unless you &lt;strong&gt;really&lt;/strong&gt; understand coercion rules.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧠 2. &lt;strong&gt;Using &lt;code&gt;var&lt;/code&gt; Instead of &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;var&lt;/code&gt; is function-scoped and hoisted, which can lead to unpredictable behavior.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3, 3, 3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; to get block-scoped, predictable results.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌀 3. &lt;strong&gt;Misunderstanding Asynchronous Behavior&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;JavaScript’s async nature can be tricky:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Doesn't wait!&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="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Always &lt;code&gt;await&lt;/code&gt; async functions, and remember &lt;code&gt;await&lt;/code&gt; can only be used inside &lt;code&gt;async&lt;/code&gt; functions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧨 4. &lt;strong&gt;Modifying Objects/Arrays by Reference&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Objects and arrays are &lt;strong&gt;reference types&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 2 ❗&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🛡 Use &lt;code&gt;structuredClone&lt;/code&gt;, spread (&lt;code&gt;{ ...a }&lt;/code&gt;), or libraries like Lodash for immutability.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔁 5. &lt;strong&gt;Incorrect &lt;code&gt;for...in&lt;/code&gt; vs &lt;code&gt;for...of&lt;/code&gt; Usage&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;for...in&lt;/code&gt; is for &lt;strong&gt;object keys&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for...of&lt;/code&gt; is for &lt;strong&gt;iterables like arrays&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "0", "1", "2"&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "a", "b", "c"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧮 6. &lt;strong&gt;Floating Point Math Woes&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt; &lt;span class="c1"&gt;// false 😤&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Use libraries like &lt;code&gt;decimal.js&lt;/code&gt; or work with integers when precision matters (e.g. cents instead of dollars).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📦 7. &lt;strong&gt;Leaking Variables to Global Scope&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In browsers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;leakedVar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;oops&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 👻 becomes global&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Always declare variables with &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;const&lt;/code&gt;, or &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🗂️ 8. &lt;strong&gt;Overusing &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; Interchangeably&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;        &lt;span class="c1"&gt;// "object" 😬&lt;/span&gt;
&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;   &lt;span class="c1"&gt;// "undefined"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 Use one consistently in your app. Many devs use &lt;code&gt;null&lt;/code&gt; for “intentional empty” and &lt;code&gt;undefined&lt;/code&gt; for “not set”.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧪 9. &lt;strong&gt;Not Handling Errors in Async Code&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Uncaught promise errors can crash your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// No `.catch()` 😵&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ Always add &lt;code&gt;.catch()&lt;/code&gt; or wrap in &lt;code&gt;try/catch&lt;/code&gt; with &lt;code&gt;async/await&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧵 10. &lt;strong&gt;Assuming JavaScript is Single-threaded (Hint: It's not entirely)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;JS &lt;strong&gt;has one main thread&lt;/strong&gt;, but async tasks like &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;setTimeout&lt;/code&gt;, and event listeners use the &lt;strong&gt;event loop&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤯 Misunderstanding this can lead to race conditions or unhandled state updates in frameworks like React or Vue.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ✅ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;JavaScript is powerful — but with great power comes great... &lt;code&gt;undefined&lt;/code&gt;. 🕸️&lt;/p&gt;

&lt;p&gt;Avoiding these common pitfalls will make your code &lt;strong&gt;more maintainable, more secure&lt;/strong&gt;, and way easier for others (and your future self) to read.&lt;/p&gt;




&lt;h3&gt;
  
  
  💬 Have you encountered any of these? Got your own JavaScript “gotchas” to share?
&lt;/h3&gt;

&lt;p&gt;Drop them in the comments below 👇&lt;br&gt;&lt;br&gt;
Let’s help each other write better JS 💪&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Bulk Delete GitHub Actions Artifacts with a Simple Script (MacOS Guide)</title>
      <dc:creator>Muhammad Aqib Bin Azam</dc:creator>
      <pubDate>Sun, 20 Apr 2025 15:34:52 +0000</pubDate>
      <link>https://dev.to/muhammadaqib86/how-to-bulk-delete-github-actions-artifacts-with-a-simple-script-macos-guide-38bh</link>
      <guid>https://dev.to/muhammadaqib86/how-to-bulk-delete-github-actions-artifacts-with-a-simple-script-macos-guide-38bh</guid>
      <description>&lt;p&gt;If you're using GitHub Actions, you know how quickly artifacts can accumulate and consume your storage quota. In this post, I'll show you how to clean up all your GitHub Actions artifacts across all repositories with a simple bash script - no manual deletion required!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Delete GitHub Actions Artifacts?
&lt;/h2&gt;

&lt;p&gt;GitHub Actions artifacts are great for storing build outputs and test results, but they come with some limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Storage limits&lt;/strong&gt;: Free accounts get only 500MB of artifact storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retention period&lt;/strong&gt;: Artifacts expire after 90 days by default&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost concerns&lt;/strong&gt;: Excess storage can lead to charges for pro accounts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regular cleanup helps you:&lt;br&gt;
✅ Stay under storage limits&lt;br&gt;&lt;br&gt;
✅ Improve repository performance&lt;br&gt;&lt;br&gt;
✅ Maintain better organization  &lt;/p&gt;
&lt;h2&gt;
  
  
  The Automated Solution
&lt;/h2&gt;

&lt;p&gt;Instead of manually deleting artifacts through the UI, we'll use GitHub's CLI (&lt;code&gt;gh&lt;/code&gt;) with a Python helper to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find all repositories you have access to
&lt;/li&gt;
&lt;li&gt;List all artifacts
&lt;/li&gt;
&lt;li&gt;Delete them in bulk
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before running the script, ensure you have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub CLI&lt;/strong&gt; installed and authenticated:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;gh
gh auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;(Make sure &lt;code&gt;repo&lt;/code&gt; scope is enabled - check with &lt;code&gt;gh auth status&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Python 3.13.2&lt;/strong&gt; (or compatible version):
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Install if needed:&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;python@3.13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;zsh shell&lt;/strong&gt; (default on modern MacOS)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  The Script Setup
&lt;/h2&gt;

&lt;p&gt;Create a new file called &lt;code&gt;delete-all-artifacts.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Script to delete artifacts from all accessible repositories&lt;/span&gt;
&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YOUR_USERNAME"&lt;/span&gt;  &lt;span class="c"&gt;# Replace with your GitHub username&lt;/span&gt;

&lt;span class="c"&gt;# Fetch all repos with write/admin access&lt;/span&gt;
&lt;span class="nv"&gt;REPOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gh api /user/repos&lt;span class="se"&gt;\?&lt;/span&gt;&lt;span class="nv"&gt;affiliation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;owner,collaborator,organization_member &lt;span class="nt"&gt;--paginate&lt;/span&gt; | python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import sys, json; repos = json.load(sys.stdin); [print(repo['full_name']) for repo in repos if repo['permissions']['admin'] or repo['permissions']['push']]"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;REPO &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$REPOS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Processing repository: &lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="c"&gt;# Optional: List recent workflow runs&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Listing recent workflow runs for &lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  gh run list &lt;span class="nt"&gt;--repo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--limit&lt;/span&gt; 5 &lt;span class="nt"&gt;--json&lt;/span&gt; databaseId,status,conclusion

  &lt;span class="c"&gt;# Delete all artifacts&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Deleting artifacts for &lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;ARTIFACT_IDS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gh api /repos/&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;/actions/artifacts &lt;span class="nt"&gt;--paginate&lt;/span&gt; | python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import sys, json; artifacts = json.load(sys.stdin)['artifacts']; print('Found ' + str(len(artifacts)) + ' artifacts'); [print(artifact['id']) for artifact in artifacts]"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ARTIFACT_IDS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"No artifacts to delete"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ARTIFACT_IDS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; +2 | xargs &lt;span class="nt"&gt;-n1&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt; % bash &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"gh api -X DELETE /repos/&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/actions/artifacts/% &amp;amp;&amp;amp; sleep 1"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x delete-all-artifacts.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Repository Discovery&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finds all repos where you have push/admin rights
&lt;/li&gt;
&lt;li&gt;Includes personal, collaborator, and organization repos
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Artifact Deletion&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lists artifacts for each repository
&lt;/li&gt;
&lt;li&gt;Deletes them one by one with a 1-second delay (avoids rate limiting)
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Progress Reporting&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shows which repository is being processed
&lt;/li&gt;
&lt;li&gt;Reports number of artifacts found and deleted
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Running the Script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./delete-all-artifacts.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Expected Output
&lt;/h3&gt;

&lt;p&gt;You'll see output like this for each repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Processing repository: username/repo-name
Listing recent workflow runs for username/repo-name
[]
Deleting artifacts for username/repo-name
Found 2 artifacts
123
124
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting Tips
&lt;/h2&gt;

&lt;p&gt;If you encounter issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Python Syntax Errors&lt;/strong&gt;: Verify the script contents match exactly what's shown above
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission Problems&lt;/strong&gt;: Run &lt;code&gt;gh auth refresh -h github.com -s repo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiting&lt;/strong&gt;: Increase the &lt;code&gt;sleep 1&lt;/code&gt; to &lt;code&gt;sleep 2&lt;/code&gt; if needed
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test First&lt;/strong&gt;: Try on a single repo before bulk deletion:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   gh api /repos/username/repo-name/actions/artifacts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Important Notes
&lt;/h2&gt;

&lt;p&gt;⚠️ &lt;strong&gt;This cannot be undone&lt;/strong&gt; - deleted artifacts are permanently removed&lt;br&gt;&lt;br&gt;
⏳ &lt;strong&gt;Takes time&lt;/strong&gt; for repositories with many artifacts&lt;br&gt;&lt;br&gt;
🔒 &lt;strong&gt;Only affects repos&lt;/strong&gt; where you have write/admin permissions  &lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Approach
&lt;/h2&gt;

&lt;p&gt;For more control, you might want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add filters to keep certain artifacts
&lt;/li&gt;
&lt;li&gt;Set up a scheduled job to run this monthly
&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="https://github.com/actions/artifacts-cleanup" rel="noopener noreferrer"&gt;actions/artifacts-cleanup&lt;/a&gt; action
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have you struggled with artifact storage before? Let me know in the comments if you'd like a version of this script with more advanced filtering options!&lt;/p&gt;

</description>
      <category>github</category>
      <category>devops</category>
      <category>automation</category>
      <category>githubactions</category>
    </item>
  </channel>
</rss>
